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