]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/i386lynx.c
ChangeLog rotatation and copyright year update
[thirdparty/binutils-gdb.git] / bfd / i386lynx.c
CommitLineData
252b5132 1/* BFD back-end for i386 a.out binaries under LynxOS.
b90efa5b 2 Copyright (C) 1990-2015 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 { \
39 bfd_size_type text_size; /* dummy vars */ \
40 file_ptr text_end; \
41 if (adata(abfd).magic == undecided_magic) \
42 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
43 \
44 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
45 execp->a_entry = bfd_get_start_address (abfd); \
46 \
47 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
48 obj_reloc_entry_size (abfd)); \
49 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
50 obj_reloc_entry_size (abfd)); \
51 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
52 \
dc810e39 53 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
2c3fc389 54 || bfd_bwrite (&exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
dc810e39 55 abfd) != EXEC_BYTES_SIZE) \
b34976b6 56 return FALSE; \
252b5132
RH
57 /* Now write out reloc info, followed by syms and strings */ \
58 \
59 if (bfd_get_symcount (abfd) != 0) \
60 { \
dc810e39 61 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
252b5132 62 != 0) \
b34976b6 63 return FALSE; \
252b5132 64 \
b34976b6 65 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
252b5132 66 \
dc810e39 67 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
252b5132 68 != 0) \
b34976b6 69 return FALSE; \
252b5132
RH
70 \
71 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
b34976b6 72 return FALSE; \
dc810e39 73 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
252b5132
RH
74 != 0) \
75 return 0; \
76 \
dc810e39 77 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
b34976b6 78 return FALSE; \
252b5132
RH
79 } \
80 }
81#endif
82
83#include "libaout.h"
84#include "aout/aout64.h"
85
e4b17274 86
252b5132
RH
87#ifdef LYNX_CORE
88
89char *lynx_core_file_failing_command ();
90int lynx_core_file_failing_signal ();
b34976b6 91bfd_boolean lynx_core_file_matches_executable_p ();
252b5132
RH
92const bfd_target *lynx_core_file_p ();
93
94#define MY_core_file_failing_command lynx_core_file_failing_command
95#define MY_core_file_failing_signal lynx_core_file_failing_signal
96#define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
97#define MY_core_file_p lynx_core_file_p
98
99#endif /* LYNX_CORE */
100\f
101
102#define KEEPIT udata.i
103
104extern reloc_howto_type aout_32_ext_howto_table[];
105extern reloc_howto_type aout_32_std_howto_table[];
106
107/* Standard reloc stuff */
108/* Output standard relocation information to a file in target byte order. */
109
2c3fc389
NC
110static void
111NAME(lynx,swap_std_reloc_out) (bfd *abfd,
112 arelent *g,
113 struct reloc_std_external *natptr)
252b5132
RH
114{
115 int r_index;
116 asymbol *sym = *(g->sym_ptr_ptr);
117 int r_extern;
118 unsigned int r_length;
119 int r_pcrel;
120 int r_baserel, r_jmptable, r_relative;
252b5132
RH
121 asection *output_section = sym->section->output_section;
122
123 PUT_WORD (abfd, g->address, natptr->r_address);
124
125 r_length = g->howto->size; /* Size as a power of two */
126 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
127 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
128 r_baserel = 0;
129 r_jmptable = 0;
130 r_relative = 0;
131
252b5132
RH
132 /* name was clobbered by aout_write_syms to be symbol index */
133
134 /* If this relocation is relative to a symbol then set the
135 r_index to the symbols index, and the r_extern bit.
136
137 Absolute symbols can come in in two ways, either as an offset
138 from the abs section, or as a symbol which has an abs value.
139 check for that here
b34976b6 140 */
252b5132 141
252b5132
RH
142 if (bfd_is_com_section (output_section)
143 || bfd_is_abs_section (output_section)
144 || bfd_is_und_section (output_section))
145 {
146 if (bfd_abs_section_ptr->symbol == sym)
147 {
148 /* Whoops, looked like an abs symbol, but is really an offset
b34976b6 149 from the abs section */
252b5132
RH
150 r_index = 0;
151 r_extern = 0;
152 }
153 else
154 {
155 /* Fill in symbol */
156 r_extern = 1;
157 r_index = (*g->sym_ptr_ptr)->KEEPIT;
158 }
159 }
160 else
161 {
162 /* Just an ordinary section */
163 r_extern = 0;
164 r_index = output_section->target_index;
165 }
166
167 /* now the fun stuff */
168 if (bfd_header_big_endian (abfd))
169 {
170 natptr->r_index[0] = r_index >> 16;
171 natptr->r_index[1] = r_index >> 8;
172 natptr->r_index[2] = r_index;
173 natptr->r_type[0] =
174 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
175 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
176 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
177 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
178 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
179 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
180 }
181 else
182 {
183 natptr->r_index[2] = r_index >> 16;
184 natptr->r_index[1] = r_index >> 8;
185 natptr->r_index[0] = r_index;
186 natptr->r_type[0] =
187 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
188 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
189 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
190 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
191 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
192 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
193 }
194}
195
196
197/* Extended stuff */
198/* Output extended relocation information to a file in target byte order. */
199
2c3fc389
NC
200static void
201NAME(lynx,swap_ext_reloc_out) (bfd *abfd,
202 arelent *g,
203 struct reloc_ext_external *natptr)
252b5132
RH
204{
205 int r_index;
206 int r_extern;
207 unsigned int r_type;
208 unsigned int r_addend;
209 asymbol *sym = *(g->sym_ptr_ptr);
210 asection *output_section = sym->section->output_section;
211
212 PUT_WORD (abfd, g->address, natptr->r_address);
213
214 r_type = (unsigned int) g->howto->type;
215
216 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
217
218
219 /* If this relocation is relative to a symbol then set the
220 r_index to the symbols index, and the r_extern bit.
221
222 Absolute symbols can come in in two ways, either as an offset
223 from the abs section, or as a symbol which has an abs value.
224 check for that here
225 */
226
227 if (bfd_is_com_section (output_section)
228 || bfd_is_abs_section (output_section)
229 || bfd_is_und_section (output_section))
230 {
231 if (bfd_abs_section_ptr->symbol == sym)
232 {
233 /* Whoops, looked like an abs symbol, but is really an offset
234 from the abs section */
235 r_index = 0;
236 r_extern = 0;
237 }
238 else
239 {
240 r_extern = 1;
241 r_index = (*g->sym_ptr_ptr)->KEEPIT;
242 }
243 }
244 else
245 {
246 /* Just an ordinary section */
247 r_extern = 0;
248 r_index = output_section->target_index;
249 }
250
251
252 /* now the fun stuff */
253 if (bfd_header_big_endian (abfd))
254 {
255 natptr->r_index[0] = r_index >> 16;
256 natptr->r_index[1] = r_index >> 8;
257 natptr->r_index[2] = r_index;
258 natptr->r_type[0] =
259 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
260 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
261 }
262 else
263 {
264 natptr->r_index[2] = r_index >> 16;
265 natptr->r_index[1] = r_index >> 8;
266 natptr->r_index[0] = r_index;
267 natptr->r_type[0] =
268 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
269 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
270 }
271
272 PUT_WORD (abfd, r_addend, natptr->r_addend);
273}
274
275/* BFD deals internally with all things based from the section they're
276 in. so, something in 10 bytes into a text section with a base of
277 50 would have a symbol (.text+10) and know .text vma was 50.
278
279 Aout keeps all it's symbols based from zero, so the symbol would
280 contain 60. This macro subs the base of each section from the value
281 to give the true offset from the section */
282
283
284#define MOVE_ADDRESS(ad) \
2c3fc389
NC
285 if (r_extern) \
286 { \
252b5132
RH
287 /* undefined symbol */ \
288 cache_ptr->sym_ptr_ptr = symbols + r_index; \
289 cache_ptr->addend = ad; \
2c3fc389
NC
290 } \
291 else \
292 { \
252b5132
RH
293 /* defined, section relative. replace symbol with pointer to \
294 symbol which points to section */ \
295 switch (r_index) { \
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 } \
318 } \
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
RH
326{
327 int r_index;
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
RH
349{
350 int r_index;
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
2c3fc389
NC
372static bfd_boolean
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)
b34976b6 384 return TRUE;
252b5132
RH
385
386 if (asect->flags & SEC_CONSTRUCTOR)
b34976b6 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);
b34976b6 402 return FALSE;
252b5132
RH
403
404doit:
405 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
b34976b6 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)
b34976b6 414 return FALSE;
252b5132 415
2c3fc389 416 relocs = bfd_alloc (abfd, reloc_size);
252b5132
RH
417 if (!relocs && reloc_size != 0)
418 {
419 free (reloc_cache);
b34976b6 420 return FALSE;
252b5132
RH
421 }
422
dc810e39 423 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
252b5132
RH
424 {
425 bfd_release (abfd, relocs);
426 free (reloc_cache);
b34976b6 427 return FALSE;
252b5132
RH
428 }
429
430 if (each_size == RELOC_EXT_SIZE)
431 {
2c3fc389 432 struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
252b5132
RH
433 unsigned int counter = 0;
434 arelent *cache_ptr = reloc_cache;
435
436 for (; counter < count; counter++, rptr++, cache_ptr++)
437 {
438 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
dc810e39 439 (bfd_size_type) bfd_get_symcount (abfd));
252b5132
RH
440 }
441 }
442 else
443 {
2c3fc389 444 struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
252b5132
RH
445 unsigned int counter = 0;
446 arelent *cache_ptr = reloc_cache;
447
448 for (; counter < count; counter++, rptr++, cache_ptr++)
449 {
450 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
dc810e39 451 (bfd_size_type) bfd_get_symcount (abfd));
252b5132
RH
452 }
453
454 }
455
456 bfd_release (abfd, relocs);
457 asect->relocation = reloc_cache;
458 asect->reloc_count = count;
b34976b6 459 return TRUE;
252b5132
RH
460}
461
462
463
464/* Write out a relocation section into an object file. */
465
2c3fc389
NC
466static bfd_boolean
467NAME(lynx,squirt_out_relocs) (bfd *abfd, asection *section)
252b5132
RH
468{
469 arelent **generic;
470 unsigned char *native, *natptr;
471 size_t each_size;
252b5132 472 unsigned int count = section->reloc_count;
dc810e39 473 bfd_size_type natsize;
252b5132
RH
474
475 if (count == 0)
b34976b6 476 return TRUE;
252b5132
RH
477
478 each_size = obj_reloc_entry_size (abfd);
dc810e39
AM
479 natsize = count;
480 natsize *= each_size;
252b5132
RH
481 native = (unsigned char *) bfd_zalloc (abfd, natsize);
482 if (!native)
b34976b6 483 return FALSE;
252b5132
RH
484
485 generic = section->orelocation;
486
487 if (each_size == RELOC_EXT_SIZE)
488 {
489 for (natptr = native;
490 count != 0;
491 --count, natptr += each_size, ++generic)
492 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
493 }
494 else
495 {
496 for (natptr = native;
497 count != 0;
498 --count, natptr += each_size, ++generic)
499 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
500 }
501
2c3fc389 502 if (bfd_bwrite (native, natsize, abfd) != natsize)
252b5132
RH
503 {
504 bfd_release (abfd, native);
b34976b6 505 return FALSE;
252b5132
RH
506 }
507 bfd_release (abfd, native);
508
b34976b6 509 return TRUE;
252b5132
RH
510}
511
512/* This is stupid. This function should be a boolean predicate */
2c3fc389
NC
513static long
514NAME(lynx,canonicalize_reloc) (bfd *abfd,
515 sec_ptr section,
516 arelent **relptr,
517 asymbol **symbols)
252b5132
RH
518{
519 arelent *tblptr = section->relocation;
520 unsigned int count;
521
522 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
523 return -1;
524
525 if (section->flags & SEC_CONSTRUCTOR)
526 {
527 arelent_chain *chain = section->constructor_chain;
528 for (count = 0; count < section->reloc_count; count++)
529 {
530 *relptr++ = &chain->relent;
531 chain = chain->next;
532 }
533 }
534 else
535 {
536 tblptr = section->relocation;
537
538 for (count = 0; count++ < section->reloc_count;)
539 {
540 *relptr++ = tblptr++;
541 }
542 }
543 *relptr = 0;
544
545 return section->reloc_count;
546}
547
548#define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
549
550#include "aout-target.h"