source: trunk/src/binutils/bfd/i386lynx.c@ 106

Last change on this file since 106 was 10, checked in by bird, 22 years ago

Initial revision

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