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