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