diff options
author | Ken Raeburn <raeburn@cygnus> | 1992-06-16 12:04:03 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@cygnus> | 1992-06-16 12:04:03 +0000 |
commit | ce07dd7c0cc9034fd9aac351d34a99b1452c0203 (patch) | |
tree | 1178d85f82390429d19d2f3b233b3bdf72e5b32e /bfd/aoutx.h | |
parent | 41729eb4b085f5e524678a9c0b4d4a6516ad4e6a (diff) | |
download | gdb-ce07dd7c0cc9034fd9aac351d34a99b1452c0203.zip gdb-ce07dd7c0cc9034fd9aac351d34a99b1452c0203.tar.gz gdb-ce07dd7c0cc9034fd9aac351d34a99b1452c0203.tar.bz2 |
[time to file a PR on cvs...]
Various changes to get linker working again for a.out:
* don't set/adjust section file positions or vmas more than once
* use correct page size and segment size when calculating them
* deal with some variations in a.out implementations
Tested on sun4 and sun4->sun3 so far, will be testing further but
needed to get wider exposure&testing. See ChangeLog for details.
Also:
* coffcode.h (coff_write_relocs): Write out swapped reloc, not
pre-swapped version.
* hosts/sparc.h (abort, exit): Hide these names if compiling with
gcc version 2, to avoid warnings.
Diffstat (limited to 'bfd/aoutx.h')
-rw-r--r-- | bfd/aoutx.h | 361 |
1 files changed, 289 insertions, 72 deletions
diff --git a/bfd/aoutx.h b/bfd/aoutx.h index a97cd58..71b56e8 100644 --- a/bfd/aoutx.h +++ b/bfd/aoutx.h @@ -1,3 +1,4 @@ +#define BFD_AOUT_DEBUG /* BFD semi-generic back-end for a.out binaries Copyright (C) 1990-1991 Free Software Foundation, Inc. Written by Cygnus Support. @@ -108,6 +109,15 @@ DESCRIPTION */ +/* Some assumptions: + * Any BFD with D_PAGED set is ZMAGIC, and vice versa. + Doesn't matter what the setting of WP_TEXT is on output, but it'll + get set on input. + * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC. + * Any BFD with both flags clear is OMAGIC. + (Just want to make these explicit, so the conditions tested in this + file make sense if you're more familiar with a.out than with BFD.) */ + #define KEEPIT flags #define KEEPITTYPE int @@ -122,7 +132,7 @@ struct external_exec; #include "aout/stab_gnu.h" #include "aout/ar.h" -void (*bfd_error_trap)(); +extern void (*bfd_error_trap)(); /* SUBSECTION @@ -140,8 +150,10 @@ DESCRIPTION */ #define CTOR_TABLE_RELOC_IDX 2 +#define howto_table_ext NAME(aout,ext_howto_table) +#define howto_table_std NAME(aout,std_howto_table) -static reloc_howto_type howto_table_ext[] = +reloc_howto_type howto_table_ext[] = { HOWTO(RELOC_8, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false), HOWTO(RELOC_16, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false), @@ -172,7 +184,7 @@ static reloc_howto_type howto_table_ext[] = /* Convert standard reloc records to "arelent" format (incl byte swap). */ -static reloc_howto_type howto_table_std[] = { +reloc_howto_type howto_table_std[] = { /* type rs size bsz pcrel bitpos abs ovrf sf name part_inpl readmask setmask pcdone */ HOWTO( 0, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false), HOWTO( 1, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false), @@ -185,7 +197,7 @@ HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedfac }; -bfd_error_vector_type bfd_error_vector; +extern bfd_error_vector_type bfd_error_vector; /* SUBSECTION @@ -318,8 +330,18 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), if (execp->a_syms) abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; - if (N_MAGIC (*execp) == ZMAGIC) abfd->flags |= D_PAGED; - if (N_MAGIC (*execp) == NMAGIC) abfd->flags |= WP_TEXT; + if (N_MAGIC (*execp) == ZMAGIC) + { + abfd->flags |= D_PAGED|WP_TEXT; + adata(abfd).magic = z_magic; + } + else if (N_MAGIC (*execp) == NMAGIC) + { + abfd->flags |= WP_TEXT; + adata(abfd).magic = n_magic; + } + else + adata(abfd).magic = o_magic; bfd_get_start_address (abfd) = execp->a_entry; @@ -569,13 +591,248 @@ DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine), enum bfd_architecture arch AND unsigned long machine) { + bfd_arch_info_type *ainfo; + bfd_default_set_arch_mach(abfd, arch, machine); if (arch != bfd_arch_unknown && NAME(aout,machine_type) (arch, machine) == M_UNKNOWN) return false; /* We can't represent this type */ + + BFD_ASSERT (&adata(abfd) != 0); + ainfo = bfd_get_arch_info (abfd); + if (ainfo->segment_size) + adata(abfd).segment_size = ainfo->segment_size; + if (ainfo->page_size) + adata(abfd).page_size = ainfo->page_size; return true; /* We're easy ... */ } +boolean +DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), + bfd *abfd AND bfd_size_type *text_size AND file_ptr *text_end) +{ + struct internal_exec *execp = exec_hdr (abfd); + if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)) + { + bfd_error = invalid_operation; + return false; + } + if (adata(abfd).magic != undecided_magic) return true; + obj_textsec(abfd)->_raw_size = + align_power(obj_textsec(abfd)->_raw_size, + obj_textsec(abfd)->alignment_power); + + *text_size = obj_textsec (abfd)->_raw_size; + /* Rule (heuristic) for when to pad to a new page. Note that there + * are (at least) two ways demand-paged (ZMAGIC) files have been + * handled. Most Berkeley-based systems start the text segment at + * (PAGE_SIZE). However, newer versions of SUNOS start the text + * segment right after the exec header; the latter is counted in the + * text segment size, and is paged in by the kernel with the rest of + * the text. */ + + /* This perhaps isn't the right way to do this, but made it simpler for me + to understand enough to implement it. Better would probably be to go + right from BFD flags to alignment/positioning characteristics. But the + old code was sloppy enough about handling the flags, and had enough + other magic, that it was a little hard for me to understand. I think + I understand it better now, but I haven't time to do the cleanup this + minute. */ + if (adata(abfd).magic == undecided_magic) + { + if (abfd->flags & D_PAGED) + /* whether or not WP_TEXT is set */ + adata(abfd).magic = z_magic; + else if (abfd->flags & WP_TEXT) + adata(abfd).magic = n_magic; + else + adata(abfd).magic = o_magic; + } + +#ifdef BFD_AOUT_DEBUG /* requires gcc2 */ +#if __GNUC__ >= 2 + fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n", + ({ char *str; + switch (adata(abfd).magic) { + case n_magic: str = "NMAGIC"; break; + case o_magic: str = "OMAGIC"; break; + case z_magic: str = "ZMAGIC"; break; + default: abort (); + } + str; + }), + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->alignment_power, + obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, obj_bsssec(abfd)->alignment_power); +#endif +#endif + + switch (adata(abfd).magic) + { + case o_magic: + { + file_ptr pos = adata (abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad; + + obj_textsec(abfd)->filepos = pos; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + if (!obj_datasec(abfd)->user_set_vma) + { + /* ?? Does alignment in the file image really matter? */ + pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; + obj_textsec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_datasec(abfd)->vma = vma; + } + obj_datasec(abfd)->filepos = pos; + pos += obj_datasec(abfd)->_raw_size; + vma += obj_datasec(abfd)->_raw_size; + if (!obj_bsssec(abfd)->user_set_vma) + { + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; + obj_datasec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_bsssec(abfd)->vma = vma; + } + obj_bsssec(abfd)->filepos = pos; + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, OMAGIC); + } + break; + case z_magic: + { + bfd_size_type data_pad, text_pad; + file_ptr text_end; + CONST struct aout_backend_data *abdp; + int ztih; + bfd_vma data_vma; + + abdp = aout_backend_info (abfd); + ztih = abdp && abdp->text_includes_header; + obj_textsec(abfd)->filepos = (ztih + ? adata(abfd).exec_bytes_size + : adata(abfd).page_size); + if (! obj_textsec(abfd)->user_set_vma) + /* ?? Do we really need to check for relocs here? */ + obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) + ? 0 + : (ztih + ? (abdp->default_text_vma + + adata(abfd).exec_bytes_size) + : abdp->default_text_vma)); + /* Could take strange alignment of text section into account here? */ + + /* Find start of data. */ + text_end = obj_textsec(abfd)->filepos + obj_textsec(abfd)->_raw_size; + text_pad = BFD_ALIGN (text_end, adata(abfd).page_size) - text_end; + obj_textsec(abfd)->_raw_size += text_pad; + text_end += text_pad; + + if (!obj_datasec(abfd)->user_set_vma) + { + bfd_vma vma; + vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + } + data_vma = obj_datasec(abfd)->vma; + if (abdp && abdp->zmagic_mapped_contiguous) + { + text_pad = (obj_datasec(abfd)->vma + - obj_textsec(abfd)->vma + - obj_textsec(abfd)->_raw_size); + obj_textsec(abfd)->_raw_size += text_pad; + } + obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos + + obj_textsec(abfd)->_raw_size); + + /* Fix up exec header while we're at it. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + if (ztih) + execp->a_text += adata(abfd).exec_bytes_size; + N_SET_MAGIC (*execp, ZMAGIC); + /* Spec says data section should be rounded up to page boundary. */ + /* If extra space in page is left after data section, fudge data + in the header so that the bss section looks smaller by that + amount. We'll start the bss section there, and lie to the OS. */ + obj_datasec(abfd)->_raw_size + = align_power (obj_datasec(abfd)->_raw_size, + obj_bsssec(abfd)->alignment_power); + execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, + adata(abfd).page_size); + data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; + /* This code is almost surely botched. It'll only get tested + for the case where the application does explicitly set the VMA + of the BSS section. */ + if (obj_bsssec(abfd)->user_set_vma + && (obj_bsssec(abfd)->vma + > BFD_ALIGN (obj_datasec(abfd)->vma + + obj_datasec(abfd)->_raw_size, + adata(abfd).page_size))) + { + /* Can't play with squeezing into data pages; fix this code. */ + abort (); + } + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma + + obj_datasec(abfd)->_raw_size); + if (data_pad > obj_bsssec(abfd)->_raw_size) + execp->a_bss = 0; + else + execp->a_bss = obj_bsssec(abfd)->_raw_size - data_pad; + } + break; + case n_magic: + { + CONST struct aout_backend_data *abdp; + file_ptr pos = adata(abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad; + + obj_textsec(abfd)->filepos = pos; + if (!obj_textsec(abfd)->user_set_vma) + obj_textsec(abfd)->vma = vma; + else + vma = obj_textsec(abfd)->vma; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + obj_datasec(abfd)->filepos = pos; + if (!obj_datasec(abfd)->user_set_vma) + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + vma = obj_datasec(abfd)->vma; + + /* Since BSS follows data immediately, see if it needs alignment. */ + vma += obj_datasec(abfd)->_raw_size; + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; + obj_datasec(abfd)->_raw_size += pad; + pos += obj_datasec(abfd)->_raw_size; + + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = vma; + else + vma = obj_bsssec(abfd)->vma; + } + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, NMAGIC); + break; + default: + abort (); + } +#ifdef BFD_AOUT_DEBUG + fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n", + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->filepos, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->filepos, + obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size); +#endif +} + /* FUNCTION aout_<size>new_section_hook @@ -634,6 +891,7 @@ boolean { file_ptr text_end; bfd_size_type text_size; + if (abfd->output_has_begun == false) { /* set by bfd.c handler */ switch (abfd->direction) @@ -642,55 +900,14 @@ boolean case no_direction: bfd_error = invalid_operation; return false; - + + case write_direction: + if (NAME(aout,adjust_sizes_and_vmas) (abfd, + &text_size, + &text_end) == false) + return false; case both_direction: break; - - case write_direction: - if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)) - { - bfd_error = invalid_operation; - return false; - } - obj_textsec(abfd)->_raw_size = - align_power(obj_textsec(abfd)->_raw_size, - obj_textsec(abfd)->alignment_power); - - text_size = obj_textsec (abfd)->_raw_size; - /* Rule (heuristic) for when to pad to a new page. - * Note that there are (at least) two ways demand-paged - * (ZMAGIC) files have been handled. Most Berkeley-based systems - * start the text segment at (PAGE_SIZE). However, newer - * versions of SUNOS start the text segment right after the - * exec header; the latter is counted in the text segment size, - * and is paged in by the kernel with the rest of the text. */ - if (!(abfd->flags & D_PAGED)) - { /* Not demand-paged. */ - obj_textsec(abfd)->filepos = adata(abfd).exec_bytes_size; - } - else if (obj_textsec(abfd)->vma % adata(abfd).page_size - < adata(abfd).exec_bytes_size) - { /* Old-style demand-paged. */ - obj_textsec(abfd)->filepos = adata(abfd).page_size; - } - else - { /* Sunos-style demand-paged. */ - obj_textsec(abfd)->filepos = adata(abfd).exec_bytes_size; - text_size += adata(abfd).exec_bytes_size; - } - text_end = obj_textsec(abfd)->_raw_size + obj_textsec(abfd)->filepos; - if (abfd->flags & (D_PAGED|WP_TEXT)) - { - bfd_size_type text_pad = - BFD_ALIGN(text_size, adata(abfd).page_size) - - text_size; - text_end += text_pad; - obj_textsec(abfd)->_raw_size += text_pad; - } - obj_datasec(abfd)->filepos = text_end; - obj_datasec(abfd)->_raw_size = - align_power(obj_datasec(abfd)->_raw_size, - obj_datasec(abfd)->alignment_power); } } @@ -1162,13 +1379,13 @@ DEFUN(NAME(aout,get_symtab),(abfd, location), { unsigned int counter = 0; aout_symbol_type *symbase; - + if (!NAME(aout,slurp_symbol_table)(abfd)) return 0; - + for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);) *(location++) = (asymbol *)( symbase++); *location++ =0; - return bfd_get_symcount(abfd); + return bfd_get_symcount (abfd); } @@ -1189,9 +1406,9 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), int r_baserel, r_jmptable, r_relative; unsigned int r_addend; asection *output_section = sym->section->output_section; - + PUT_WORD(abfd, g->address, natptr->r_address); - + r_length = g->howto->size ; /* Size as a power of two */ r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ /* r_baserel, r_jmptable, r_relative??? FIXME-soon */ @@ -1203,21 +1420,21 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), /* name was clobbered by aout_write_syms to be symbol index */ -if (output_section == &bfd_com_section - || output_section == &bfd_abs_section - || output_section == &bfd_und_section) - { - /* Fill in symbol */ - r_extern = 1; - r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT); - } + if (output_section == &bfd_com_section + || output_section == &bfd_abs_section + || output_section == &bfd_und_section) + { + /* Fill in symbol */ + r_extern = 1; + r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT); + } else - { - /* Just an ordinary section */ - r_extern = 0; - r_index = output_section->target_index; - } - + { + /* Just an ordinary section */ + r_extern = 0; + r_index = output_section->target_index; + } + /* now the fun stuff */ if (abfd->xvec->header_byteorder_big_p != false) { natptr->r_index[0] = r_index >> 16; |