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