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