* symbols.c (resolve_symbol_value): Don't permit subtraction of
[binutils.git] / bfd / i386lynx.c
blob1f0344ec000913c424f74f0d1da1ada2b6f5594f
1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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 2 of the License, or
9 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #define BYTES_IN_WORD 4
21 #define N_SHARED_LIB(x) 0
23 #define TEXT_START_ADDR 0
24 #define TARGET_PAGE_SIZE 4096
25 #define SEGMENT_SIZE TARGET_PAGE_SIZE
26 #define DEFAULT_ARCH bfd_arch_i386
28 #define MY(OP) CAT(i386lynx_aout_,OP)
29 #define TARGETNAME "a.out-i386-lynx"
31 #include "bfd.h"
32 #include "sysdep.h"
33 #include "libbfd.h"
35 #ifndef WRITE_HEADERS
36 #define WRITE_HEADERS(abfd, execp) \
37 { \
38 bfd_size_type text_size; /* dummy vars */ \
39 file_ptr text_end; \
40 if (adata(abfd).magic == undecided_magic) \
41 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
43 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
44 execp->a_entry = bfd_get_start_address (abfd); \
46 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
47 obj_reloc_entry_size (abfd)); \
48 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
49 obj_reloc_entry_size (abfd)); \
50 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
52 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return false; \
53 if (bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) \
54 != EXEC_BYTES_SIZE) \
55 return false; \
56 /* Now write out reloc info, followed by syms and strings */ \
58 if (bfd_get_symcount (abfd) != 0) \
59 { \
60 if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) \
61 != 0) \
62 return false; \
64 if (! NAME(aout,write_syms)(abfd)) return false; \
66 if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET) \
67 != 0) \
68 return false; \
70 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
71 return false; \
72 if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET) \
73 != 0) \
74 return 0; \
76 if (!NAME(lynx,squirt_out_relocs)(abfd, obj_datasec (abfd))) \
77 return false; \
78 } \
80 #endif
82 #include "libaout.h"
83 #include "aout/aout64.h"
85 #ifdef LYNX_CORE
87 char *lynx_core_file_failing_command ();
88 int lynx_core_file_failing_signal ();
89 boolean lynx_core_file_matches_executable_p ();
90 const bfd_target *lynx_core_file_p ();
92 #define MY_core_file_failing_command lynx_core_file_failing_command
93 #define MY_core_file_failing_signal lynx_core_file_failing_signal
94 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
95 #define MY_core_file_p lynx_core_file_p
97 #endif /* LYNX_CORE */
100 #define KEEPIT udata.i
102 extern reloc_howto_type aout_32_ext_howto_table[];
103 extern reloc_howto_type aout_32_std_howto_table[];
105 /* Standard reloc stuff */
106 /* Output standard relocation information to a file in target byte order. */
108 void
109 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
110 bfd *abfd;
111 arelent *g;
112 struct reloc_std_external *natptr;
114 int r_index;
115 asymbol *sym = *(g->sym_ptr_ptr);
116 int r_extern;
117 unsigned int r_length;
118 int r_pcrel;
119 int r_baserel, r_jmptable, r_relative;
120 unsigned int r_addend;
121 asection *output_section = sym->section->output_section;
123 PUT_WORD (abfd, g->address, natptr->r_address);
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;
132 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
134 /* name was clobbered by aout_write_syms to be symbol index */
136 /* If this relocation is relative to a symbol then set the
137 r_index to the symbols index, and the r_extern bit.
139 Absolute symbols can come in in two ways, either as an offset
140 from the abs section, or as a symbol which has an abs value.
141 check for that here
145 if (bfd_is_com_section (output_section)
146 || bfd_is_abs_section (output_section)
147 || bfd_is_und_section (output_section))
149 if (bfd_abs_section_ptr->symbol == sym)
151 /* Whoops, looked like an abs symbol, but is really an offset
152 from the abs section */
153 r_index = 0;
154 r_extern = 0;
156 else
158 /* Fill in symbol */
159 r_extern = 1;
160 r_index = (*g->sym_ptr_ptr)->KEEPIT;
163 else
165 /* Just an ordinary section */
166 r_extern = 0;
167 r_index = output_section->target_index;
170 /* now the fun stuff */
171 if (bfd_header_big_endian (abfd))
173 natptr->r_index[0] = r_index >> 16;
174 natptr->r_index[1] = r_index >> 8;
175 natptr->r_index[2] = r_index;
176 natptr->r_type[0] =
177 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
178 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
179 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
180 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
181 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
182 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
184 else
186 natptr->r_index[2] = r_index >> 16;
187 natptr->r_index[1] = r_index >> 8;
188 natptr->r_index[0] = r_index;
189 natptr->r_type[0] =
190 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
191 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
192 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
193 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
194 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
195 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
200 /* Extended stuff */
201 /* Output extended relocation information to a file in target byte order. */
203 void
204 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
205 bfd *abfd;
206 arelent *g;
207 register struct reloc_ext_external *natptr;
209 int r_index;
210 int r_extern;
211 unsigned int r_type;
212 unsigned int r_addend;
213 asymbol *sym = *(g->sym_ptr_ptr);
214 asection *output_section = sym->section->output_section;
216 PUT_WORD (abfd, g->address, natptr->r_address);
218 r_type = (unsigned int) g->howto->type;
220 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
223 /* If this relocation is relative to a symbol then set the
224 r_index to the symbols index, and the r_extern bit.
226 Absolute symbols can come in in two ways, either as an offset
227 from the abs section, or as a symbol which has an abs value.
228 check for that here
231 if (bfd_is_com_section (output_section)
232 || bfd_is_abs_section (output_section)
233 || bfd_is_und_section (output_section))
235 if (bfd_abs_section_ptr->symbol == sym)
237 /* Whoops, looked like an abs symbol, but is really an offset
238 from the abs section */
239 r_index = 0;
240 r_extern = 0;
242 else
244 r_extern = 1;
245 r_index = (*g->sym_ptr_ptr)->KEEPIT;
248 else
250 /* Just an ordinary section */
251 r_extern = 0;
252 r_index = output_section->target_index;
256 /* now the fun stuff */
257 if (bfd_header_big_endian (abfd))
259 natptr->r_index[0] = r_index >> 16;
260 natptr->r_index[1] = r_index >> 8;
261 natptr->r_index[2] = r_index;
262 natptr->r_type[0] =
263 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
264 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
266 else
268 natptr->r_index[2] = r_index >> 16;
269 natptr->r_index[1] = r_index >> 8;
270 natptr->r_index[0] = r_index;
271 natptr->r_type[0] =
272 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
273 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
276 PUT_WORD (abfd, r_addend, natptr->r_addend);
279 /* BFD deals internally with all things based from the section they're
280 in. so, something in 10 bytes into a text section with a base of
281 50 would have a symbol (.text+10) and know .text vma was 50.
283 Aout keeps all it's symbols based from zero, so the symbol would
284 contain 60. This macro subs the base of each section from the value
285 to give the true offset from the section */
288 #define MOVE_ADDRESS(ad) \
289 if (r_extern) { \
290 /* undefined symbol */ \
291 cache_ptr->sym_ptr_ptr = symbols + r_index; \
292 cache_ptr->addend = ad; \
293 } else { \
294 /* defined, section relative. replace symbol with pointer to \
295 symbol which points to section */ \
296 switch (r_index) { \
297 case N_TEXT: \
298 case N_TEXT | N_EXT: \
299 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
300 cache_ptr->addend = ad - su->textsec->vma; \
301 break; \
302 case N_DATA: \
303 case N_DATA | N_EXT: \
304 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
305 cache_ptr->addend = ad - su->datasec->vma; \
306 break; \
307 case N_BSS: \
308 case N_BSS | N_EXT: \
309 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
310 cache_ptr->addend = ad - su->bsssec->vma; \
311 break; \
312 default: \
313 case N_ABS: \
314 case N_ABS | N_EXT: \
315 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
316 cache_ptr->addend = ad; \
317 break; \
321 void
322 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
323 bfd *abfd;
324 struct reloc_ext_external *bytes;
325 arelent *cache_ptr;
326 asymbol **symbols;
327 bfd_size_type symcount;
329 int r_index;
330 int r_extern;
331 unsigned int r_type;
332 struct aoutdata *su = &(abfd->tdata.aout_data->a);
334 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
336 r_index = bytes->r_index[1];
337 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
338 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
339 >> RELOC_EXT_BITS_TYPE_SH_BIG;
341 cache_ptr->howto = aout_32_ext_howto_table + r_type;
342 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
345 void
346 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
347 bfd *abfd;
348 struct reloc_std_external *bytes;
349 arelent *cache_ptr;
350 asymbol **symbols;
351 bfd_size_type symcount;
353 int r_index;
354 int r_extern;
355 unsigned int r_length;
356 int r_pcrel;
357 int r_baserel, r_jmptable, r_relative;
358 struct aoutdata *su = &(abfd->tdata.aout_data->a);
360 cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
362 r_index = bytes->r_index[1];
363 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
364 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
365 r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
366 r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
367 r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
368 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
369 >> RELOC_STD_BITS_LENGTH_SH_BIG;
371 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
372 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
374 MOVE_ADDRESS (0);
377 /* Reloc hackery */
379 boolean
380 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
381 bfd *abfd;
382 sec_ptr asect;
383 asymbol **symbols;
385 unsigned int count;
386 bfd_size_type reloc_size;
387 PTR relocs;
388 arelent *reloc_cache;
389 size_t each_size;
391 if (asect->relocation)
392 return true;
394 if (asect->flags & SEC_CONSTRUCTOR)
395 return true;
397 if (asect == obj_datasec (abfd))
399 reloc_size = exec_hdr (abfd)->a_drsize;
400 goto doit;
403 if (asect == obj_textsec (abfd))
405 reloc_size = exec_hdr (abfd)->a_trsize;
406 goto doit;
409 bfd_set_error (bfd_error_invalid_operation);
410 return false;
412 doit:
413 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
414 return false;
415 each_size = obj_reloc_entry_size (abfd);
417 count = reloc_size / each_size;
420 reloc_cache = (arelent *) bfd_malloc (count * sizeof (arelent));
421 if (!reloc_cache && count != 0)
422 return false;
423 memset (reloc_cache, 0, count * sizeof (arelent));
425 relocs = (PTR) bfd_alloc (abfd, reloc_size);
426 if (!relocs && reloc_size != 0)
428 free (reloc_cache);
429 return false;
432 if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
434 bfd_release (abfd, relocs);
435 free (reloc_cache);
436 return false;
439 if (each_size == RELOC_EXT_SIZE)
441 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
442 unsigned int counter = 0;
443 arelent *cache_ptr = reloc_cache;
445 for (; counter < count; counter++, rptr++, cache_ptr++)
447 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
448 bfd_get_symcount (abfd));
451 else
453 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
454 unsigned int counter = 0;
455 arelent *cache_ptr = reloc_cache;
457 for (; counter < count; counter++, rptr++, cache_ptr++)
459 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
460 bfd_get_symcount (abfd));
465 bfd_release (abfd, relocs);
466 asect->relocation = reloc_cache;
467 asect->reloc_count = count;
468 return true;
473 /* Write out a relocation section into an object file. */
475 boolean
476 NAME(lynx,squirt_out_relocs) (abfd, section)
477 bfd *abfd;
478 asection *section;
480 arelent **generic;
481 unsigned char *native, *natptr;
482 size_t each_size;
484 unsigned int count = section->reloc_count;
485 size_t natsize;
487 if (count == 0)
488 return true;
490 each_size = obj_reloc_entry_size (abfd);
491 natsize = each_size * count;
492 native = (unsigned char *) bfd_zalloc (abfd, natsize);
493 if (!native)
494 return false;
496 generic = section->orelocation;
498 if (each_size == RELOC_EXT_SIZE)
500 for (natptr = native;
501 count != 0;
502 --count, natptr += each_size, ++generic)
503 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
505 else
507 for (natptr = native;
508 count != 0;
509 --count, natptr += each_size, ++generic)
510 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
513 if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize)
515 bfd_release (abfd, native);
516 return false;
518 bfd_release (abfd, native);
520 return true;
523 /* This is stupid. This function should be a boolean predicate */
524 long
525 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
526 bfd *abfd;
527 sec_ptr section;
528 arelent **relptr;
529 asymbol **symbols;
531 arelent *tblptr = section->relocation;
532 unsigned int count;
534 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
535 return -1;
537 if (section->flags & SEC_CONSTRUCTOR)
539 arelent_chain *chain = section->constructor_chain;
540 for (count = 0; count < section->reloc_count; count++)
542 *relptr++ = &chain->relent;
543 chain = chain->next;
546 else
548 tblptr = section->relocation;
550 for (count = 0; count++ < section->reloc_count;)
552 *relptr++ = tblptr++;
555 *relptr = 0;
557 return section->reloc_count;
560 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
562 #include "aout-target.h"