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