1 /* BFD back-end for i386 a.out binaries under Lynx.
2 Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 #define BYTES_IN_WORD 4
22 #define N_SHARED_LIB(x) 0
24 #define TEXT_START_ADDR 0
25 #define PAGE_SIZE 4096
26 #define SEGMENT_SIZE PAGE_SIZE
27 #define DEFAULT_ARCH bfd_arch_i386
29 #define MY(OP) CAT(i386lynx_aout_,OP)
30 #define TARGETNAME "a.out-i386-lynx"
37 #define WRITE_HEADERS(abfd, execp) \
39 bfd_size_type text_size; /* dummy vars */ \
41 if (adata(abfd).magic == undecided_magic) \
42 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
44 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
45 execp->a_entry = bfd_get_start_address (abfd); \
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); \
53 bfd_seek (abfd, (file_ptr) 0, SEEK_SET); \
54 bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); \
55 /* Now write out reloc info, followed by syms and strings */ \
57 if (bfd_get_symcount (abfd) != 0) \
59 bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET); \
61 NAME(aout,write_syms)(abfd); \
63 bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET); \
65 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) return false; \
66 bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET); \
68 if (!NAME(lynx,squirt_out_relocs)(abfd, obj_datasec (abfd))) return false; \
74 #include "aout/aout64.h"
78 char *lynx_core_file_failing_command();
79 int lynx_core_file_failing_signal();
80 boolean lynx_core_file_matches_executable_p();
81 bfd_target *lynx_core_file_p();
83 #define MY_core_file_failing_command lynx_core_file_failing_command
84 #define MY_core_file_failing_signal lynx_core_file_failing_signal
85 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
86 #define MY_core_file_p lynx_core_file_p
88 #endif /* HOST_LYNX */
93 extern reloc_howto_type aout_32_ext_howto_table[];
94 extern reloc_howto_type aout_32_std_howto_table[];
96 /* Standard reloc stuff */
97 /* Output standard relocation information to a file in target byte order. */
100 DEFUN(NAME(lynx,swap_std_reloc_out),(abfd, g, natptr),
103 struct reloc_std_external *natptr)
106 asymbol *sym = *(g->sym_ptr_ptr);
108 unsigned int r_length;
110 int r_baserel, r_jmptable, r_relative;
111 unsigned int r_addend;
112 asection *output_section = sym->section->output_section;
114 PUT_WORD(abfd, g->address, natptr->r_address);
116 r_length = g->howto->size ; /* Size as a power of two */
117 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
118 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
123 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
125 /* name was clobbered by aout_write_syms to be symbol index */
127 /* If this relocation is relative to a symbol then set the
128 r_index to the symbols index, and the r_extern bit.
130 Absolute symbols can come in in two ways, either as an offset
131 from the abs section, or as a symbol which has an abs value.
136 if (bfd_is_com_section (output_section)
137 || output_section == &bfd_abs_section
138 || output_section == &bfd_und_section)
140 if (bfd_abs_section.symbol == sym)
142 /* Whoops, looked like an abs symbol, but is really an offset
143 from the abs section */
151 r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT);
157 /* Just an ordinary section */
159 r_index = output_section->target_index;
162 /* now the fun stuff */
163 if (abfd->xvec->header_byteorder_big_p != false) {
164 natptr->r_index[0] = r_index >> 16;
165 natptr->r_index[1] = r_index >> 8;
166 natptr->r_index[2] = r_index;
168 (r_extern? RELOC_STD_BITS_EXTERN_BIG: 0)
169 | (r_pcrel? RELOC_STD_BITS_PCREL_BIG: 0)
170 | (r_baserel? RELOC_STD_BITS_BASEREL_BIG: 0)
171 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_BIG: 0)
172 | (r_relative? RELOC_STD_BITS_RELATIVE_BIG: 0)
173 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
175 natptr->r_index[2] = r_index >> 16;
176 natptr->r_index[1] = r_index >> 8;
177 natptr->r_index[0] = r_index;
179 (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0)
180 | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0)
181 | (r_baserel? RELOC_STD_BITS_BASEREL_LITTLE: 0)
182 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
183 | (r_relative? RELOC_STD_BITS_RELATIVE_LITTLE: 0)
184 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
190 /* Output extended relocation information to a file in target byte order. */
193 DEFUN(NAME(lynx,swap_ext_reloc_out),(abfd, g, natptr),
196 register struct reloc_ext_external *natptr)
201 unsigned int r_addend;
202 asymbol *sym = *(g->sym_ptr_ptr);
203 asection *output_section = sym->section->output_section;
205 PUT_WORD (abfd, g->address, natptr->r_address);
207 r_type = (unsigned int) g->howto->type;
209 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
212 /* If this relocation is relative to a symbol then set the
213 r_index to the symbols index, and the r_extern bit.
215 Absolute symbols can come in in two ways, either as an offset
216 from the abs section, or as a symbol which has an abs value.
220 if (bfd_is_com_section (output_section)
221 || output_section == &bfd_abs_section
222 || output_section == &bfd_und_section)
224 if (bfd_abs_section.symbol == sym)
226 /* Whoops, looked like an abs symbol, but is really an offset
227 from the abs section */
234 r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT);
239 /* Just an ordinary section */
241 r_index = output_section->target_index;
245 /* now the fun stuff */
246 if (abfd->xvec->header_byteorder_big_p != false) {
247 natptr->r_index[0] = r_index >> 16;
248 natptr->r_index[1] = r_index >> 8;
249 natptr->r_index[2] = r_index;
251 (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
252 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
254 natptr->r_index[2] = r_index >> 16;
255 natptr->r_index[1] = r_index >> 8;
256 natptr->r_index[0] = r_index;
258 (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
259 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
262 PUT_WORD (abfd, r_addend, natptr->r_addend);
265 /* BFD deals internally with all things based from the section they're
266 in. so, something in 10 bytes into a text section with a base of
267 50 would have a symbol (.text+10) and know .text vma was 50.
269 Aout keeps all it's symbols based from zero, so the symbol would
270 contain 60. This macro subs the base of each section from the value
271 to give the true offset from the section */
274 #define MOVE_ADDRESS(ad) \
276 /* undefined symbol */ \
277 cache_ptr->sym_ptr_ptr = symbols + r_index; \
278 cache_ptr->addend = ad; \
280 /* defined, section relative. replace symbol with pointer to \
281 symbol which points to section */ \
284 case N_TEXT | N_EXT: \
285 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
286 cache_ptr->addend = ad - su->textsec->vma; \
289 case N_DATA | N_EXT: \
290 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
291 cache_ptr->addend = ad - su->datasec->vma; \
294 case N_BSS | N_EXT: \
295 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
296 cache_ptr->addend = ad - su->bsssec->vma; \
300 case N_ABS | N_EXT: \
301 cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; \
302 cache_ptr->addend = ad; \
308 DEFUN(NAME(lynx,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols),
310 struct reloc_ext_external *bytes AND
311 arelent *cache_ptr AND
317 struct aoutdata *su = &(abfd->tdata.aout_data->a);
319 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
321 /* now the fun stuff */
322 if (1 /* abfd->xvec->header_byteorder_big_p != false */) {
323 r_index = (bytes->r_index[0] << 16)
324 | (bytes->r_index[1] << 8)
326 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
327 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
328 >> RELOC_EXT_BITS_TYPE_SH_BIG;
330 r_index = (bytes->r_index[2] << 16)
331 | (bytes->r_index[1] << 8)
333 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
334 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
335 >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
338 cache_ptr->howto = aout_32_ext_howto_table + r_type;
339 MOVE_ADDRESS(GET_SWORD(abfd, bytes->r_addend));
343 DEFUN(NAME(lynx,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols),
345 struct reloc_std_external *bytes AND
346 arelent *cache_ptr AND
352 unsigned int r_length;
354 int r_baserel, r_jmptable, r_relative;
355 struct aoutdata *su = &(abfd->tdata.aout_data->a);
357 cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
359 r_index = (bytes->r_type[0] << 16)
360 | (bytes->r_index[2] << 8)
362 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
363 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
364 r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
365 r_jmptable= (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
366 r_relative= (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
367 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
368 >> RELOC_STD_BITS_LENGTH_SH_BIG;
370 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
371 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
379 DEFUN(NAME(lynx,slurp_reloc_table),(abfd, asect, symbols),
385 bfd_size_type reloc_size;
387 arelent *reloc_cache;
390 if (asect->relocation) return true;
392 if (asect->flags & SEC_CONSTRUCTOR) return true;
394 if (asect == obj_datasec (abfd)) {
395 reloc_size = exec_hdr(abfd)->a_drsize;
399 if (asect == obj_textsec (abfd)) {
400 reloc_size = exec_hdr(abfd)->a_trsize;
404 bfd_error = invalid_operation;
408 bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
409 each_size = obj_reloc_entry_size (abfd);
411 count = reloc_size / each_size;
414 reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
418 bfd_error = no_memory;
422 relocs = (PTR) bfd_alloc (abfd, reloc_size);
424 bfd_release (abfd, reloc_cache);
428 if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
429 bfd_release (abfd, relocs);
430 bfd_release (abfd, reloc_cache);
431 bfd_error = system_call_error;
435 if (each_size == RELOC_EXT_SIZE) {
436 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
437 unsigned int counter = 0;
438 arelent *cache_ptr = reloc_cache;
440 for (; counter < count; counter++, rptr++, cache_ptr++) {
441 NAME(lynx,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols);
444 register struct reloc_std_external *rptr = (struct reloc_std_external*) relocs;
445 unsigned int counter = 0;
446 arelent *cache_ptr = reloc_cache;
448 for (; counter < count; counter++, rptr++, cache_ptr++) {
449 NAME(lynx,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols);
454 bfd_release (abfd,relocs);
455 asect->relocation = reloc_cache;
456 asect->reloc_count = count;
462 /* Write out a relocation section into an object file. */
465 DEFUN(NAME(lynx,squirt_out_relocs),(abfd, section),
470 unsigned char *native, *natptr;
473 unsigned int count = section->reloc_count;
476 if (count == 0) return true;
478 each_size = obj_reloc_entry_size (abfd);
479 natsize = each_size * count;
480 native = (unsigned char *) bfd_zalloc (abfd, natsize);
482 bfd_error = no_memory;
486 generic = section->orelocation;
488 if (each_size == RELOC_EXT_SIZE)
490 for (natptr = native;
492 --count, natptr += each_size, ++generic)
493 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr);
497 for (natptr = native;
499 --count, natptr += each_size, ++generic)
500 NAME(lynx,swap_std_reloc_out)(abfd, *generic, (struct reloc_std_external *)natptr);
503 if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
504 bfd_release(abfd, native);
507 bfd_release (abfd, native);
512 /* This is stupid. This function should be a boolean predicate */
514 DEFUN(NAME(lynx,canonicalize_reloc),(abfd, section, relptr, symbols),
520 arelent *tblptr = section->relocation;
523 if (!(tblptr || NAME(lynx,slurp_reloc_table)(abfd, section, symbols)))
526 if (section->flags & SEC_CONSTRUCTOR) {
527 arelent_chain *chain = section->constructor_chain;
528 for (count = 0; count < section->reloc_count; count ++) {
529 *relptr ++ = &chain->relent;
534 tblptr = section->relocation;
535 if (!tblptr) return 0;
537 for (count = 0; count++ < section->reloc_count;)
539 *relptr++ = tblptr++;
544 return section->reloc_count;
547 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
549 #include "aout-target.h"