Wed Mar 30 16:25:41 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
[deliverable/binutils-gdb.git] / bfd / i386lynx.c
1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #define BYTES_IN_WORD 4
21 #define ARCH 32
22 #define N_SHARED_LIB(x) 0
23
24 #define TEXT_START_ADDR 0
25 #define PAGE_SIZE 4096
26 #define SEGMENT_SIZE PAGE_SIZE
27 #define DEFAULT_ARCH bfd_arch_i386
28
29 #define MY(OP) CAT(i386lynx_aout_,OP)
30 #define TARGETNAME "a.out-i386-lynx"
31
32 #include "bfd.h"
33 #include "sysdep.h"
34 #include "libbfd.h"
35
36 #ifndef WRITE_HEADERS
37 #define WRITE_HEADERS(abfd, execp) \
38 { \
39 bfd_size_type text_size; /* dummy vars */ \
40 file_ptr text_end; \
41 if (adata(abfd).magic == undecided_magic) \
42 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
43 \
44 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
45 execp->a_entry = bfd_get_start_address (abfd); \
46 \
47 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
48 obj_reloc_entry_size (abfd)); \
49 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
50 obj_reloc_entry_size (abfd)); \
51 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
52 \
53 bfd_seek (abfd, (file_ptr) 0, SEEK_SET); \
54 bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); \
55 /* Now write out reloc info, followed by syms and strings */ \
56 \
57 if (bfd_get_symcount (abfd) != 0) \
58 { \
59 bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET); \
60 \
61 if (! NAME(aout,write_syms)(abfd)) return false; \
62 \
63 bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET); \
64 \
65 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) return false; \
66 bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET); \
67 \
68 if (!NAME(lynx,squirt_out_relocs)(abfd, obj_datasec (abfd))) return false; \
69 } \
70 }
71 #endif
72
73 #include "libaout.h"
74 #include "aout/aout64.h"
75
76 #ifdef HOST_LYNX
77
78 char *lynx_core_file_failing_command ();
79 int lynx_core_file_failing_signal ();
80 boolean lynx_core_file_matches_executable_p ();
81 bfd_target *lynx_core_file_p ();
82
83 #define MY_core_file_failing_command lynx_core_file_failing_command
84 #define MY_core_file_failing_signal lynx_core_file_failing_signal
85 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
86 #define MY_core_file_p lynx_core_file_p
87
88 #endif /* HOST_LYNX */
89 \f
90
91 #define KEEPIT flags
92
93 extern reloc_howto_type aout_32_ext_howto_table[];
94 extern reloc_howto_type aout_32_std_howto_table[];
95
96 /* Standard reloc stuff */
97 /* Output standard relocation information to a file in target byte order. */
98
99 void
100 NAME (lynx, swap_std_reloc_out) (abfd, g, natptr)
101 bfd *abfd;
102 arelent *g;
103 struct reloc_std_external *natptr;
104 {
105 int r_index;
106 asymbol *sym = *(g->sym_ptr_ptr);
107 int r_extern;
108 unsigned int r_length;
109 int r_pcrel;
110 int r_baserel, r_jmptable, r_relative;
111 unsigned int r_addend;
112 asection *output_section = sym->section->output_section;
113
114 PUT_WORD (abfd, g->address, natptr->r_address);
115
116 r_length = g->howto->size; /* Size as a power of two */
117 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
118 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
119 r_baserel = 0;
120 r_jmptable = 0;
121 r_relative = 0;
122
123 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
124
125 /* name was clobbered by aout_write_syms to be symbol index */
126
127 /* If this relocation is relative to a symbol then set the
128 r_index to the symbols index, and the r_extern bit.
129
130 Absolute symbols can come in in two ways, either as an offset
131 from the abs section, or as a symbol which has an abs value.
132 check for that here
133 */
134
135
136 if (bfd_is_com_section (output_section)
137 || output_section == &bfd_abs_section
138 || output_section == &bfd_und_section)
139 {
140 if (bfd_abs_section.symbol == sym)
141 {
142 /* Whoops, looked like an abs symbol, but is really an offset
143 from the abs section */
144 r_index = 0;
145 r_extern = 0;
146 }
147 else
148 {
149 /* Fill in symbol */
150 r_extern = 1;
151 r_index = stoi ((*(g->sym_ptr_ptr))->KEEPIT);
152
153 }
154 }
155 else
156 {
157 /* Just an ordinary section */
158 r_extern = 0;
159 r_index = output_section->target_index;
160 }
161
162 /* now the fun stuff */
163 if (abfd->xvec->header_byteorder_big_p != false)
164 {
165 natptr->r_index[0] = r_index >> 16;
166 natptr->r_index[1] = r_index >> 8;
167 natptr->r_index[2] = r_index;
168 natptr->r_type[0] =
169 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
170 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
171 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
172 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
173 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
174 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
175 }
176 else
177 {
178 natptr->r_index[2] = r_index >> 16;
179 natptr->r_index[1] = r_index >> 8;
180 natptr->r_index[0] = r_index;
181 natptr->r_type[0] =
182 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
183 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
184 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
185 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
186 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
187 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
188 }
189 }
190
191
192 /* Extended stuff */
193 /* Output extended relocation information to a file in target byte order. */
194
195 void
196 NAME (lynx, swap_ext_reloc_out) (abfd, g, natptr)
197 bfd *abfd;
198 arelent *g;
199 register struct reloc_ext_external *natptr;
200 {
201 int r_index;
202 int r_extern;
203 unsigned int r_type;
204 unsigned int r_addend;
205 asymbol *sym = *(g->sym_ptr_ptr);
206 asection *output_section = sym->section->output_section;
207
208 PUT_WORD (abfd, g->address, natptr->r_address);
209
210 r_type = (unsigned int) g->howto->type;
211
212 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
213
214
215 /* If this relocation is relative to a symbol then set the
216 r_index to the symbols index, and the r_extern bit.
217
218 Absolute symbols can come in in two ways, either as an offset
219 from the abs section, or as a symbol which has an abs value.
220 check for that here
221 */
222
223 if (bfd_is_com_section (output_section)
224 || output_section == &bfd_abs_section
225 || output_section == &bfd_und_section)
226 {
227 if (bfd_abs_section.symbol == sym)
228 {
229 /* Whoops, looked like an abs symbol, but is really an offset
230 from the abs section */
231 r_index = 0;
232 r_extern = 0;
233 }
234 else
235 {
236 r_extern = 1;
237 r_index = stoi ((*(g->sym_ptr_ptr))->KEEPIT);
238 }
239 }
240 else
241 {
242 /* Just an ordinary section */
243 r_extern = 0;
244 r_index = output_section->target_index;
245 }
246
247
248 /* now the fun stuff */
249 if (abfd->xvec->header_byteorder_big_p != false)
250 {
251 natptr->r_index[0] = r_index >> 16;
252 natptr->r_index[1] = r_index >> 8;
253 natptr->r_index[2] = r_index;
254 natptr->r_type[0] =
255 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
256 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
257 }
258 else
259 {
260 natptr->r_index[2] = r_index >> 16;
261 natptr->r_index[1] = r_index >> 8;
262 natptr->r_index[0] = r_index;
263 natptr->r_type[0] =
264 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
265 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
266 }
267
268 PUT_WORD (abfd, r_addend, natptr->r_addend);
269 }
270
271 /* BFD deals internally with all things based from the section they're
272 in. so, something in 10 bytes into a text section with a base of
273 50 would have a symbol (.text+10) and know .text vma was 50.
274
275 Aout keeps all it's symbols based from zero, so the symbol would
276 contain 60. This macro subs the base of each section from the value
277 to give the true offset from the section */
278
279
280 #define MOVE_ADDRESS(ad) \
281 if (r_extern) { \
282 /* undefined symbol */ \
283 cache_ptr->sym_ptr_ptr = symbols + r_index; \
284 cache_ptr->addend = ad; \
285 } else { \
286 /* defined, section relative. replace symbol with pointer to \
287 symbol which points to section */ \
288 switch (r_index) { \
289 case N_TEXT: \
290 case N_TEXT | N_EXT: \
291 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
292 cache_ptr->addend = ad - su->textsec->vma; \
293 break; \
294 case N_DATA: \
295 case N_DATA | N_EXT: \
296 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
297 cache_ptr->addend = ad - su->datasec->vma; \
298 break; \
299 case N_BSS: \
300 case N_BSS | N_EXT: \
301 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
302 cache_ptr->addend = ad - su->bsssec->vma; \
303 break; \
304 default: \
305 case N_ABS: \
306 case N_ABS | N_EXT: \
307 cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; \
308 cache_ptr->addend = ad; \
309 break; \
310 } \
311 } \
312
313 void
314 NAME (lynx, swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols)
315 bfd *abfd;
316 struct reloc_ext_external *bytes;
317 arelent *cache_ptr;
318 asymbol **symbols;
319 {
320 int r_index;
321 int r_extern;
322 unsigned int r_type;
323 struct aoutdata *su = &(abfd->tdata.aout_data->a);
324
325 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
326
327 r_index = bytes->r_index[1];
328 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
329 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
330 >> RELOC_EXT_BITS_TYPE_SH_BIG;
331
332 cache_ptr->howto = aout_32_ext_howto_table + r_type;
333 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
334 }
335
336 void
337 NAME (lynx, swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols)
338 bfd *abfd;
339 struct reloc_std_external *bytes;
340 arelent *cache_ptr;
341 asymbol **symbols;
342 {
343 int r_index;
344 int r_extern;
345 unsigned int r_length;
346 int r_pcrel;
347 int r_baserel, r_jmptable, r_relative;
348 struct aoutdata *su = &(abfd->tdata.aout_data->a);
349
350 cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
351
352 r_index = bytes->r_index[1];
353 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
354 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
355 r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
356 r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
357 r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
358 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
359 >> RELOC_STD_BITS_LENGTH_SH_BIG;
360
361 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
362 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
363
364 MOVE_ADDRESS (0);
365 }
366
367 /* Reloc hackery */
368
369 boolean
370 NAME (lynx, slurp_reloc_table) (abfd, asect, symbols)
371 bfd *abfd;
372 sec_ptr asect;
373 asymbol **symbols;
374 {
375 unsigned int count;
376 bfd_size_type reloc_size;
377 PTR relocs;
378 arelent *reloc_cache;
379 size_t each_size;
380
381 if (asect->relocation)
382 return true;
383
384 if (asect->flags & SEC_CONSTRUCTOR)
385 return true;
386
387 if (asect == obj_datasec (abfd))
388 {
389 reloc_size = exec_hdr (abfd)->a_drsize;
390 goto doit;
391 }
392
393 if (asect == obj_textsec (abfd))
394 {
395 reloc_size = exec_hdr (abfd)->a_trsize;
396 goto doit;
397 }
398
399 bfd_set_error (bfd_error_invalid_operation);
400 return false;
401
402 doit:
403 bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
404 each_size = obj_reloc_entry_size (abfd);
405
406 count = reloc_size / each_size;
407
408
409 reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t) (count * sizeof
410 (arelent)));
411 if (!reloc_cache)
412 {
413 nomem:
414 bfd_set_error (bfd_error_no_memory);
415 return false;
416 }
417
418 relocs = (PTR) bfd_alloc (abfd, reloc_size);
419 if (!relocs)
420 {
421 bfd_release (abfd, reloc_cache);
422 goto nomem;
423 }
424
425 if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
426 {
427 bfd_release (abfd, relocs);
428 bfd_release (abfd, reloc_cache);
429 return false;
430 }
431
432 if (each_size == RELOC_EXT_SIZE)
433 {
434 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
435 unsigned int counter = 0;
436 arelent *cache_ptr = reloc_cache;
437
438 for (; counter < count; counter++, rptr++, cache_ptr++)
439 {
440 NAME (lynx, swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols);
441 }
442 }
443 else
444 {
445 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
446 unsigned int counter = 0;
447 arelent *cache_ptr = reloc_cache;
448
449 for (; counter < count; counter++, rptr++, cache_ptr++)
450 {
451 NAME (lynx, swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols);
452 }
453
454 }
455
456 bfd_release (abfd, relocs);
457 asect->relocation = reloc_cache;
458 asect->reloc_count = count;
459 return true;
460 }
461
462
463
464 /* Write out a relocation section into an object file. */
465
466 boolean
467 NAME (lynx, squirt_out_relocs) (abfd, section)
468 bfd *abfd;
469 asection *section;
470 {
471 arelent **generic;
472 unsigned char *native, *natptr;
473 size_t each_size;
474
475 unsigned int count = section->reloc_count;
476 size_t natsize;
477
478 if (count == 0)
479 return true;
480
481 each_size = obj_reloc_entry_size (abfd);
482 natsize = each_size * count;
483 native = (unsigned char *) bfd_zalloc (abfd, natsize);
484 if (!native)
485 {
486 bfd_set_error (bfd_error_no_memory);
487 return false;
488 }
489
490 generic = section->orelocation;
491
492 if (each_size == RELOC_EXT_SIZE)
493 {
494 for (natptr = native;
495 count != 0;
496 --count, natptr += each_size, ++generic)
497 NAME (lynx, swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
498 }
499 else
500 {
501 for (natptr = native;
502 count != 0;
503 --count, natptr += each_size, ++generic)
504 NAME (lynx, swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
505 }
506
507 if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize)
508 {
509 bfd_release (abfd, native);
510 return false;
511 }
512 bfd_release (abfd, native);
513
514 return true;
515 }
516
517 /* This is stupid. This function should be a boolean predicate */
518 long
519 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
520 bfd *abfd;
521 sec_ptr section;
522 arelent **relptr;
523 asymbol **symbols;
524 {
525 arelent *tblptr = section->relocation;
526 unsigned int count;
527
528 if (!(tblptr || NAME (lynx, slurp_reloc_table) (abfd, section, symbols)))
529 return -1;
530
531 if (section->flags & SEC_CONSTRUCTOR)
532 {
533 arelent_chain *chain = section->constructor_chain;
534 for (count = 0; count < section->reloc_count; count++)
535 {
536 *relptr++ = &chain->relent;
537 chain = chain->next;
538 }
539 }
540 else
541 {
542 tblptr = section->relocation;
543 if (!tblptr)
544 return -1;
545
546 for (count = 0; count++ < section->reloc_count;)
547 {
548 *relptr++ = tblptr++;
549 }
550 }
551 *relptr = 0;
552
553 return section->reloc_count;
554 }
555
556 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
557
558 #include "aout-target.h"
This page took 0.0541 seconds and 5 git commands to generate.