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