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