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