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