i386lynx.c revision 1.1.1.2 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, 2010 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
118
120 #define KEEPIT udata.i
121
122 extern reloc_howto_type aout_32_ext_howto_table[];
123 extern reloc_howto_type aout_32_std_howto_table[];
124
125 /* Standard reloc stuff */
126 /* Output standard relocation information to a file in target byte order. */
127
128 void
129 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
130 bfd *abfd;
131 arelent *g;
132 struct reloc_std_external *natptr;
133 {
134 int r_index;
135 asymbol *sym = *(g->sym_ptr_ptr);
136 int r_extern;
137 unsigned int r_length;
138 int r_pcrel;
139 int r_baserel, r_jmptable, r_relative;
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 /* name was clobbered by aout_write_syms to be symbol index */
152
153 /* If this relocation is relative to a symbol then set the
154 r_index to the symbols index, and the r_extern bit.
155
156 Absolute symbols can come in in two ways, either as an offset
157 from the abs section, or as a symbol which has an abs value.
158 check for that here
159 */
160
161
162 if (bfd_is_com_section (output_section)
163 || bfd_is_abs_section (output_section)
164 || bfd_is_und_section (output_section))
165 {
166 if (bfd_abs_section_ptr->symbol == sym)
167 {
168 /* Whoops, looked like an abs symbol, but is really an offset
169 from the abs section */
170 r_index = 0;
171 r_extern = 0;
172 }
173 else
174 {
175 /* Fill in symbol */
176 r_extern = 1;
177 r_index = (*g->sym_ptr_ptr)->KEEPIT;
178 }
179 }
180 else
181 {
182 /* Just an ordinary section */
183 r_extern = 0;
184 r_index = output_section->target_index;
185 }
186
187 /* now the fun stuff */
188 if (bfd_header_big_endian (abfd))
189 {
190 natptr->r_index[0] = r_index >> 16;
191 natptr->r_index[1] = r_index >> 8;
192 natptr->r_index[2] = r_index;
193 natptr->r_type[0] =
194 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
195 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
196 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
197 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
198 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
199 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
200 }
201 else
202 {
203 natptr->r_index[2] = r_index >> 16;
204 natptr->r_index[1] = r_index >> 8;
205 natptr->r_index[0] = r_index;
206 natptr->r_type[0] =
207 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
208 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
209 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
210 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
211 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
212 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
213 }
214 }
215
216
217 /* Extended stuff */
218 /* Output extended relocation information to a file in target byte order. */
219
220 void
221 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
222 bfd *abfd;
223 arelent *g;
224 register struct reloc_ext_external *natptr;
225 {
226 int r_index;
227 int r_extern;
228 unsigned int r_type;
229 unsigned int r_addend;
230 asymbol *sym = *(g->sym_ptr_ptr);
231 asection *output_section = sym->section->output_section;
232
233 PUT_WORD (abfd, g->address, natptr->r_address);
234
235 r_type = (unsigned int) g->howto->type;
236
237 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
238
239
240 /* If this relocation is relative to a symbol then set the
241 r_index to the symbols index, and the r_extern bit.
242
243 Absolute symbols can come in in two ways, either as an offset
244 from the abs section, or as a symbol which has an abs value.
245 check for that here
246 */
247
248 if (bfd_is_com_section (output_section)
249 || bfd_is_abs_section (output_section)
250 || bfd_is_und_section (output_section))
251 {
252 if (bfd_abs_section_ptr->symbol == sym)
253 {
254 /* Whoops, looked like an abs symbol, but is really an offset
255 from the abs section */
256 r_index = 0;
257 r_extern = 0;
258 }
259 else
260 {
261 r_extern = 1;
262 r_index = (*g->sym_ptr_ptr)->KEEPIT;
263 }
264 }
265 else
266 {
267 /* Just an ordinary section */
268 r_extern = 0;
269 r_index = output_section->target_index;
270 }
271
272
273 /* now the fun stuff */
274 if (bfd_header_big_endian (abfd))
275 {
276 natptr->r_index[0] = r_index >> 16;
277 natptr->r_index[1] = r_index >> 8;
278 natptr->r_index[2] = r_index;
279 natptr->r_type[0] =
280 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
281 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
282 }
283 else
284 {
285 natptr->r_index[2] = r_index >> 16;
286 natptr->r_index[1] = r_index >> 8;
287 natptr->r_index[0] = r_index;
288 natptr->r_type[0] =
289 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
290 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
291 }
292
293 PUT_WORD (abfd, r_addend, natptr->r_addend);
294 }
295
296 /* BFD deals internally with all things based from the section they're
297 in. so, something in 10 bytes into a text section with a base of
298 50 would have a symbol (.text+10) and know .text vma was 50.
299
300 Aout keeps all it's symbols based from zero, so the symbol would
301 contain 60. This macro subs the base of each section from the value
302 to give the true offset from the section */
303
304
305 #define MOVE_ADDRESS(ad) \
306 if (r_extern) { \
307 /* undefined symbol */ \
308 cache_ptr->sym_ptr_ptr = symbols + r_index; \
309 cache_ptr->addend = ad; \
310 } else { \
311 /* defined, section relative. replace symbol with pointer to \
312 symbol which points to section */ \
313 switch (r_index) { \
314 case N_TEXT: \
315 case N_TEXT | N_EXT: \
316 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
317 cache_ptr->addend = ad - su->textsec->vma; \
318 break; \
319 case N_DATA: \
320 case N_DATA | N_EXT: \
321 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
322 cache_ptr->addend = ad - su->datasec->vma; \
323 break; \
324 case N_BSS: \
325 case N_BSS | N_EXT: \
326 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
327 cache_ptr->addend = ad - su->bsssec->vma; \
328 break; \
329 default: \
330 case N_ABS: \
331 case N_ABS | N_EXT: \
332 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
333 cache_ptr->addend = ad; \
334 break; \
335 } \
336 } \
337
338 void
339 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
340 bfd *abfd;
341 struct reloc_ext_external *bytes;
342 arelent *cache_ptr;
343 asymbol **symbols;
344 bfd_size_type symcount ATTRIBUTE_UNUSED;
345 {
346 int r_index;
347 int r_extern;
348 unsigned int r_type;
349 struct aoutdata *su = &(abfd->tdata.aout_data->a);
350
351 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
352
353 r_index = bytes->r_index[1];
354 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
355 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
356 >> RELOC_EXT_BITS_TYPE_SH_BIG;
357
358 cache_ptr->howto = aout_32_ext_howto_table + r_type;
359 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
360 }
361
362 void
363 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
364 bfd *abfd;
365 struct reloc_std_external *bytes;
366 arelent *cache_ptr;
367 asymbol **symbols;
368 bfd_size_type symcount ATTRIBUTE_UNUSED;
369 {
370 int r_index;
371 int r_extern;
372 unsigned int r_length;
373 int r_pcrel;
374 struct aoutdata *su = &(abfd->tdata.aout_data->a);
375
376 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
377
378 r_index = bytes->r_index[1];
379 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
380 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
381 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
382 >> RELOC_STD_BITS_LENGTH_SH_BIG;
383
384 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
385 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
386
387 MOVE_ADDRESS (0);
388 }
389
390 /* Reloc hackery */
391
392 bfd_boolean
393 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
394 bfd *abfd;
395 sec_ptr asect;
396 asymbol **symbols;
397 {
398 bfd_size_type count;
399 bfd_size_type reloc_size;
400 PTR relocs;
401 arelent *reloc_cache;
402 size_t each_size;
403
404 if (asect->relocation)
405 return TRUE;
406
407 if (asect->flags & SEC_CONSTRUCTOR)
408 return TRUE;
409
410 if (asect == obj_datasec (abfd))
411 {
412 reloc_size = exec_hdr (abfd)->a_drsize;
413 goto doit;
414 }
415
416 if (asect == obj_textsec (abfd))
417 {
418 reloc_size = exec_hdr (abfd)->a_trsize;
419 goto doit;
420 }
421
422 bfd_set_error (bfd_error_invalid_operation);
423 return FALSE;
424
425 doit:
426 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
427 return FALSE;
428 each_size = obj_reloc_entry_size (abfd);
429
430 count = reloc_size / each_size;
431
432
433 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
434 if (!reloc_cache && count != 0)
435 return FALSE;
436
437 relocs = (PTR) bfd_alloc (abfd, reloc_size);
438 if (!relocs && reloc_size != 0)
439 {
440 free (reloc_cache);
441 return FALSE;
442 }
443
444 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
445 {
446 bfd_release (abfd, relocs);
447 free (reloc_cache);
448 return FALSE;
449 }
450
451 if (each_size == RELOC_EXT_SIZE)
452 {
453 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
454 unsigned int counter = 0;
455 arelent *cache_ptr = reloc_cache;
456
457 for (; counter < count; counter++, rptr++, cache_ptr++)
458 {
459 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
460 (bfd_size_type) bfd_get_symcount (abfd));
461 }
462 }
463 else
464 {
465 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
466 unsigned int counter = 0;
467 arelent *cache_ptr = reloc_cache;
468
469 for (; counter < count; counter++, rptr++, cache_ptr++)
470 {
471 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
472 (bfd_size_type) bfd_get_symcount (abfd));
473 }
474
475 }
476
477 bfd_release (abfd, relocs);
478 asect->relocation = reloc_cache;
479 asect->reloc_count = count;
480 return TRUE;
481 }
482
483
484
485 /* Write out a relocation section into an object file. */
486
487 bfd_boolean
488 NAME(lynx,squirt_out_relocs) (abfd, section)
489 bfd *abfd;
490 asection *section;
491 {
492 arelent **generic;
493 unsigned char *native, *natptr;
494 size_t each_size;
495
496 unsigned int count = section->reloc_count;
497 bfd_size_type natsize;
498
499 if (count == 0)
500 return TRUE;
501
502 each_size = obj_reloc_entry_size (abfd);
503 natsize = count;
504 natsize *= each_size;
505 native = (unsigned char *) bfd_zalloc (abfd, natsize);
506 if (!native)
507 return FALSE;
508
509 generic = section->orelocation;
510
511 if (each_size == RELOC_EXT_SIZE)
512 {
513 for (natptr = native;
514 count != 0;
515 --count, natptr += each_size, ++generic)
516 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
517 }
518 else
519 {
520 for (natptr = native;
521 count != 0;
522 --count, natptr += each_size, ++generic)
523 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
524 }
525
526 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
527 {
528 bfd_release (abfd, native);
529 return FALSE;
530 }
531 bfd_release (abfd, native);
532
533 return TRUE;
534 }
535
536 /* This is stupid. This function should be a boolean predicate */
537 long
538 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
539 bfd *abfd;
540 sec_ptr section;
541 arelent **relptr;
542 asymbol **symbols;
543 {
544 arelent *tblptr = section->relocation;
545 unsigned int count;
546
547 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
548 return -1;
549
550 if (section->flags & SEC_CONSTRUCTOR)
551 {
552 arelent_chain *chain = section->constructor_chain;
553 for (count = 0; count < section->reloc_count; count++)
554 {
555 *relptr++ = &chain->relent;
556 chain = chain->next;
557 }
558 }
559 else
560 {
561 tblptr = section->relocation;
562
563 for (count = 0; count++ < section->reloc_count;)
564 {
565 *relptr++ = tblptr++;
566 }
567 }
568 *relptr = 0;
569
570 return section->reloc_count;
571 }
572
573 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
574
575 #include "aout-target.h"
576