aoutx.h revision 61843
133965Sjdp/* BFD semi-generic back-end for a.out binaries. 261843Sobrien Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 338889Sjdp Free Software Foundation, Inc. 433965Sjdp Written by Cygnus Support. 533965Sjdp 633965SjdpThis file is part of BFD, the Binary File Descriptor library. 733965Sjdp 833965SjdpThis program is free software; you can redistribute it and/or modify 933965Sjdpit under the terms of the GNU General Public License as published by 1033965Sjdpthe Free Software Foundation; either version 2 of the License, or 1133965Sjdp(at your option) any later version. 1233965Sjdp 1333965SjdpThis program is distributed in the hope that it will be useful, 1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965SjdpGNU General Public License for more details. 1733965Sjdp 1833965SjdpYou should have received a copy of the GNU General Public License 1933965Sjdpalong with this program; if not, write to the Free Software 2033965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2133965Sjdp 2233965Sjdp/* 2333965SjdpSECTION 2433965Sjdp a.out backends 2533965Sjdp 2633965Sjdp 2733965SjdpDESCRIPTION 2833965Sjdp 2933965Sjdp BFD supports a number of different flavours of a.out format, 3033965Sjdp though the major differences are only the sizes of the 3133965Sjdp structures on disk, and the shape of the relocation 3233965Sjdp information. 3333965Sjdp 3433965Sjdp The support is split into a basic support file @file{aoutx.h} 3533965Sjdp and other files which derive functions from the base. One 3633965Sjdp derivation file is @file{aoutf1.h} (for a.out flavour 1), and 3733965Sjdp adds to the basic a.out functions support for sun3, sun4, 386 3833965Sjdp and 29k a.out files, to create a target jump vector for a 3933965Sjdp specific target. 4033965Sjdp 4133965Sjdp This information is further split out into more specific files 4233965Sjdp for each machine, including @file{sunos.c} for sun3 and sun4, 4333965Sjdp @file{newsos3.c} for the Sony NEWS, and @file{demo64.c} for a 4433965Sjdp demonstration of a 64 bit a.out format. 4533965Sjdp 4633965Sjdp The base file @file{aoutx.h} defines general mechanisms for 4733965Sjdp reading and writing records to and from disk and various 4833965Sjdp other methods which BFD requires. It is included by 4933965Sjdp @file{aout32.c} and @file{aout64.c} to form the names 5033965Sjdp <<aout_32_swap_exec_header_in>>, <<aout_64_swap_exec_header_in>>, etc. 5133965Sjdp 5233965Sjdp As an example, this is what goes on to make the back end for a 5333965Sjdp sun4, from @file{aout32.c}: 5433965Sjdp 5533965Sjdp| #define ARCH_SIZE 32 5633965Sjdp| #include "aoutx.h" 5733965Sjdp 5833965Sjdp Which exports names: 5933965Sjdp 6033965Sjdp| ... 6133965Sjdp| aout_32_canonicalize_reloc 6233965Sjdp| aout_32_find_nearest_line 6333965Sjdp| aout_32_get_lineno 6433965Sjdp| aout_32_get_reloc_upper_bound 6533965Sjdp| ... 6633965Sjdp 6733965Sjdp from @file{sunos.c}: 6833965Sjdp 6933965Sjdp| #define TARGET_NAME "a.out-sunos-big" 7033965Sjdp| #define VECNAME sunos_big_vec 7133965Sjdp| #include "aoutf1.h" 7233965Sjdp 7333965Sjdp requires all the names from @file{aout32.c}, and produces the jump vector 7433965Sjdp 7533965Sjdp| sunos_big_vec 7633965Sjdp 7733965Sjdp The file @file{host-aout.c} is a special case. It is for a large set 7833965Sjdp of hosts that use ``more or less standard'' a.out files, and 7933965Sjdp for which cross-debugging is not interesting. It uses the 8033965Sjdp standard 32-bit a.out support routines, but determines the 8133965Sjdp file offsets and addresses of the text, data, and BSS 8233965Sjdp sections, the machine architecture and machine type, and the 8333965Sjdp entry point address, in a host-dependent manner. Once these 8433965Sjdp values have been determined, generic code is used to handle 8533965Sjdp the object file. 8633965Sjdp 8733965Sjdp When porting it to run on a new system, you must supply: 8833965Sjdp 8933965Sjdp| HOST_PAGE_SIZE 9033965Sjdp| HOST_SEGMENT_SIZE 9133965Sjdp| HOST_MACHINE_ARCH (optional) 9233965Sjdp| HOST_MACHINE_MACHINE (optional) 9333965Sjdp| HOST_TEXT_START_ADDR 9433965Sjdp| HOST_STACK_END_ADDR 9533965Sjdp 9633965Sjdp in the file @file{../include/sys/h-@var{XXX}.h} (for your host). These 9733965Sjdp values, plus the structures and macros defined in @file{a.out.h} on 9833965Sjdp your host system, will produce a BFD target that will access 9933965Sjdp ordinary a.out files on your host. To configure a new machine 10033965Sjdp to use @file{host-aout.c}, specify: 10133965Sjdp 10233965Sjdp| TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec 10333965Sjdp| TDEPFILES= host-aout.o trad-core.o 10433965Sjdp 10533965Sjdp in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in} 10633965Sjdp to use the 10733965Sjdp @file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your 10833965Sjdp configuration is selected. 10933965Sjdp 11033965Sjdp*/ 11133965Sjdp 11233965Sjdp/* Some assumptions: 11333965Sjdp * Any BFD with D_PAGED set is ZMAGIC, and vice versa. 11433965Sjdp Doesn't matter what the setting of WP_TEXT is on output, but it'll 11533965Sjdp get set on input. 11633965Sjdp * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC. 11733965Sjdp * Any BFD with both flags clear is OMAGIC. 11833965Sjdp (Just want to make these explicit, so the conditions tested in this 11933965Sjdp file make sense if you're more familiar with a.out than with BFD.) */ 12033965Sjdp 12133965Sjdp#define KEEPIT udata.i 12233965Sjdp 12333965Sjdp#include <ctype.h> 12433965Sjdp#include "bfd.h" 12560484Sobrien#include "sysdep.h" 12633965Sjdp#include "bfdlink.h" 12733965Sjdp 12833965Sjdp#include "libaout.h" 12933965Sjdp#include "libbfd.h" 13033965Sjdp#include "aout/aout64.h" 13133965Sjdp#include "aout/stab_gnu.h" 13233965Sjdp#include "aout/ar.h" 13333965Sjdp 13433965Sjdpstatic boolean aout_get_external_symbols PARAMS ((bfd *)); 13533965Sjdpstatic boolean translate_from_native_sym_flags 13633965Sjdp PARAMS ((bfd *, aout_symbol_type *)); 13733965Sjdpstatic boolean translate_to_native_sym_flags 13833965Sjdp PARAMS ((bfd *, asymbol *, struct external_nlist *)); 13933965Sjdpstatic void adjust_o_magic PARAMS ((bfd *, struct internal_exec *)); 14033965Sjdpstatic void adjust_z_magic PARAMS ((bfd *, struct internal_exec *)); 14133965Sjdpstatic void adjust_n_magic PARAMS ((bfd *, struct internal_exec *)); 14233965Sjdp 14333965Sjdp/* 14433965SjdpSUBSECTION 14533965Sjdp Relocations 14633965Sjdp 14733965SjdpDESCRIPTION 14833965Sjdp The file @file{aoutx.h} provides for both the @emph{standard} 14933965Sjdp and @emph{extended} forms of a.out relocation records. 15033965Sjdp 15133965Sjdp The standard records contain only an 15233965Sjdp address, a symbol index, and a type field. The extended records 15333965Sjdp (used on 29ks and sparcs) also have a full integer for an 15433965Sjdp addend. 15533965Sjdp 15633965Sjdp*/ 15733965Sjdp#ifndef CTOR_TABLE_RELOC_HOWTO 15833965Sjdp#define CTOR_TABLE_RELOC_IDX 2 15933965Sjdp#define CTOR_TABLE_RELOC_HOWTO(BFD) ((obj_reloc_entry_size(BFD) == RELOC_EXT_SIZE \ 16033965Sjdp ? howto_table_ext : howto_table_std) \ 16133965Sjdp + CTOR_TABLE_RELOC_IDX) 16233965Sjdp#endif 16333965Sjdp 16433965Sjdp#ifndef MY_swap_std_reloc_in 16533965Sjdp#define MY_swap_std_reloc_in NAME(aout,swap_std_reloc_in) 16633965Sjdp#endif 16733965Sjdp 16833965Sjdp#ifndef MY_swap_std_reloc_out 16933965Sjdp#define MY_swap_std_reloc_out NAME(aout,swap_std_reloc_out) 17033965Sjdp#endif 17133965Sjdp 17233965Sjdp#ifndef MY_final_link_relocate 17333965Sjdp#define MY_final_link_relocate _bfd_final_link_relocate 17433965Sjdp#endif 17533965Sjdp 17633965Sjdp#ifndef MY_relocate_contents 17733965Sjdp#define MY_relocate_contents _bfd_relocate_contents 17833965Sjdp#endif 17933965Sjdp 18033965Sjdp#define howto_table_ext NAME(aout,ext_howto_table) 18133965Sjdp#define howto_table_std NAME(aout,std_howto_table) 18233965Sjdp 18333965Sjdpreloc_howto_type howto_table_ext[] = 18433965Sjdp{ 18533965Sjdp /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ 18633965Sjdp HOWTO(RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", false, 0,0x000000ff, false), 18733965Sjdp HOWTO(RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", false, 0,0x0000ffff, false), 18833965Sjdp HOWTO(RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", false, 0,0xffffffff, false), 18933965Sjdp HOWTO(RELOC_DISP8, 0, 0, 8, true, 0, complain_overflow_signed,0,"DISP8", false, 0,0x000000ff, false), 19033965Sjdp HOWTO(RELOC_DISP16, 0, 1, 16, true, 0, complain_overflow_signed,0,"DISP16", false, 0,0x0000ffff, false), 19133965Sjdp HOWTO(RELOC_DISP32, 0, 2, 32, true, 0, complain_overflow_signed,0,"DISP32", false, 0,0xffffffff, false), 19233965Sjdp HOWTO(RELOC_WDISP30,2, 2, 30, true, 0, complain_overflow_signed,0,"WDISP30", false, 0,0x3fffffff, false), 19333965Sjdp HOWTO(RELOC_WDISP22,2, 2, 22, true, 0, complain_overflow_signed,0,"WDISP22", false, 0,0x003fffff, false), 19433965Sjdp HOWTO(RELOC_HI22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"HI22", false, 0,0x003fffff, false), 19533965Sjdp HOWTO(RELOC_22, 0, 2, 22, false, 0, complain_overflow_bitfield,0,"22", false, 0,0x003fffff, false), 19633965Sjdp HOWTO(RELOC_13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"13", false, 0,0x00001fff, false), 19733965Sjdp HOWTO(RELOC_LO10, 0, 2, 10, false, 0, complain_overflow_dont,0,"LO10", false, 0,0x000003ff, false), 19833965Sjdp HOWTO(RELOC_SFA_BASE,0, 2, 32, false, 0, complain_overflow_bitfield,0,"SFA_BASE", false, 0,0xffffffff, false), 19933965Sjdp HOWTO(RELOC_SFA_OFF13,0,2, 32, false, 0, complain_overflow_bitfield,0,"SFA_OFF13",false, 0,0xffffffff, false), 20033965Sjdp HOWTO(RELOC_BASE10, 0, 2, 10, false, 0, complain_overflow_dont,0,"BASE10", false, 0,0x000003ff, false), 20160484Sobrien HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, complain_overflow_signed,0,"BASE13", false, 0,0x00001fff, false), 20233965Sjdp HOWTO(RELOC_BASE22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"BASE22", false, 0,0x003fffff, false), 20333965Sjdp HOWTO(RELOC_PC10, 0, 2, 10, true, 0, complain_overflow_dont,0,"PC10", false, 0,0x000003ff, true), 20433965Sjdp HOWTO(RELOC_PC22, 10, 2, 22, true, 0, complain_overflow_signed,0,"PC22", false, 0,0x003fffff, true), 20533965Sjdp HOWTO(RELOC_JMP_TBL,2, 2, 30, true, 0, complain_overflow_signed,0,"JMP_TBL", false, 0,0x3fffffff, false), 20633965Sjdp HOWTO(RELOC_SEGOFF16,0, 2, 0, false, 0, complain_overflow_bitfield,0,"SEGOFF16", false, 0,0x00000000, false), 20733965Sjdp HOWTO(RELOC_GLOB_DAT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"GLOB_DAT", false, 0,0x00000000, false), 20833965Sjdp HOWTO(RELOC_JMP_SLOT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_SLOT", false, 0,0x00000000, false), 20933965Sjdp HOWTO(RELOC_RELATIVE,0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false), 21060484Sobrien HOWTO(0, 0, 0, 0, false, 0, complain_overflow_dont, 0, "R_SPARC_NONE", false,0,0x00000000,true), 21160484Sobrien HOWTO(0, 0, 0, 0, false, 0, complain_overflow_dont, 0, "R_SPARC_NONE", false,0,0x00000000,true), 21260484Sobrien#define RELOC_SPARC_REV32 RELOC_WDISP19 21360484Sobrien HOWTO(RELOC_SPARC_REV32, 0, 2, 32, false, 0, complain_overflow_dont,0,"R_SPARC_REV32", false, 0,0xffffffff, false), 21433965Sjdp}; 21533965Sjdp 21633965Sjdp/* Convert standard reloc records to "arelent" format (incl byte swap). */ 21733965Sjdp 21833965Sjdpreloc_howto_type howto_table_std[] = { 21933965Sjdp /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ 22033965SjdpHOWTO( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false), 22133965SjdpHOWTO( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false), 22233965SjdpHOWTO( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false), 22333965SjdpHOWTO( 3, 0, 4, 64, false, 0, complain_overflow_bitfield,0,"64", true, 0xdeaddead,0xdeaddead, false), 22433965SjdpHOWTO( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", true, 0x000000ff,0x000000ff, false), 22533965SjdpHOWTO( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, false), 22633965SjdpHOWTO( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, false), 22733965SjdpHOWTO( 7, 0, 4, 64, true, 0, complain_overflow_signed, 0,"DISP64", true, 0xfeedface,0xfeedface, false), 22833965SjdpHOWTO( 8, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"GOT_REL", false, 0,0x00000000, false), 22933965SjdpHOWTO( 9, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"BASE16", false,0xffffffff,0xffffffff, false), 23033965SjdpHOWTO(10, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"BASE32", false,0xffffffff,0xffffffff, false), 23160484SobrienEMPTY_HOWTO (-1), 23260484SobrienEMPTY_HOWTO (-1), 23360484SobrienEMPTY_HOWTO (-1), 23460484SobrienEMPTY_HOWTO (-1), 23560484SobrienEMPTY_HOWTO (-1), 23633965Sjdp HOWTO(16, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_TABLE", false, 0,0x00000000, false), 23760484SobrienEMPTY_HOWTO (-1), 23860484SobrienEMPTY_HOWTO (-1), 23960484SobrienEMPTY_HOWTO (-1), 24060484SobrienEMPTY_HOWTO (-1), 24160484SobrienEMPTY_HOWTO (-1), 24260484SobrienEMPTY_HOWTO (-1), 24360484SobrienEMPTY_HOWTO (-1), 24460484SobrienEMPTY_HOWTO (-1), 24560484SobrienEMPTY_HOWTO (-1), 24660484SobrienEMPTY_HOWTO (-1), 24760484SobrienEMPTY_HOWTO (-1), 24860484SobrienEMPTY_HOWTO (-1), 24960484SobrienEMPTY_HOWTO (-1), 25060484SobrienEMPTY_HOWTO (-1), 25160484SobrienEMPTY_HOWTO (-1), 25233965Sjdp HOWTO(32, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false), 25360484SobrienEMPTY_HOWTO (-1), 25460484SobrienEMPTY_HOWTO (-1), 25560484SobrienEMPTY_HOWTO (-1), 25660484SobrienEMPTY_HOWTO (-1), 25760484SobrienEMPTY_HOWTO (-1), 25860484SobrienEMPTY_HOWTO (-1), 25960484SobrienEMPTY_HOWTO (-1), 26033965Sjdp HOWTO(40, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASEREL", false, 0,0x00000000, false), 26133965Sjdp}; 26233965Sjdp 26333965Sjdp#define TABLE_SIZE(TABLE) (sizeof(TABLE)/sizeof(TABLE[0])) 26433965Sjdp 26533965Sjdpreloc_howto_type * 26633965SjdpNAME(aout,reloc_type_lookup) (abfd,code) 26733965Sjdp bfd *abfd; 26833965Sjdp bfd_reloc_code_real_type code; 26933965Sjdp{ 27033965Sjdp#define EXT(i,j) case i: return &howto_table_ext[j] 27133965Sjdp#define STD(i,j) case i: return &howto_table_std[j] 27233965Sjdp int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE; 27333965Sjdp if (code == BFD_RELOC_CTOR) 27433965Sjdp switch (bfd_get_arch_info (abfd)->bits_per_address) 27533965Sjdp { 27633965Sjdp case 32: 27733965Sjdp code = BFD_RELOC_32; 27833965Sjdp break; 27933965Sjdp case 64: 28033965Sjdp code = BFD_RELOC_64; 28133965Sjdp break; 28233965Sjdp } 28333965Sjdp if (ext) 28433965Sjdp switch (code) 28533965Sjdp { 28633965Sjdp EXT (BFD_RELOC_32, 2); 28733965Sjdp EXT (BFD_RELOC_HI22, 8); 28833965Sjdp EXT (BFD_RELOC_LO10, 11); 28933965Sjdp EXT (BFD_RELOC_32_PCREL_S2, 6); 29033965Sjdp EXT (BFD_RELOC_SPARC_WDISP22, 7); 29133965Sjdp EXT (BFD_RELOC_SPARC13, 10); 29233965Sjdp EXT (BFD_RELOC_SPARC_GOT10, 14); 29333965Sjdp EXT (BFD_RELOC_SPARC_BASE13, 15); 29433965Sjdp EXT (BFD_RELOC_SPARC_GOT13, 15); 29533965Sjdp EXT (BFD_RELOC_SPARC_GOT22, 16); 29633965Sjdp EXT (BFD_RELOC_SPARC_PC10, 17); 29733965Sjdp EXT (BFD_RELOC_SPARC_PC22, 18); 29833965Sjdp EXT (BFD_RELOC_SPARC_WPLT30, 19); 29960484Sobrien EXT (BFD_RELOC_SPARC_REV32, 26); 30033965Sjdp default: return (reloc_howto_type *) NULL; 30133965Sjdp } 30233965Sjdp else 30333965Sjdp /* std relocs */ 30433965Sjdp switch (code) 30533965Sjdp { 30633965Sjdp STD (BFD_RELOC_16, 1); 30733965Sjdp STD (BFD_RELOC_32, 2); 30833965Sjdp STD (BFD_RELOC_8_PCREL, 4); 30933965Sjdp STD (BFD_RELOC_16_PCREL, 5); 31033965Sjdp STD (BFD_RELOC_32_PCREL, 6); 31133965Sjdp STD (BFD_RELOC_16_BASEREL, 9); 31233965Sjdp STD (BFD_RELOC_32_BASEREL, 10); 31333965Sjdp default: return (reloc_howto_type *) NULL; 31433965Sjdp } 31533965Sjdp} 31633965Sjdp 31733965Sjdp/* 31833965SjdpSUBSECTION 31933965Sjdp Internal entry points 32033965Sjdp 32133965SjdpDESCRIPTION 32233965Sjdp @file{aoutx.h} exports several routines for accessing the 32333965Sjdp contents of an a.out file, which are gathered and exported in 32433965Sjdp turn by various format specific files (eg sunos.c). 32533965Sjdp 32633965Sjdp*/ 32733965Sjdp 32833965Sjdp/* 32933965SjdpFUNCTION 33033965Sjdp aout_@var{size}_swap_exec_header_in 33133965Sjdp 33233965SjdpSYNOPSIS 33333965Sjdp void aout_@var{size}_swap_exec_header_in, 33433965Sjdp (bfd *abfd, 33533965Sjdp struct external_exec *raw_bytes, 33633965Sjdp struct internal_exec *execp); 33733965Sjdp 33833965SjdpDESCRIPTION 33933965Sjdp Swap the information in an executable header @var{raw_bytes} taken 34033965Sjdp from a raw byte stream memory image into the internal exec header 34133965Sjdp structure @var{execp}. 34233965Sjdp*/ 34333965Sjdp 34433965Sjdp#ifndef NAME_swap_exec_header_in 34533965Sjdpvoid 34633965SjdpNAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp) 34733965Sjdp bfd *abfd; 34833965Sjdp struct external_exec *raw_bytes; 34933965Sjdp struct internal_exec *execp; 35033965Sjdp{ 35133965Sjdp struct external_exec *bytes = (struct external_exec *)raw_bytes; 35233965Sjdp 35333965Sjdp /* The internal_exec structure has some fields that are unused in this 35433965Sjdp configuration (IE for i960), so ensure that all such uninitialized 35533965Sjdp fields are zero'd out. There are places where two of these structs 35633965Sjdp are memcmp'd, and thus the contents do matter. */ 35733965Sjdp memset ((PTR) execp, 0, sizeof (struct internal_exec)); 35833965Sjdp /* Now fill in fields in the execp, from the bytes in the raw data. */ 35933965Sjdp execp->a_info = bfd_h_get_32 (abfd, bytes->e_info); 36033965Sjdp execp->a_text = GET_WORD (abfd, bytes->e_text); 36133965Sjdp execp->a_data = GET_WORD (abfd, bytes->e_data); 36233965Sjdp execp->a_bss = GET_WORD (abfd, bytes->e_bss); 36333965Sjdp execp->a_syms = GET_WORD (abfd, bytes->e_syms); 36433965Sjdp execp->a_entry = GET_WORD (abfd, bytes->e_entry); 36533965Sjdp execp->a_trsize = GET_WORD (abfd, bytes->e_trsize); 36633965Sjdp execp->a_drsize = GET_WORD (abfd, bytes->e_drsize); 36733965Sjdp} 36833965Sjdp#define NAME_swap_exec_header_in NAME(aout,swap_exec_header_in) 36933965Sjdp#endif 37033965Sjdp 37133965Sjdp/* 37233965SjdpFUNCTION 37333965Sjdp aout_@var{size}_swap_exec_header_out 37433965Sjdp 37533965SjdpSYNOPSIS 37633965Sjdp void aout_@var{size}_swap_exec_header_out 37733965Sjdp (bfd *abfd, 37833965Sjdp struct internal_exec *execp, 37933965Sjdp struct external_exec *raw_bytes); 38033965Sjdp 38133965SjdpDESCRIPTION 38233965Sjdp Swap the information in an internal exec header structure 38333965Sjdp @var{execp} into the buffer @var{raw_bytes} ready for writing to disk. 38433965Sjdp*/ 38533965Sjdpvoid 38633965SjdpNAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes) 38733965Sjdp bfd *abfd; 38833965Sjdp struct internal_exec *execp; 38933965Sjdp struct external_exec *raw_bytes; 39033965Sjdp{ 39133965Sjdp struct external_exec *bytes = (struct external_exec *)raw_bytes; 39233965Sjdp 39333965Sjdp /* Now fill in fields in the raw data, from the fields in the exec struct. */ 39433965Sjdp bfd_h_put_32 (abfd, execp->a_info , bytes->e_info); 39533965Sjdp PUT_WORD (abfd, execp->a_text , bytes->e_text); 39633965Sjdp PUT_WORD (abfd, execp->a_data , bytes->e_data); 39733965Sjdp PUT_WORD (abfd, execp->a_bss , bytes->e_bss); 39833965Sjdp PUT_WORD (abfd, execp->a_syms , bytes->e_syms); 39933965Sjdp PUT_WORD (abfd, execp->a_entry , bytes->e_entry); 40033965Sjdp PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize); 40133965Sjdp PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize); 40233965Sjdp} 40333965Sjdp 40433965Sjdp/* Make all the section for an a.out file. */ 40533965Sjdp 40633965Sjdpboolean 40733965SjdpNAME(aout,make_sections) (abfd) 40833965Sjdp bfd *abfd; 40933965Sjdp{ 41033965Sjdp if (obj_textsec (abfd) == (asection *) NULL 41133965Sjdp && bfd_make_section (abfd, ".text") == (asection *) NULL) 41233965Sjdp return false; 41333965Sjdp if (obj_datasec (abfd) == (asection *) NULL 41433965Sjdp && bfd_make_section (abfd, ".data") == (asection *) NULL) 41533965Sjdp return false; 41633965Sjdp if (obj_bsssec (abfd) == (asection *) NULL 41733965Sjdp && bfd_make_section (abfd, ".bss") == (asection *) NULL) 41833965Sjdp return false; 41933965Sjdp return true; 42033965Sjdp} 42133965Sjdp 42233965Sjdp/* 42333965SjdpFUNCTION 42433965Sjdp aout_@var{size}_some_aout_object_p 42533965Sjdp 42633965SjdpSYNOPSIS 42733965Sjdp const bfd_target *aout_@var{size}_some_aout_object_p 42833965Sjdp (bfd *abfd, 42933965Sjdp const bfd_target *(*callback_to_real_object_p)()); 43033965Sjdp 43133965SjdpDESCRIPTION 43233965Sjdp Some a.out variant thinks that the file open in @var{abfd} 43333965Sjdp checking is an a.out file. Do some more checking, and set up 43433965Sjdp for access if it really is. Call back to the calling 43533965Sjdp environment's "finish up" function just before returning, to 43633965Sjdp handle any last-minute setup. 43733965Sjdp*/ 43833965Sjdp 43933965Sjdpconst bfd_target * 44033965SjdpNAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p) 44133965Sjdp bfd *abfd; 44233965Sjdp struct internal_exec *execp; 44333965Sjdp const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *)); 44433965Sjdp{ 44533965Sjdp struct aout_data_struct *rawptr, *oldrawptr; 44633965Sjdp const bfd_target *result; 44733965Sjdp 44833965Sjdp rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, sizeof (struct aout_data_struct )); 44933965Sjdp if (rawptr == NULL) 45033965Sjdp return 0; 45133965Sjdp 45233965Sjdp oldrawptr = abfd->tdata.aout_data; 45333965Sjdp abfd->tdata.aout_data = rawptr; 45433965Sjdp 45533965Sjdp /* Copy the contents of the old tdata struct. 45633965Sjdp In particular, we want the subformat, since for hpux it was set in 45733965Sjdp hp300hpux.c:swap_exec_header_in and will be used in 45833965Sjdp hp300hpux.c:callback. */ 45933965Sjdp if (oldrawptr != NULL) 46033965Sjdp *abfd->tdata.aout_data = *oldrawptr; 46133965Sjdp 46233965Sjdp abfd->tdata.aout_data->a.hdr = &rawptr->e; 46333965Sjdp *(abfd->tdata.aout_data->a.hdr) = *execp; /* Copy in the internal_exec struct */ 46433965Sjdp execp = abfd->tdata.aout_data->a.hdr; 46533965Sjdp 46633965Sjdp /* Set the file flags */ 46733965Sjdp abfd->flags = BFD_NO_FLAGS; 46833965Sjdp if (execp->a_drsize || execp->a_trsize) 46933965Sjdp abfd->flags |= HAS_RELOC; 47033965Sjdp /* Setting of EXEC_P has been deferred to the bottom of this function */ 47133965Sjdp if (execp->a_syms) 47233965Sjdp abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; 47333965Sjdp if (N_DYNAMIC(*execp)) 47433965Sjdp abfd->flags |= DYNAMIC; 47533965Sjdp 47633965Sjdp if (N_MAGIC (*execp) == ZMAGIC) 47733965Sjdp { 47833965Sjdp abfd->flags |= D_PAGED | WP_TEXT; 47933965Sjdp adata (abfd).magic = z_magic; 48033965Sjdp } 48133965Sjdp else if (N_MAGIC (*execp) == QMAGIC) 48233965Sjdp { 48333965Sjdp abfd->flags |= D_PAGED | WP_TEXT; 48433965Sjdp adata (abfd).magic = z_magic; 48533965Sjdp adata (abfd).subformat = q_magic_format; 48633965Sjdp } 48733965Sjdp else if (N_MAGIC (*execp) == NMAGIC) 48833965Sjdp { 48933965Sjdp abfd->flags |= WP_TEXT; 49033965Sjdp adata (abfd).magic = n_magic; 49133965Sjdp } 49233965Sjdp else if (N_MAGIC (*execp) == OMAGIC 49333965Sjdp || N_MAGIC (*execp) == BMAGIC) 49433965Sjdp adata (abfd).magic = o_magic; 49533965Sjdp else 49633965Sjdp { 49733965Sjdp /* Should have been checked with N_BADMAG before this routine 49833965Sjdp was called. */ 49933965Sjdp abort (); 50033965Sjdp } 50133965Sjdp 50233965Sjdp bfd_get_start_address (abfd) = execp->a_entry; 50333965Sjdp 50433965Sjdp obj_aout_symbols (abfd) = (aout_symbol_type *)NULL; 50533965Sjdp bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist); 50633965Sjdp 50733965Sjdp /* The default relocation entry size is that of traditional V7 Unix. */ 50833965Sjdp obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 50933965Sjdp 51033965Sjdp /* The default symbol entry size is that of traditional Unix. */ 51133965Sjdp obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE; 51233965Sjdp 51333965Sjdp#ifdef USE_MMAP 51433965Sjdp bfd_init_window (&obj_aout_sym_window (abfd)); 51533965Sjdp bfd_init_window (&obj_aout_string_window (abfd)); 51633965Sjdp#endif 51733965Sjdp obj_aout_external_syms (abfd) = NULL; 51833965Sjdp obj_aout_external_strings (abfd) = NULL; 51933965Sjdp obj_aout_sym_hashes (abfd) = NULL; 52033965Sjdp 52133965Sjdp if (! NAME(aout,make_sections) (abfd)) 52233965Sjdp return NULL; 52333965Sjdp 52433965Sjdp obj_datasec (abfd)->_raw_size = execp->a_data; 52533965Sjdp obj_bsssec (abfd)->_raw_size = execp->a_bss; 52633965Sjdp 52733965Sjdp obj_textsec (abfd)->flags = 52833965Sjdp (execp->a_trsize != 0 52933965Sjdp ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) 53033965Sjdp : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); 53133965Sjdp obj_datasec (abfd)->flags = 53233965Sjdp (execp->a_drsize != 0 53333965Sjdp ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) 53433965Sjdp : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); 53533965Sjdp obj_bsssec (abfd)->flags = SEC_ALLOC; 53633965Sjdp 53733965Sjdp#ifdef THIS_IS_ONLY_DOCUMENTATION 53833965Sjdp /* The common code can't fill in these things because they depend 53933965Sjdp on either the start address of the text segment, the rounding 54033965Sjdp up of virtual addresses between segments, or the starting file 54133965Sjdp position of the text segment -- all of which varies among different 54233965Sjdp versions of a.out. */ 54333965Sjdp 54433965Sjdp /* Call back to the format-dependent code to fill in the rest of the 54533965Sjdp fields and do any further cleanup. Things that should be filled 54633965Sjdp in by the callback: */ 54733965Sjdp 54833965Sjdp struct exec *execp = exec_hdr (abfd); 54933965Sjdp 55033965Sjdp obj_textsec (abfd)->size = N_TXTSIZE(*execp); 55133965Sjdp obj_textsec (abfd)->raw_size = N_TXTSIZE(*execp); 55233965Sjdp /* data and bss are already filled in since they're so standard */ 55333965Sjdp 55433965Sjdp /* The virtual memory addresses of the sections */ 55533965Sjdp obj_textsec (abfd)->vma = N_TXTADDR(*execp); 55633965Sjdp obj_datasec (abfd)->vma = N_DATADDR(*execp); 55733965Sjdp obj_bsssec (abfd)->vma = N_BSSADDR(*execp); 55833965Sjdp 55933965Sjdp /* The file offsets of the sections */ 56033965Sjdp obj_textsec (abfd)->filepos = N_TXTOFF(*execp); 56133965Sjdp obj_datasec (abfd)->filepos = N_DATOFF(*execp); 56233965Sjdp 56333965Sjdp /* The file offsets of the relocation info */ 56433965Sjdp obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp); 56533965Sjdp obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp); 56633965Sjdp 56733965Sjdp /* The file offsets of the string table and symbol table. */ 56833965Sjdp obj_str_filepos (abfd) = N_STROFF (*execp); 56933965Sjdp obj_sym_filepos (abfd) = N_SYMOFF (*execp); 57033965Sjdp 57133965Sjdp /* Determine the architecture and machine type of the object file. */ 57233965Sjdp switch (N_MACHTYPE (*exec_hdr (abfd))) { 57333965Sjdp default: 57433965Sjdp abfd->obj_arch = bfd_arch_obscure; 57533965Sjdp break; 57633965Sjdp } 57733965Sjdp 57833965Sjdp adata(abfd)->page_size = TARGET_PAGE_SIZE; 57933965Sjdp adata(abfd)->segment_size = SEGMENT_SIZE; 58033965Sjdp adata(abfd)->exec_bytes_size = EXEC_BYTES_SIZE; 58133965Sjdp 58233965Sjdp return abfd->xvec; 58333965Sjdp 58433965Sjdp /* The architecture is encoded in various ways in various a.out variants, 58533965Sjdp or is not encoded at all in some of them. The relocation size depends 58633965Sjdp on the architecture and the a.out variant. Finally, the return value 58733965Sjdp is the bfd_target vector in use. If an error occurs, return zero and 58833965Sjdp set bfd_error to the appropriate error code. 58933965Sjdp 59033965Sjdp Formats such as b.out, which have additional fields in the a.out 59133965Sjdp header, should cope with them in this callback as well. */ 59233965Sjdp#endif /* DOCUMENTATION */ 59333965Sjdp 59433965Sjdp result = (*callback_to_real_object_p)(abfd); 59533965Sjdp 59633965Sjdp /* Now that the segment addresses have been worked out, take a better 59733965Sjdp guess at whether the file is executable. If the entry point 59833965Sjdp is within the text segment, assume it is. (This makes files 59933965Sjdp executable even if their entry point address is 0, as long as 60033965Sjdp their text starts at zero.). 60133965Sjdp 60233965Sjdp This test had to be changed to deal with systems where the text segment 60333965Sjdp runs at a different location than the default. The problem is that the 60433965Sjdp entry address can appear to be outside the text segment, thus causing an 60533965Sjdp erroneous conclusion that the file isn't executable. 60633965Sjdp 60733965Sjdp To fix this, we now accept any non-zero entry point as an indication of 60833965Sjdp executability. This will work most of the time, since only the linker 60933965Sjdp sets the entry point, and that is likely to be non-zero for most systems. */ 61033965Sjdp 61133965Sjdp if (execp->a_entry != 0 61233965Sjdp || (execp->a_entry >= obj_textsec(abfd)->vma 61333965Sjdp && execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size)) 61433965Sjdp abfd->flags |= EXEC_P; 61533965Sjdp#ifdef STAT_FOR_EXEC 61633965Sjdp else 61733965Sjdp { 61833965Sjdp struct stat stat_buf; 61933965Sjdp 62033965Sjdp /* The original heuristic doesn't work in some important cases. 62133965Sjdp The a.out file has no information about the text start 62233965Sjdp address. For files (like kernels) linked to non-standard 62333965Sjdp addresses (ld -Ttext nnn) the entry point may not be between 62433965Sjdp the default text start (obj_textsec(abfd)->vma) and 62533965Sjdp (obj_textsec(abfd)->vma) + text size. This is not just a mach 62633965Sjdp issue. Many kernels are loaded at non standard addresses. */ 62733965Sjdp if (abfd->iostream != NULL 62833965Sjdp && (abfd->flags & BFD_IN_MEMORY) == 0 62933965Sjdp && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0) 63033965Sjdp && ((stat_buf.st_mode & 0111) != 0)) 63133965Sjdp abfd->flags |= EXEC_P; 63233965Sjdp } 63333965Sjdp#endif /* STAT_FOR_EXEC */ 63433965Sjdp 63533965Sjdp if (result) 63633965Sjdp { 63733965Sjdp#if 0 /* These should be set correctly anyways. */ 63833965Sjdp abfd->sections = obj_textsec (abfd); 63933965Sjdp obj_textsec (abfd)->next = obj_datasec (abfd); 64033965Sjdp obj_datasec (abfd)->next = obj_bsssec (abfd); 64133965Sjdp#endif 64233965Sjdp } 64333965Sjdp else 64433965Sjdp { 64533965Sjdp free (rawptr); 64633965Sjdp abfd->tdata.aout_data = oldrawptr; 64733965Sjdp } 64833965Sjdp return result; 64933965Sjdp} 65033965Sjdp 65133965Sjdp/* 65233965SjdpFUNCTION 65333965Sjdp aout_@var{size}_mkobject 65433965Sjdp 65533965SjdpSYNOPSIS 65633965Sjdp boolean aout_@var{size}_mkobject, (bfd *abfd); 65733965Sjdp 65833965SjdpDESCRIPTION 65933965Sjdp Initialize BFD @var{abfd} for use with a.out files. 66033965Sjdp*/ 66133965Sjdp 66233965Sjdpboolean 66333965SjdpNAME(aout,mkobject) (abfd) 66433965Sjdp bfd *abfd; 66533965Sjdp{ 66633965Sjdp struct aout_data_struct *rawptr; 66733965Sjdp 66833965Sjdp bfd_set_error (bfd_error_system_call); 66933965Sjdp 67033965Sjdp /* Use an intermediate variable for clarity */ 67133965Sjdp rawptr = (struct aout_data_struct *)bfd_zalloc (abfd, sizeof (struct aout_data_struct )); 67233965Sjdp 67333965Sjdp if (rawptr == NULL) 67433965Sjdp return false; 67533965Sjdp 67633965Sjdp abfd->tdata.aout_data = rawptr; 67733965Sjdp exec_hdr (abfd) = &(rawptr->e); 67833965Sjdp 67933965Sjdp obj_textsec (abfd) = (asection *)NULL; 68033965Sjdp obj_datasec (abfd) = (asection *)NULL; 68133965Sjdp obj_bsssec (abfd) = (asection *)NULL; 68233965Sjdp 68333965Sjdp return true; 68433965Sjdp} 68533965Sjdp 68633965Sjdp 68733965Sjdp/* 68833965SjdpFUNCTION 68933965Sjdp aout_@var{size}_machine_type 69033965Sjdp 69133965SjdpSYNOPSIS 69233965Sjdp enum machine_type aout_@var{size}_machine_type 69333965Sjdp (enum bfd_architecture arch, 69433965Sjdp unsigned long machine)); 69533965Sjdp 69633965SjdpDESCRIPTION 69733965Sjdp Keep track of machine architecture and machine type for 69833965Sjdp a.out's. Return the <<machine_type>> for a particular 69933965Sjdp architecture and machine, or <<M_UNKNOWN>> if that exact architecture 70033965Sjdp and machine can't be represented in a.out format. 70133965Sjdp 70233965Sjdp If the architecture is understood, machine type 0 (default) 70333965Sjdp is always understood. 70433965Sjdp*/ 70533965Sjdp 70633965Sjdpenum machine_type 70733965SjdpNAME(aout,machine_type) (arch, machine, unknown) 70833965Sjdp enum bfd_architecture arch; 70933965Sjdp unsigned long machine; 71033965Sjdp boolean *unknown; 71133965Sjdp{ 71233965Sjdp enum machine_type arch_flags; 71333965Sjdp 71433965Sjdp arch_flags = M_UNKNOWN; 71533965Sjdp *unknown = true; 71633965Sjdp 71733965Sjdp switch (arch) { 71833965Sjdp case bfd_arch_sparc: 71933965Sjdp if (machine == 0 72033965Sjdp || machine == bfd_mach_sparc 72133965Sjdp || machine == bfd_mach_sparc_sparclite 72260484Sobrien || machine == bfd_mach_sparc_sparclite_le 72333965Sjdp || machine == bfd_mach_sparc_v9) 72433965Sjdp arch_flags = M_SPARC; 72533965Sjdp else if (machine == bfd_mach_sparc_sparclet) 72633965Sjdp arch_flags = M_SPARCLET; 72733965Sjdp break; 72833965Sjdp 72933965Sjdp case bfd_arch_m68k: 73033965Sjdp switch (machine) { 73138889Sjdp case 0: arch_flags = M_68010; break; 73238889Sjdp case bfd_mach_m68000: arch_flags = M_UNKNOWN; *unknown = false; break; 73338889Sjdp case bfd_mach_m68010: arch_flags = M_68010; break; 73438889Sjdp case bfd_mach_m68020: arch_flags = M_68020; break; 73538889Sjdp default: arch_flags = M_UNKNOWN; break; 73633965Sjdp } 73733965Sjdp break; 73833965Sjdp 73933965Sjdp case bfd_arch_i386: 74033965Sjdp if (machine == 0) arch_flags = M_386; 74133965Sjdp break; 74233965Sjdp 74333965Sjdp case bfd_arch_a29k: 74433965Sjdp if (machine == 0) arch_flags = M_29K; 74533965Sjdp break; 74633965Sjdp 74733965Sjdp case bfd_arch_arm: 74833965Sjdp if (machine == 0) arch_flags = M_ARM; 74933965Sjdp break; 75033965Sjdp 75133965Sjdp case bfd_arch_mips: 75233965Sjdp switch (machine) { 75333965Sjdp case 0: 75460484Sobrien case bfd_mach_mips3000: 75560484Sobrien case bfd_mach_mips3900: 75660484Sobrien arch_flags = M_MIPS1; 75760484Sobrien break; 75860484Sobrien case bfd_mach_mips6000: 75960484Sobrien arch_flags = M_MIPS2; 76060484Sobrien break; 76160484Sobrien case bfd_mach_mips4000: 76260484Sobrien case bfd_mach_mips4010: 76360484Sobrien case bfd_mach_mips4100: 76460484Sobrien case bfd_mach_mips4300: 76560484Sobrien case bfd_mach_mips4400: 76660484Sobrien case bfd_mach_mips4600: 76760484Sobrien case bfd_mach_mips4650: 76860484Sobrien case bfd_mach_mips8000: 76960484Sobrien case bfd_mach_mips10000: 77060484Sobrien case bfd_mach_mips16: 77160484Sobrien /* FIXME: These should be MIPS3 or MIPS4. */ 77260484Sobrien arch_flags = M_MIPS2; 77360484Sobrien break; 77460484Sobrien default: 77560484Sobrien arch_flags = M_UNKNOWN; 77660484Sobrien break; 77733965Sjdp } 77833965Sjdp break; 77933965Sjdp 78033965Sjdp case bfd_arch_ns32k: 78133965Sjdp switch (machine) { 78233965Sjdp case 0: arch_flags = M_NS32532; break; 78333965Sjdp case 32032: arch_flags = M_NS32032; break; 78433965Sjdp case 32532: arch_flags = M_NS32532; break; 78533965Sjdp default: arch_flags = M_UNKNOWN; break; 78633965Sjdp } 78733965Sjdp break; 78833965Sjdp 78933965Sjdp case bfd_arch_vax: 79033965Sjdp *unknown = false; 79133965Sjdp break; 79233965Sjdp 79333965Sjdp default: 79433965Sjdp arch_flags = M_UNKNOWN; 79533965Sjdp } 79633965Sjdp 79733965Sjdp if (arch_flags != M_UNKNOWN) 79833965Sjdp *unknown = false; 79933965Sjdp 80033965Sjdp return arch_flags; 80133965Sjdp} 80233965Sjdp 80333965Sjdp 80433965Sjdp/* 80533965SjdpFUNCTION 80633965Sjdp aout_@var{size}_set_arch_mach 80733965Sjdp 80833965SjdpSYNOPSIS 80933965Sjdp boolean aout_@var{size}_set_arch_mach, 81033965Sjdp (bfd *, 81133965Sjdp enum bfd_architecture arch, 81233965Sjdp unsigned long machine)); 81333965Sjdp 81433965SjdpDESCRIPTION 81533965Sjdp Set the architecture and the machine of the BFD @var{abfd} to the 81633965Sjdp values @var{arch} and @var{machine}. Verify that @var{abfd}'s format 81733965Sjdp can support the architecture required. 81833965Sjdp*/ 81933965Sjdp 82033965Sjdpboolean 82133965SjdpNAME(aout,set_arch_mach) (abfd, arch, machine) 82233965Sjdp bfd *abfd; 82333965Sjdp enum bfd_architecture arch; 82433965Sjdp unsigned long machine; 82533965Sjdp{ 82633965Sjdp if (! bfd_default_set_arch_mach (abfd, arch, machine)) 82733965Sjdp return false; 82833965Sjdp 82933965Sjdp if (arch != bfd_arch_unknown) 83033965Sjdp { 83133965Sjdp boolean unknown; 83233965Sjdp 83333965Sjdp NAME(aout,machine_type) (arch, machine, &unknown); 83433965Sjdp if (unknown) 83533965Sjdp return false; 83633965Sjdp } 83733965Sjdp 83833965Sjdp /* Determine the size of a relocation entry */ 83933965Sjdp switch (arch) { 84033965Sjdp case bfd_arch_sparc: 84133965Sjdp case bfd_arch_a29k: 84233965Sjdp case bfd_arch_mips: 84333965Sjdp obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE; 84433965Sjdp break; 84533965Sjdp default: 84633965Sjdp obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 84733965Sjdp break; 84833965Sjdp } 84933965Sjdp 85033965Sjdp return (*aout_backend_info(abfd)->set_sizes) (abfd); 85133965Sjdp} 85233965Sjdp 85333965Sjdpstatic void 85433965Sjdpadjust_o_magic (abfd, execp) 85533965Sjdp bfd *abfd; 85633965Sjdp struct internal_exec *execp; 85733965Sjdp{ 85833965Sjdp file_ptr pos = adata (abfd).exec_bytes_size; 85933965Sjdp bfd_vma vma = 0; 86033965Sjdp int pad = 0; 86133965Sjdp 86233965Sjdp /* Text. */ 86333965Sjdp obj_textsec(abfd)->filepos = pos; 86433965Sjdp if (!obj_textsec(abfd)->user_set_vma) 86533965Sjdp obj_textsec(abfd)->vma = vma; 86633965Sjdp else 86733965Sjdp vma = obj_textsec(abfd)->vma; 86833965Sjdp 86933965Sjdp pos += obj_textsec(abfd)->_raw_size; 87033965Sjdp vma += obj_textsec(abfd)->_raw_size; 87133965Sjdp 87233965Sjdp /* Data. */ 87333965Sjdp if (!obj_datasec(abfd)->user_set_vma) 87433965Sjdp { 87533965Sjdp#if 0 /* ?? Does alignment in the file image really matter? */ 87633965Sjdp pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; 87733965Sjdp#endif 87833965Sjdp obj_textsec(abfd)->_raw_size += pad; 87933965Sjdp pos += pad; 88033965Sjdp vma += pad; 88133965Sjdp obj_datasec(abfd)->vma = vma; 88233965Sjdp } 88333965Sjdp else 88433965Sjdp vma = obj_datasec(abfd)->vma; 88533965Sjdp obj_datasec(abfd)->filepos = pos; 88633965Sjdp pos += obj_datasec(abfd)->_raw_size; 88733965Sjdp vma += obj_datasec(abfd)->_raw_size; 88833965Sjdp 88933965Sjdp /* BSS. */ 89033965Sjdp if (!obj_bsssec(abfd)->user_set_vma) 89133965Sjdp { 89233965Sjdp#if 0 89333965Sjdp pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; 89433965Sjdp#endif 89533965Sjdp obj_datasec(abfd)->_raw_size += pad; 89633965Sjdp pos += pad; 89733965Sjdp vma += pad; 89833965Sjdp obj_bsssec(abfd)->vma = vma; 89933965Sjdp } 90033965Sjdp else 90133965Sjdp { 90233965Sjdp /* The VMA of the .bss section is set by the the VMA of the 90333965Sjdp .data section plus the size of the .data section. We may 90433965Sjdp need to add padding bytes to make this true. */ 90533965Sjdp pad = obj_bsssec (abfd)->vma - vma; 90633965Sjdp if (pad > 0) 90733965Sjdp { 90833965Sjdp obj_datasec (abfd)->_raw_size += pad; 90933965Sjdp pos += pad; 91033965Sjdp } 91133965Sjdp } 91233965Sjdp obj_bsssec(abfd)->filepos = pos; 91333965Sjdp 91433965Sjdp /* Fix up the exec header. */ 91533965Sjdp execp->a_text = obj_textsec(abfd)->_raw_size; 91633965Sjdp execp->a_data = obj_datasec(abfd)->_raw_size; 91733965Sjdp execp->a_bss = obj_bsssec(abfd)->_raw_size; 91833965Sjdp N_SET_MAGIC (*execp, OMAGIC); 91933965Sjdp} 92033965Sjdp 92133965Sjdpstatic void 92233965Sjdpadjust_z_magic (abfd, execp) 92333965Sjdp bfd *abfd; 92433965Sjdp struct internal_exec *execp; 92533965Sjdp{ 92633965Sjdp bfd_size_type data_pad, text_pad; 92733965Sjdp file_ptr text_end; 92833965Sjdp CONST struct aout_backend_data *abdp; 92933965Sjdp int ztih; /* Nonzero if text includes exec header. */ 93033965Sjdp 93133965Sjdp abdp = aout_backend_info (abfd); 93233965Sjdp 93333965Sjdp /* Text. */ 93433965Sjdp ztih = (abdp != NULL 93533965Sjdp && (abdp->text_includes_header 93633965Sjdp || obj_aout_subformat (abfd) == q_magic_format)); 93733965Sjdp obj_textsec(abfd)->filepos = (ztih 93833965Sjdp ? adata(abfd).exec_bytes_size 93933965Sjdp : adata(abfd).zmagic_disk_block_size); 94033965Sjdp if (! obj_textsec(abfd)->user_set_vma) 94133965Sjdp { 94233965Sjdp /* ?? Do we really need to check for relocs here? */ 94333965Sjdp obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) 94433965Sjdp ? 0 94533965Sjdp : (ztih 94633965Sjdp ? (abdp->default_text_vma 94733965Sjdp + adata(abfd).exec_bytes_size) 94833965Sjdp : abdp->default_text_vma)); 94933965Sjdp text_pad = 0; 95033965Sjdp } 95133965Sjdp else 95233965Sjdp { 95333965Sjdp /* The .text section is being loaded at an unusual address. We 95433965Sjdp may need to pad it such that the .data section starts at a page 95533965Sjdp boundary. */ 95633965Sjdp if (ztih) 95733965Sjdp text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma) 95833965Sjdp & (adata (abfd).page_size - 1)); 95933965Sjdp else 96033965Sjdp text_pad = ((- obj_textsec (abfd)->vma) 96133965Sjdp & (adata (abfd).page_size - 1)); 96233965Sjdp } 96333965Sjdp 96433965Sjdp /* Find start of data. */ 96533965Sjdp if (ztih) 96633965Sjdp { 96733965Sjdp text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->_raw_size; 96833965Sjdp text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; 96933965Sjdp } 97033965Sjdp else 97133965Sjdp { 97233965Sjdp /* Note that if page_size == zmagic_disk_block_size, then 97333965Sjdp filepos == page_size, and this case is the same as the ztih 97433965Sjdp case. */ 97533965Sjdp text_end = obj_textsec (abfd)->_raw_size; 97633965Sjdp text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; 97733965Sjdp text_end += obj_textsec (abfd)->filepos; 97833965Sjdp } 97933965Sjdp obj_textsec(abfd)->_raw_size += text_pad; 98033965Sjdp text_end += text_pad; 98133965Sjdp 98233965Sjdp /* Data. */ 98333965Sjdp if (!obj_datasec(abfd)->user_set_vma) 98433965Sjdp { 98533965Sjdp bfd_vma vma; 98633965Sjdp vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; 98733965Sjdp obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); 98833965Sjdp } 98933965Sjdp if (abdp && abdp->zmagic_mapped_contiguous) 99033965Sjdp { 99133965Sjdp text_pad = (obj_datasec(abfd)->vma 99233965Sjdp - obj_textsec(abfd)->vma 99333965Sjdp - obj_textsec(abfd)->_raw_size); 99433965Sjdp obj_textsec(abfd)->_raw_size += text_pad; 99533965Sjdp } 99633965Sjdp obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos 99733965Sjdp + obj_textsec(abfd)->_raw_size); 99833965Sjdp 99933965Sjdp /* Fix up exec header while we're at it. */ 100033965Sjdp execp->a_text = obj_textsec(abfd)->_raw_size; 100133965Sjdp if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) 100233965Sjdp execp->a_text += adata(abfd).exec_bytes_size; 100333965Sjdp if (obj_aout_subformat (abfd) == q_magic_format) 100433965Sjdp N_SET_MAGIC (*execp, QMAGIC); 100533965Sjdp else 100633965Sjdp N_SET_MAGIC (*execp, ZMAGIC); 100733965Sjdp 100833965Sjdp /* Spec says data section should be rounded up to page boundary. */ 100933965Sjdp obj_datasec(abfd)->_raw_size 101033965Sjdp = align_power (obj_datasec(abfd)->_raw_size, 101133965Sjdp obj_bsssec(abfd)->alignment_power); 101233965Sjdp execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, 101333965Sjdp adata(abfd).page_size); 101433965Sjdp data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; 101533965Sjdp 101633965Sjdp /* BSS. */ 101733965Sjdp if (!obj_bsssec(abfd)->user_set_vma) 101833965Sjdp obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma 101933965Sjdp + obj_datasec(abfd)->_raw_size); 102033965Sjdp /* If the BSS immediately follows the data section and extra space 102133965Sjdp in the page is left after the data section, fudge data 102233965Sjdp in the header so that the bss section looks smaller by that 102333965Sjdp amount. We'll start the bss section there, and lie to the OS. 102433965Sjdp (Note that a linker script, as well as the above assignment, 102533965Sjdp could have explicitly set the BSS vma to immediately follow 102633965Sjdp the data section.) */ 102733965Sjdp if (align_power (obj_bsssec(abfd)->vma, obj_bsssec(abfd)->alignment_power) 102833965Sjdp == obj_datasec(abfd)->vma + obj_datasec(abfd)->_raw_size) 102933965Sjdp execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 : 103033965Sjdp obj_bsssec(abfd)->_raw_size - data_pad; 103133965Sjdp else 103233965Sjdp execp->a_bss = obj_bsssec(abfd)->_raw_size; 103333965Sjdp} 103433965Sjdp 103533965Sjdpstatic void 103633965Sjdpadjust_n_magic (abfd, execp) 103733965Sjdp bfd *abfd; 103833965Sjdp struct internal_exec *execp; 103933965Sjdp{ 104033965Sjdp file_ptr pos = adata(abfd).exec_bytes_size; 104133965Sjdp bfd_vma vma = 0; 104233965Sjdp int pad; 104333965Sjdp 104433965Sjdp /* Text. */ 104533965Sjdp obj_textsec(abfd)->filepos = pos; 104633965Sjdp if (!obj_textsec(abfd)->user_set_vma) 104733965Sjdp obj_textsec(abfd)->vma = vma; 104833965Sjdp else 104933965Sjdp vma = obj_textsec(abfd)->vma; 105033965Sjdp pos += obj_textsec(abfd)->_raw_size; 105133965Sjdp vma += obj_textsec(abfd)->_raw_size; 105233965Sjdp 105333965Sjdp /* Data. */ 105433965Sjdp obj_datasec(abfd)->filepos = pos; 105533965Sjdp if (!obj_datasec(abfd)->user_set_vma) 105633965Sjdp obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); 105733965Sjdp vma = obj_datasec(abfd)->vma; 105833965Sjdp 105933965Sjdp /* Since BSS follows data immediately, see if it needs alignment. */ 106033965Sjdp vma += obj_datasec(abfd)->_raw_size; 106133965Sjdp pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; 106233965Sjdp obj_datasec(abfd)->_raw_size += pad; 106333965Sjdp pos += obj_datasec(abfd)->_raw_size; 106433965Sjdp 106533965Sjdp /* BSS. */ 106633965Sjdp if (!obj_bsssec(abfd)->user_set_vma) 106733965Sjdp obj_bsssec(abfd)->vma = vma; 106833965Sjdp else 106933965Sjdp vma = obj_bsssec(abfd)->vma; 107033965Sjdp 107133965Sjdp /* Fix up exec header. */ 107233965Sjdp execp->a_text = obj_textsec(abfd)->_raw_size; 107333965Sjdp execp->a_data = obj_datasec(abfd)->_raw_size; 107433965Sjdp execp->a_bss = obj_bsssec(abfd)->_raw_size; 107533965Sjdp N_SET_MAGIC (*execp, NMAGIC); 107633965Sjdp} 107733965Sjdp 107833965Sjdpboolean 107933965SjdpNAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end) 108033965Sjdp bfd *abfd; 108133965Sjdp bfd_size_type *text_size; 108260484Sobrien file_ptr *text_end ATTRIBUTE_UNUSED; 108333965Sjdp{ 108433965Sjdp struct internal_exec *execp = exec_hdr (abfd); 108533965Sjdp 108633965Sjdp if (! NAME(aout,make_sections) (abfd)) 108733965Sjdp return false; 108833965Sjdp 108933965Sjdp if (adata(abfd).magic != undecided_magic) 109033965Sjdp return true; 109133965Sjdp 109233965Sjdp obj_textsec(abfd)->_raw_size = 109333965Sjdp align_power(obj_textsec(abfd)->_raw_size, 109433965Sjdp obj_textsec(abfd)->alignment_power); 109533965Sjdp 109633965Sjdp *text_size = obj_textsec (abfd)->_raw_size; 109733965Sjdp /* Rule (heuristic) for when to pad to a new page. Note that there 109833965Sjdp are (at least) two ways demand-paged (ZMAGIC) files have been 109933965Sjdp handled. Most Berkeley-based systems start the text segment at 110033965Sjdp (TARGET_PAGE_SIZE). However, newer versions of SUNOS start the text 110133965Sjdp segment right after the exec header; the latter is counted in the 110233965Sjdp text segment size, and is paged in by the kernel with the rest of 110333965Sjdp the text. */ 110433965Sjdp 110533965Sjdp /* This perhaps isn't the right way to do this, but made it simpler for me 110633965Sjdp to understand enough to implement it. Better would probably be to go 110733965Sjdp right from BFD flags to alignment/positioning characteristics. But the 110833965Sjdp old code was sloppy enough about handling the flags, and had enough 110933965Sjdp other magic, that it was a little hard for me to understand. I think 111033965Sjdp I understand it better now, but I haven't time to do the cleanup this 111133965Sjdp minute. */ 111233965Sjdp 111333965Sjdp if (abfd->flags & D_PAGED) 111433965Sjdp /* Whether or not WP_TEXT is set -- let D_PAGED override. */ 111533965Sjdp adata(abfd).magic = z_magic; 111633965Sjdp else if (abfd->flags & WP_TEXT) 111733965Sjdp adata(abfd).magic = n_magic; 111833965Sjdp else 111933965Sjdp adata(abfd).magic = o_magic; 112033965Sjdp 112133965Sjdp#ifdef BFD_AOUT_DEBUG /* requires gcc2 */ 112233965Sjdp#if __GNUC__ >= 2 112333965Sjdp fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n", 112433965Sjdp ({ char *str; 112533965Sjdp switch (adata(abfd).magic) { 112633965Sjdp case n_magic: str = "NMAGIC"; break; 112733965Sjdp case o_magic: str = "OMAGIC"; break; 112833965Sjdp case z_magic: str = "ZMAGIC"; break; 112933965Sjdp default: abort (); 113033965Sjdp } 113133965Sjdp str; 113233965Sjdp }), 113333965Sjdp obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, 113433965Sjdp obj_textsec(abfd)->alignment_power, 113533965Sjdp obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, 113633965Sjdp obj_datasec(abfd)->alignment_power, 113733965Sjdp obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, 113833965Sjdp obj_bsssec(abfd)->alignment_power); 113933965Sjdp#endif 114033965Sjdp#endif 114133965Sjdp 114233965Sjdp switch (adata(abfd).magic) 114333965Sjdp { 114433965Sjdp case o_magic: 114533965Sjdp adjust_o_magic (abfd, execp); 114633965Sjdp break; 114733965Sjdp case z_magic: 114833965Sjdp adjust_z_magic (abfd, execp); 114933965Sjdp break; 115033965Sjdp case n_magic: 115133965Sjdp adjust_n_magic (abfd, execp); 115233965Sjdp break; 115333965Sjdp default: 115433965Sjdp abort (); 115533965Sjdp } 115633965Sjdp 115733965Sjdp#ifdef BFD_AOUT_DEBUG 115833965Sjdp fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n", 115933965Sjdp obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, 116033965Sjdp obj_textsec(abfd)->filepos, 116133965Sjdp obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, 116233965Sjdp obj_datasec(abfd)->filepos, 116333965Sjdp obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size); 116433965Sjdp#endif 116533965Sjdp 116633965Sjdp return true; 116733965Sjdp} 116833965Sjdp 116933965Sjdp/* 117033965SjdpFUNCTION 117133965Sjdp aout_@var{size}_new_section_hook 117233965Sjdp 117333965SjdpSYNOPSIS 117433965Sjdp boolean aout_@var{size}_new_section_hook, 117533965Sjdp (bfd *abfd, 117633965Sjdp asection *newsect)); 117733965Sjdp 117833965SjdpDESCRIPTION 117933965Sjdp Called by the BFD in response to a @code{bfd_make_section} 118033965Sjdp request. 118133965Sjdp*/ 118233965Sjdpboolean 118333965SjdpNAME(aout,new_section_hook) (abfd, newsect) 118433965Sjdp bfd *abfd; 118533965Sjdp asection *newsect; 118633965Sjdp{ 118733965Sjdp /* align to double at least */ 118833965Sjdp newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power; 118933965Sjdp 119033965Sjdp 119133965Sjdp if (bfd_get_format (abfd) == bfd_object) 119233965Sjdp { 119333965Sjdp if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) { 119433965Sjdp obj_textsec(abfd)= newsect; 119533965Sjdp newsect->target_index = N_TEXT; 119633965Sjdp return true; 119733965Sjdp } 119833965Sjdp 119933965Sjdp if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) { 120033965Sjdp obj_datasec(abfd) = newsect; 120133965Sjdp newsect->target_index = N_DATA; 120233965Sjdp return true; 120333965Sjdp } 120433965Sjdp 120533965Sjdp if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) { 120633965Sjdp obj_bsssec(abfd) = newsect; 120733965Sjdp newsect->target_index = N_BSS; 120833965Sjdp return true; 120933965Sjdp } 121033965Sjdp 121133965Sjdp } 121233965Sjdp 121333965Sjdp /* We allow more than three sections internally */ 121433965Sjdp return true; 121533965Sjdp} 121633965Sjdp 121733965Sjdpboolean 121833965SjdpNAME(aout,set_section_contents) (abfd, section, location, offset, count) 121933965Sjdp bfd *abfd; 122033965Sjdp sec_ptr section; 122133965Sjdp PTR location; 122233965Sjdp file_ptr offset; 122333965Sjdp bfd_size_type count; 122433965Sjdp{ 122533965Sjdp file_ptr text_end; 122633965Sjdp bfd_size_type text_size; 122733965Sjdp 122833965Sjdp if (! abfd->output_has_begun) 122933965Sjdp { 123033965Sjdp if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) 123133965Sjdp return false; 123233965Sjdp } 123333965Sjdp 123433965Sjdp if (section == obj_bsssec (abfd)) 123533965Sjdp { 123633965Sjdp bfd_set_error (bfd_error_no_contents); 123733965Sjdp return false; 123833965Sjdp } 123933965Sjdp 124033965Sjdp if (section != obj_textsec (abfd) 124133965Sjdp && section != obj_datasec (abfd)) 124233965Sjdp { 124333965Sjdp (*_bfd_error_handler) 124460484Sobrien (_("%s: can not represent section `%s' in a.out object file format"), 124533965Sjdp bfd_get_filename (abfd), bfd_get_section_name (abfd, section)); 124633965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 124733965Sjdp return false; 124833965Sjdp } 124933965Sjdp 125033965Sjdp if (count != 0) 125133965Sjdp { 125233965Sjdp if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 125333965Sjdp || bfd_write (location, 1, count, abfd) != count) 125433965Sjdp return false; 125533965Sjdp } 125633965Sjdp 125733965Sjdp return true; 125833965Sjdp} 125933965Sjdp 126033965Sjdp/* Read the external symbols from an a.out file. */ 126133965Sjdp 126233965Sjdpstatic boolean 126333965Sjdpaout_get_external_symbols (abfd) 126433965Sjdp bfd *abfd; 126533965Sjdp{ 126633965Sjdp if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL) 126733965Sjdp { 126833965Sjdp bfd_size_type count; 126933965Sjdp struct external_nlist *syms; 127033965Sjdp 127133965Sjdp count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE; 127233965Sjdp 127333965Sjdp#ifdef USE_MMAP 127433965Sjdp if (bfd_get_file_window (abfd, 127533965Sjdp obj_sym_filepos (abfd), exec_hdr (abfd)->a_syms, 127633965Sjdp &obj_aout_sym_window (abfd), true) == false) 127733965Sjdp return false; 127833965Sjdp syms = (struct external_nlist *) obj_aout_sym_window (abfd).data; 127933965Sjdp#else 128033965Sjdp /* We allocate using malloc to make the values easy to free 128133965Sjdp later on. If we put them on the objalloc it might not be 128233965Sjdp possible to free them. */ 128333965Sjdp syms = ((struct external_nlist *) 128433965Sjdp bfd_malloc ((size_t) count * EXTERNAL_NLIST_SIZE)); 128533965Sjdp if (syms == (struct external_nlist *) NULL && count != 0) 128633965Sjdp return false; 128733965Sjdp 128833965Sjdp if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 128933965Sjdp || (bfd_read (syms, 1, exec_hdr (abfd)->a_syms, abfd) 129033965Sjdp != exec_hdr (abfd)->a_syms)) 129133965Sjdp { 129233965Sjdp free (syms); 129333965Sjdp return false; 129433965Sjdp } 129533965Sjdp#endif 129633965Sjdp 129733965Sjdp obj_aout_external_syms (abfd) = syms; 129833965Sjdp obj_aout_external_sym_count (abfd) = count; 129933965Sjdp } 130033965Sjdp 130133965Sjdp if (obj_aout_external_strings (abfd) == NULL 130233965Sjdp && exec_hdr (abfd)->a_syms != 0) 130333965Sjdp { 130433965Sjdp unsigned char string_chars[BYTES_IN_WORD]; 130533965Sjdp bfd_size_type stringsize; 130633965Sjdp char *strings; 130733965Sjdp 130833965Sjdp /* Get the size of the strings. */ 130933965Sjdp if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 131033965Sjdp || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd) 131133965Sjdp != BYTES_IN_WORD)) 131233965Sjdp return false; 131333965Sjdp stringsize = GET_WORD (abfd, string_chars); 131433965Sjdp 131533965Sjdp#ifdef USE_MMAP 131633965Sjdp if (bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize, 131733965Sjdp &obj_aout_string_window (abfd), true) == false) 131833965Sjdp return false; 131933965Sjdp strings = (char *) obj_aout_string_window (abfd).data; 132033965Sjdp#else 132133965Sjdp strings = (char *) bfd_malloc ((size_t) stringsize + 1); 132233965Sjdp if (strings == NULL) 132333965Sjdp return false; 132433965Sjdp 132533965Sjdp /* Skip space for the string count in the buffer for convenience 132633965Sjdp when using indexes. */ 132733965Sjdp if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD, 132833965Sjdp abfd) 132933965Sjdp != stringsize - BYTES_IN_WORD) 133033965Sjdp { 133133965Sjdp free (strings); 133233965Sjdp return false; 133333965Sjdp } 133433965Sjdp#endif 133533965Sjdp 133633965Sjdp /* Ensure that a zero index yields an empty string. */ 133733965Sjdp strings[0] = '\0'; 133833965Sjdp 133933965Sjdp strings[stringsize - 1] = 0; 134033965Sjdp 134133965Sjdp obj_aout_external_strings (abfd) = strings; 134233965Sjdp obj_aout_external_string_size (abfd) = stringsize; 134333965Sjdp } 134433965Sjdp 134533965Sjdp return true; 134633965Sjdp} 134733965Sjdp 134833965Sjdp/* Translate an a.out symbol into a BFD symbol. The desc, other, type 134933965Sjdp and symbol->value fields of CACHE_PTR will be set from the a.out 135033965Sjdp nlist structure. This function is responsible for setting 135133965Sjdp symbol->flags and symbol->section, and adjusting symbol->value. */ 135233965Sjdp 135333965Sjdpstatic boolean 135433965Sjdptranslate_from_native_sym_flags (abfd, cache_ptr) 135533965Sjdp bfd *abfd; 135633965Sjdp aout_symbol_type *cache_ptr; 135733965Sjdp{ 135833965Sjdp flagword visible; 135933965Sjdp 136033965Sjdp if ((cache_ptr->type & N_STAB) != 0 136133965Sjdp || cache_ptr->type == N_FN) 136233965Sjdp { 136333965Sjdp asection *sec; 136433965Sjdp 136533965Sjdp /* This is a debugging symbol. */ 136633965Sjdp 136733965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING; 136833965Sjdp 136933965Sjdp /* Work out the symbol section. */ 137033965Sjdp switch (cache_ptr->type & N_TYPE) 137133965Sjdp { 137233965Sjdp case N_TEXT: 137333965Sjdp case N_FN: 137433965Sjdp sec = obj_textsec (abfd); 137533965Sjdp break; 137633965Sjdp case N_DATA: 137733965Sjdp sec = obj_datasec (abfd); 137833965Sjdp break; 137933965Sjdp case N_BSS: 138033965Sjdp sec = obj_bsssec (abfd); 138133965Sjdp break; 138233965Sjdp default: 138333965Sjdp case N_ABS: 138433965Sjdp sec = bfd_abs_section_ptr; 138533965Sjdp break; 138633965Sjdp } 138733965Sjdp 138833965Sjdp cache_ptr->symbol.section = sec; 138933965Sjdp cache_ptr->symbol.value -= sec->vma; 139033965Sjdp 139133965Sjdp return true; 139233965Sjdp } 139333965Sjdp 139433965Sjdp /* Get the default visibility. This does not apply to all types, so 139533965Sjdp we just hold it in a local variable to use if wanted. */ 139633965Sjdp if ((cache_ptr->type & N_EXT) == 0) 139733965Sjdp visible = BSF_LOCAL; 139833965Sjdp else 139933965Sjdp visible = BSF_GLOBAL; 140033965Sjdp 140133965Sjdp switch (cache_ptr->type) 140233965Sjdp { 140333965Sjdp default: 140433965Sjdp case N_ABS: case N_ABS | N_EXT: 140533965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 140633965Sjdp cache_ptr->symbol.flags = visible; 140733965Sjdp break; 140833965Sjdp 140933965Sjdp case N_UNDF | N_EXT: 141033965Sjdp if (cache_ptr->symbol.value != 0) 141133965Sjdp { 141233965Sjdp /* This is a common symbol. */ 141333965Sjdp cache_ptr->symbol.flags = BSF_GLOBAL; 141433965Sjdp cache_ptr->symbol.section = bfd_com_section_ptr; 141533965Sjdp } 141633965Sjdp else 141733965Sjdp { 141833965Sjdp cache_ptr->symbol.flags = 0; 141933965Sjdp cache_ptr->symbol.section = bfd_und_section_ptr; 142033965Sjdp } 142133965Sjdp break; 142233965Sjdp 142333965Sjdp case N_TEXT: case N_TEXT | N_EXT: 142433965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 142533965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 142633965Sjdp cache_ptr->symbol.flags = visible; 142733965Sjdp break; 142833965Sjdp 142933965Sjdp /* N_SETV symbols used to represent set vectors placed in the 143033965Sjdp data section. They are no longer generated. Theoretically, 143133965Sjdp it was possible to extract the entries and combine them with 143233965Sjdp new ones, although I don't know if that was ever actually 143333965Sjdp done. Unless that feature is restored, treat them as data 143433965Sjdp symbols. */ 143533965Sjdp case N_SETV: case N_SETV | N_EXT: 143633965Sjdp case N_DATA: case N_DATA | N_EXT: 143733965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 143833965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 143933965Sjdp cache_ptr->symbol.flags = visible; 144033965Sjdp break; 144133965Sjdp 144233965Sjdp case N_BSS: case N_BSS | N_EXT: 144333965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 144433965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 144533965Sjdp cache_ptr->symbol.flags = visible; 144633965Sjdp break; 144733965Sjdp 144833965Sjdp case N_SETA: case N_SETA | N_EXT: 144933965Sjdp case N_SETT: case N_SETT | N_EXT: 145033965Sjdp case N_SETD: case N_SETD | N_EXT: 145133965Sjdp case N_SETB: case N_SETB | N_EXT: 145233965Sjdp { 145333965Sjdp /* This code is no longer needed. It used to be used to make 145433965Sjdp the linker handle set symbols, but they are now handled in 145533965Sjdp the add_symbols routine instead. */ 145633965Sjdp#if 0 145733965Sjdp asection *section; 145833965Sjdp arelent_chain *reloc; 145933965Sjdp asection *into_section; 146033965Sjdp 146133965Sjdp /* This is a set symbol. The name of the symbol is the name 146233965Sjdp of the set (e.g., __CTOR_LIST__). The value of the symbol 146333965Sjdp is the value to add to the set. We create a section with 146433965Sjdp the same name as the symbol, and add a reloc to insert the 146533965Sjdp appropriate value into the section. 146633965Sjdp 146733965Sjdp This action is actually obsolete; it used to make the 146833965Sjdp linker do the right thing, but the linker no longer uses 146933965Sjdp this function. */ 147033965Sjdp 147133965Sjdp section = bfd_get_section_by_name (abfd, cache_ptr->symbol.name); 147233965Sjdp if (section == NULL) 147333965Sjdp { 147433965Sjdp char *copy; 147533965Sjdp 147633965Sjdp copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1); 147733965Sjdp if (copy == NULL) 147833965Sjdp return false; 147933965Sjdp 148033965Sjdp strcpy (copy, cache_ptr->symbol.name); 148133965Sjdp section = bfd_make_section (abfd, copy); 148233965Sjdp if (section == NULL) 148333965Sjdp return false; 148433965Sjdp } 148533965Sjdp 148633965Sjdp reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); 148733965Sjdp if (reloc == NULL) 148833965Sjdp return false; 148933965Sjdp 149033965Sjdp /* Build a relocation entry for the constructor. */ 149133965Sjdp switch (cache_ptr->type & N_TYPE) 149233965Sjdp { 149333965Sjdp case N_SETA: 149433965Sjdp into_section = bfd_abs_section_ptr; 149533965Sjdp cache_ptr->type = N_ABS; 149633965Sjdp break; 149733965Sjdp case N_SETT: 149833965Sjdp into_section = obj_textsec (abfd); 149933965Sjdp cache_ptr->type = N_TEXT; 150033965Sjdp break; 150133965Sjdp case N_SETD: 150233965Sjdp into_section = obj_datasec (abfd); 150333965Sjdp cache_ptr->type = N_DATA; 150433965Sjdp break; 150533965Sjdp case N_SETB: 150633965Sjdp into_section = obj_bsssec (abfd); 150733965Sjdp cache_ptr->type = N_BSS; 150833965Sjdp break; 150933965Sjdp } 151033965Sjdp 151133965Sjdp /* Build a relocation pointing into the constructor section 151233965Sjdp pointing at the symbol in the set vector specified. */ 151333965Sjdp reloc->relent.addend = cache_ptr->symbol.value; 151433965Sjdp cache_ptr->symbol.section = into_section; 151533965Sjdp reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr; 151633965Sjdp 151733965Sjdp /* We modify the symbol to belong to a section depending upon 151833965Sjdp the name of the symbol, and add to the size of the section 151933965Sjdp to contain a pointer to the symbol. Build a reloc entry to 152033965Sjdp relocate to this symbol attached to this section. */ 152133965Sjdp section->flags = SEC_CONSTRUCTOR | SEC_RELOC; 152233965Sjdp 152333965Sjdp section->reloc_count++; 152433965Sjdp section->alignment_power = 2; 152533965Sjdp 152633965Sjdp reloc->next = section->constructor_chain; 152733965Sjdp section->constructor_chain = reloc; 152833965Sjdp reloc->relent.address = section->_raw_size; 152933965Sjdp section->_raw_size += BYTES_IN_WORD; 153033965Sjdp 153133965Sjdp reloc->relent.howto = CTOR_TABLE_RELOC_HOWTO(abfd); 153233965Sjdp 153333965Sjdp#endif /* 0 */ 153433965Sjdp 153533965Sjdp switch (cache_ptr->type & N_TYPE) 153633965Sjdp { 153733965Sjdp case N_SETA: 153833965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 153933965Sjdp break; 154033965Sjdp case N_SETT: 154133965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 154233965Sjdp break; 154333965Sjdp case N_SETD: 154433965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 154533965Sjdp break; 154633965Sjdp case N_SETB: 154733965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 154833965Sjdp break; 154933965Sjdp } 155033965Sjdp 155133965Sjdp cache_ptr->symbol.flags |= BSF_CONSTRUCTOR; 155233965Sjdp } 155333965Sjdp break; 155433965Sjdp 155533965Sjdp case N_WARNING: 155633965Sjdp /* This symbol is the text of a warning message. The next 155733965Sjdp symbol is the symbol to associate the warning with. If a 155833965Sjdp reference is made to that symbol, a warning is issued. */ 155933965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING; 156033965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 156133965Sjdp break; 156233965Sjdp 156333965Sjdp case N_INDR: case N_INDR | N_EXT: 156433965Sjdp /* An indirect symbol. This consists of two symbols in a row. 156533965Sjdp The first symbol is the name of the indirection. The second 156633965Sjdp symbol is the name of the target. A reference to the first 156733965Sjdp symbol becomes a reference to the second. */ 156833965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible; 156933965Sjdp cache_ptr->symbol.section = bfd_ind_section_ptr; 157033965Sjdp break; 157133965Sjdp 157233965Sjdp case N_WEAKU: 157333965Sjdp cache_ptr->symbol.section = bfd_und_section_ptr; 157433965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 157533965Sjdp break; 157633965Sjdp 157733965Sjdp case N_WEAKA: 157833965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 157933965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 158033965Sjdp break; 158133965Sjdp 158233965Sjdp case N_WEAKT: 158333965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 158433965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 158533965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 158633965Sjdp break; 158733965Sjdp 158833965Sjdp case N_WEAKD: 158933965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 159033965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 159133965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 159233965Sjdp break; 159333965Sjdp 159433965Sjdp case N_WEAKB: 159533965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 159633965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 159733965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 159833965Sjdp break; 159933965Sjdp } 160033965Sjdp 160133965Sjdp return true; 160233965Sjdp} 160333965Sjdp 160433965Sjdp/* Set the fields of SYM_POINTER according to CACHE_PTR. */ 160533965Sjdp 160633965Sjdpstatic boolean 160733965Sjdptranslate_to_native_sym_flags (abfd, cache_ptr, sym_pointer) 160833965Sjdp bfd *abfd; 160933965Sjdp asymbol *cache_ptr; 161033965Sjdp struct external_nlist *sym_pointer; 161133965Sjdp{ 161233965Sjdp bfd_vma value = cache_ptr->value; 161333965Sjdp asection *sec; 161433965Sjdp bfd_vma off; 161533965Sjdp 161633965Sjdp /* Mask out any existing type bits in case copying from one section 161733965Sjdp to another. */ 161833965Sjdp sym_pointer->e_type[0] &= ~N_TYPE; 161933965Sjdp 162033965Sjdp sec = bfd_get_section (cache_ptr); 162133965Sjdp off = 0; 162233965Sjdp 162333965Sjdp if (sec == NULL) 162433965Sjdp { 162533965Sjdp /* This case occurs, e.g., for the *DEBUG* section of a COFF 162633965Sjdp file. */ 162733965Sjdp (*_bfd_error_handler) 162860484Sobrien (_("%s: can not represent section for symbol `%s' in a.out object file format"), 162933965Sjdp bfd_get_filename (abfd), 163060484Sobrien cache_ptr->name != NULL ? cache_ptr->name : _("*unknown*")); 163133965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 163233965Sjdp return false; 163333965Sjdp } 163433965Sjdp 163533965Sjdp if (sec->output_section != NULL) 163633965Sjdp { 163733965Sjdp off = sec->output_offset; 163833965Sjdp sec = sec->output_section; 163933965Sjdp } 164033965Sjdp 164133965Sjdp if (bfd_is_abs_section (sec)) 164233965Sjdp sym_pointer->e_type[0] |= N_ABS; 164333965Sjdp else if (sec == obj_textsec (abfd)) 164433965Sjdp sym_pointer->e_type[0] |= N_TEXT; 164533965Sjdp else if (sec == obj_datasec (abfd)) 164633965Sjdp sym_pointer->e_type[0] |= N_DATA; 164733965Sjdp else if (sec == obj_bsssec (abfd)) 164833965Sjdp sym_pointer->e_type[0] |= N_BSS; 164933965Sjdp else if (bfd_is_und_section (sec)) 165033965Sjdp sym_pointer->e_type[0] = N_UNDF | N_EXT; 165133965Sjdp else if (bfd_is_ind_section (sec)) 165233965Sjdp sym_pointer->e_type[0] = N_INDR; 165333965Sjdp else if (bfd_is_com_section (sec)) 165433965Sjdp sym_pointer->e_type[0] = N_UNDF | N_EXT; 165533965Sjdp else 165633965Sjdp { 165733965Sjdp (*_bfd_error_handler) 165860484Sobrien (_("%s: can not represent section `%s' in a.out object file format"), 165933965Sjdp bfd_get_filename (abfd), bfd_get_section_name (abfd, sec)); 166033965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 166133965Sjdp return false; 166233965Sjdp } 166333965Sjdp 166433965Sjdp /* Turn the symbol from section relative to absolute again */ 166533965Sjdp value += sec->vma + off; 166633965Sjdp 166733965Sjdp if ((cache_ptr->flags & BSF_WARNING) != 0) 166833965Sjdp sym_pointer->e_type[0] = N_WARNING; 166933965Sjdp 167033965Sjdp if ((cache_ptr->flags & BSF_DEBUGGING) != 0) 167133965Sjdp sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type; 167233965Sjdp else if ((cache_ptr->flags & BSF_GLOBAL) != 0) 167333965Sjdp sym_pointer->e_type[0] |= N_EXT; 167433965Sjdp 167533965Sjdp if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0) 167633965Sjdp { 167733965Sjdp int type = ((aout_symbol_type *) cache_ptr)->type; 167833965Sjdp switch (type) 167933965Sjdp { 168033965Sjdp case N_ABS: type = N_SETA; break; 168133965Sjdp case N_TEXT: type = N_SETT; break; 168233965Sjdp case N_DATA: type = N_SETD; break; 168333965Sjdp case N_BSS: type = N_SETB; break; 168433965Sjdp } 168533965Sjdp sym_pointer->e_type[0] = type; 168633965Sjdp } 168733965Sjdp 168833965Sjdp if ((cache_ptr->flags & BSF_WEAK) != 0) 168933965Sjdp { 169033965Sjdp int type; 169133965Sjdp 169233965Sjdp switch (sym_pointer->e_type[0] & N_TYPE) 169333965Sjdp { 169433965Sjdp default: 169533965Sjdp case N_ABS: type = N_WEAKA; break; 169633965Sjdp case N_TEXT: type = N_WEAKT; break; 169733965Sjdp case N_DATA: type = N_WEAKD; break; 169833965Sjdp case N_BSS: type = N_WEAKB; break; 169933965Sjdp case N_UNDF: type = N_WEAKU; break; 170033965Sjdp } 170133965Sjdp sym_pointer->e_type[0] = type; 170233965Sjdp } 170333965Sjdp 170433965Sjdp PUT_WORD(abfd, value, sym_pointer->e_value); 170533965Sjdp 170633965Sjdp return true; 170733965Sjdp} 170833965Sjdp 170933965Sjdp/* Native-level interface to symbols. */ 171033965Sjdp 171133965Sjdpasymbol * 171233965SjdpNAME(aout,make_empty_symbol) (abfd) 171333965Sjdp bfd *abfd; 171433965Sjdp{ 171533965Sjdp aout_symbol_type *new = 171633965Sjdp (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type)); 171733965Sjdp if (!new) 171833965Sjdp return NULL; 171933965Sjdp new->symbol.the_bfd = abfd; 172033965Sjdp 172133965Sjdp return &new->symbol; 172233965Sjdp} 172333965Sjdp 172433965Sjdp/* Translate a set of internal symbols into external symbols. */ 172533965Sjdp 172633965Sjdpboolean 172733965SjdpNAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic) 172833965Sjdp bfd *abfd; 172933965Sjdp aout_symbol_type *in; 173033965Sjdp struct external_nlist *ext; 173133965Sjdp bfd_size_type count; 173233965Sjdp char *str; 173333965Sjdp bfd_size_type strsize; 173433965Sjdp boolean dynamic; 173533965Sjdp{ 173633965Sjdp struct external_nlist *ext_end; 173733965Sjdp 173833965Sjdp ext_end = ext + count; 173933965Sjdp for (; ext < ext_end; ext++, in++) 174033965Sjdp { 174133965Sjdp bfd_vma x; 174233965Sjdp 174333965Sjdp x = GET_WORD (abfd, ext->e_strx); 174433965Sjdp in->symbol.the_bfd = abfd; 174533965Sjdp 174633965Sjdp /* For the normal symbols, the zero index points at the number 174733965Sjdp of bytes in the string table but is to be interpreted as the 174833965Sjdp null string. For the dynamic symbols, the number of bytes in 174933965Sjdp the string table is stored in the __DYNAMIC structure and the 175033965Sjdp zero index points at an actual string. */ 175133965Sjdp if (x == 0 && ! dynamic) 175233965Sjdp in->symbol.name = ""; 175333965Sjdp else if (x < strsize) 175433965Sjdp in->symbol.name = str + x; 175533965Sjdp else 175633965Sjdp return false; 175733965Sjdp 175833965Sjdp in->symbol.value = GET_SWORD (abfd, ext->e_value); 175933965Sjdp in->desc = bfd_h_get_16 (abfd, ext->e_desc); 176033965Sjdp in->other = bfd_h_get_8 (abfd, ext->e_other); 176133965Sjdp in->type = bfd_h_get_8 (abfd, ext->e_type); 176233965Sjdp in->symbol.udata.p = NULL; 176333965Sjdp 176433965Sjdp if (! translate_from_native_sym_flags (abfd, in)) 176533965Sjdp return false; 176633965Sjdp 176733965Sjdp if (dynamic) 176833965Sjdp in->symbol.flags |= BSF_DYNAMIC; 176933965Sjdp } 177033965Sjdp 177133965Sjdp return true; 177233965Sjdp} 177333965Sjdp 177433965Sjdp/* We read the symbols into a buffer, which is discarded when this 177533965Sjdp function exits. We read the strings into a buffer large enough to 177633965Sjdp hold them all plus all the cached symbol entries. */ 177733965Sjdp 177833965Sjdpboolean 177933965SjdpNAME(aout,slurp_symbol_table) (abfd) 178033965Sjdp bfd *abfd; 178133965Sjdp{ 178233965Sjdp struct external_nlist *old_external_syms; 178333965Sjdp aout_symbol_type *cached; 178433965Sjdp size_t cached_size; 178533965Sjdp 178633965Sjdp /* If there's no work to be done, don't do any */ 178733965Sjdp if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL) 178833965Sjdp return true; 178933965Sjdp 179033965Sjdp old_external_syms = obj_aout_external_syms (abfd); 179133965Sjdp 179233965Sjdp if (! aout_get_external_symbols (abfd)) 179333965Sjdp return false; 179433965Sjdp 179533965Sjdp cached_size = (obj_aout_external_sym_count (abfd) 179633965Sjdp * sizeof (aout_symbol_type)); 179733965Sjdp cached = (aout_symbol_type *) bfd_malloc (cached_size); 179833965Sjdp if (cached == NULL && cached_size != 0) 179933965Sjdp return false; 180033965Sjdp if (cached_size != 0) 180133965Sjdp memset (cached, 0, cached_size); 180233965Sjdp 180333965Sjdp /* Convert from external symbol information to internal. */ 180433965Sjdp if (! (NAME(aout,translate_symbol_table) 180533965Sjdp (abfd, cached, 180633965Sjdp obj_aout_external_syms (abfd), 180733965Sjdp obj_aout_external_sym_count (abfd), 180833965Sjdp obj_aout_external_strings (abfd), 180933965Sjdp obj_aout_external_string_size (abfd), 181033965Sjdp false))) 181133965Sjdp { 181233965Sjdp free (cached); 181333965Sjdp return false; 181433965Sjdp } 181533965Sjdp 181633965Sjdp bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd); 181733965Sjdp 181833965Sjdp obj_aout_symbols (abfd) = cached; 181933965Sjdp 182033965Sjdp /* It is very likely that anybody who calls this function will not 182133965Sjdp want the external symbol information, so if it was allocated 182233965Sjdp because of our call to aout_get_external_symbols, we free it up 182333965Sjdp right away to save space. */ 182433965Sjdp if (old_external_syms == (struct external_nlist *) NULL 182533965Sjdp && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) 182633965Sjdp { 182733965Sjdp#ifdef USE_MMAP 182833965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 182933965Sjdp#else 183033965Sjdp free (obj_aout_external_syms (abfd)); 183133965Sjdp#endif 183233965Sjdp obj_aout_external_syms (abfd) = NULL; 183333965Sjdp } 183433965Sjdp 183533965Sjdp return true; 183633965Sjdp} 183733965Sjdp 183833965Sjdp/* We use a hash table when writing out symbols so that we only write 183933965Sjdp out a particular string once. This helps particularly when the 184033965Sjdp linker writes out stabs debugging entries, because each different 184133965Sjdp contributing object file tends to have many duplicate stabs 184233965Sjdp strings. 184333965Sjdp 184433965Sjdp This hash table code breaks dbx on SunOS 4.1.3, so we don't do it 184533965Sjdp if BFD_TRADITIONAL_FORMAT is set. */ 184633965Sjdp 184733965Sjdpstatic bfd_size_type add_to_stringtab 184833965Sjdp PARAMS ((bfd *, struct bfd_strtab_hash *, const char *, boolean)); 184933965Sjdpstatic boolean emit_stringtab PARAMS ((bfd *, struct bfd_strtab_hash *)); 185033965Sjdp 185133965Sjdp/* Get the index of a string in a strtab, adding it if it is not 185233965Sjdp already present. */ 185333965Sjdp 185433965Sjdpstatic INLINE bfd_size_type 185533965Sjdpadd_to_stringtab (abfd, tab, str, copy) 185633965Sjdp bfd *abfd; 185733965Sjdp struct bfd_strtab_hash *tab; 185833965Sjdp const char *str; 185933965Sjdp boolean copy; 186033965Sjdp{ 186133965Sjdp boolean hash; 186233965Sjdp bfd_size_type index; 186333965Sjdp 186433965Sjdp /* An index of 0 always means the empty string. */ 186533965Sjdp if (str == 0 || *str == '\0') 186633965Sjdp return 0; 186733965Sjdp 186833965Sjdp /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx 186933965Sjdp doesn't understand a hashed string table. */ 187033965Sjdp hash = true; 187133965Sjdp if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0) 187233965Sjdp hash = false; 187333965Sjdp 187433965Sjdp index = _bfd_stringtab_add (tab, str, hash, copy); 187533965Sjdp 187633965Sjdp if (index != (bfd_size_type) -1) 187733965Sjdp { 187833965Sjdp /* Add BYTES_IN_WORD to the return value to account for the 187933965Sjdp space taken up by the string table size. */ 188033965Sjdp index += BYTES_IN_WORD; 188133965Sjdp } 188233965Sjdp 188333965Sjdp return index; 188433965Sjdp} 188533965Sjdp 188633965Sjdp/* Write out a strtab. ABFD is already at the right location in the 188733965Sjdp file. */ 188833965Sjdp 188933965Sjdpstatic boolean 189033965Sjdpemit_stringtab (abfd, tab) 189133965Sjdp register bfd *abfd; 189233965Sjdp struct bfd_strtab_hash *tab; 189333965Sjdp{ 189433965Sjdp bfd_byte buffer[BYTES_IN_WORD]; 189533965Sjdp 189633965Sjdp /* The string table starts with the size. */ 189733965Sjdp PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer); 189833965Sjdp if (bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd) != BYTES_IN_WORD) 189933965Sjdp return false; 190033965Sjdp 190133965Sjdp return _bfd_stringtab_emit (abfd, tab); 190233965Sjdp} 190333965Sjdp 190433965Sjdpboolean 190533965SjdpNAME(aout,write_syms) (abfd) 190633965Sjdp bfd *abfd; 190733965Sjdp{ 190833965Sjdp unsigned int count ; 190933965Sjdp asymbol **generic = bfd_get_outsymbols (abfd); 191033965Sjdp struct bfd_strtab_hash *strtab; 191133965Sjdp 191233965Sjdp strtab = _bfd_stringtab_init (); 191333965Sjdp if (strtab == NULL) 191433965Sjdp return false; 191533965Sjdp 191633965Sjdp for (count = 0; count < bfd_get_symcount (abfd); count++) 191733965Sjdp { 191833965Sjdp asymbol *g = generic[count]; 191933965Sjdp bfd_size_type indx; 192033965Sjdp struct external_nlist nsp; 192133965Sjdp 192233965Sjdp indx = add_to_stringtab (abfd, strtab, g->name, false); 192333965Sjdp if (indx == (bfd_size_type) -1) 192433965Sjdp goto error_return; 192533965Sjdp PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx); 192633965Sjdp 192733965Sjdp if (bfd_asymbol_flavour(g) == abfd->xvec->flavour) 192833965Sjdp { 192933965Sjdp bfd_h_put_16(abfd, aout_symbol(g)->desc, nsp.e_desc); 193033965Sjdp bfd_h_put_8(abfd, aout_symbol(g)->other, nsp.e_other); 193133965Sjdp bfd_h_put_8(abfd, aout_symbol(g)->type, nsp.e_type); 193233965Sjdp } 193333965Sjdp else 193433965Sjdp { 193533965Sjdp bfd_h_put_16(abfd,0, nsp.e_desc); 193633965Sjdp bfd_h_put_8(abfd, 0, nsp.e_other); 193733965Sjdp bfd_h_put_8(abfd, 0, nsp.e_type); 193833965Sjdp } 193933965Sjdp 194033965Sjdp if (! translate_to_native_sym_flags (abfd, g, &nsp)) 194133965Sjdp goto error_return; 194233965Sjdp 194333965Sjdp if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd) 194433965Sjdp != EXTERNAL_NLIST_SIZE) 194533965Sjdp goto error_return; 194633965Sjdp 194733965Sjdp /* NB: `KEEPIT' currently overlays `udata.p', so set this only 194833965Sjdp here, at the end. */ 194933965Sjdp g->KEEPIT = count; 195033965Sjdp } 195133965Sjdp 195233965Sjdp if (! emit_stringtab (abfd, strtab)) 195333965Sjdp goto error_return; 195433965Sjdp 195533965Sjdp _bfd_stringtab_free (strtab); 195633965Sjdp 195733965Sjdp return true; 195833965Sjdp 195933965Sjdperror_return: 196033965Sjdp _bfd_stringtab_free (strtab); 196133965Sjdp return false; 196233965Sjdp} 196333965Sjdp 196433965Sjdp 196533965Sjdplong 196633965SjdpNAME(aout,get_symtab) (abfd, location) 196733965Sjdp bfd *abfd; 196833965Sjdp asymbol **location; 196933965Sjdp{ 197033965Sjdp unsigned int counter = 0; 197133965Sjdp aout_symbol_type *symbase; 197233965Sjdp 197333965Sjdp if (!NAME(aout,slurp_symbol_table)(abfd)) 197433965Sjdp return -1; 197533965Sjdp 197633965Sjdp for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);) 197733965Sjdp *(location++) = (asymbol *)( symbase++); 197833965Sjdp *location++ =0; 197933965Sjdp return bfd_get_symcount (abfd); 198033965Sjdp} 198133965Sjdp 198233965Sjdp 198333965Sjdp/* Standard reloc stuff */ 198433965Sjdp/* Output standard relocation information to a file in target byte order. */ 198533965Sjdp 198633965Sjdpextern void NAME(aout,swap_std_reloc_out) 198733965Sjdp PARAMS ((bfd *, arelent *, struct reloc_std_external *)); 198833965Sjdp 198933965Sjdpvoid 199033965SjdpNAME(aout,swap_std_reloc_out) (abfd, g, natptr) 199133965Sjdp bfd *abfd; 199233965Sjdp arelent *g; 199333965Sjdp struct reloc_std_external *natptr; 199433965Sjdp{ 199533965Sjdp int r_index; 199633965Sjdp asymbol *sym = *(g->sym_ptr_ptr); 199733965Sjdp int r_extern; 199833965Sjdp unsigned int r_length; 199933965Sjdp int r_pcrel; 200033965Sjdp int r_baserel, r_jmptable, r_relative; 200133965Sjdp asection *output_section = sym->section->output_section; 200233965Sjdp 200333965Sjdp PUT_WORD(abfd, g->address, natptr->r_address); 200433965Sjdp 200533965Sjdp r_length = g->howto->size ; /* Size as a power of two */ 200633965Sjdp r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ 200733965Sjdp /* XXX This relies on relocs coming from a.out files. */ 200833965Sjdp r_baserel = (g->howto->type & 8) != 0; 200933965Sjdp r_jmptable = (g->howto->type & 16) != 0; 201033965Sjdp r_relative = (g->howto->type & 32) != 0; 201133965Sjdp 201233965Sjdp#if 0 201333965Sjdp /* For a standard reloc, the addend is in the object file. */ 201433965Sjdp r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma; 201533965Sjdp#endif 201633965Sjdp 201733965Sjdp /* name was clobbered by aout_write_syms to be symbol index */ 201833965Sjdp 201933965Sjdp /* If this relocation is relative to a symbol then set the 202033965Sjdp r_index to the symbols index, and the r_extern bit. 202133965Sjdp 202233965Sjdp Absolute symbols can come in in two ways, either as an offset 202333965Sjdp from the abs section, or as a symbol which has an abs value. 202433965Sjdp check for that here 202533965Sjdp */ 202633965Sjdp 202733965Sjdp 202833965Sjdp if (bfd_is_com_section (output_section) 202933965Sjdp || bfd_is_abs_section (output_section) 203033965Sjdp || bfd_is_und_section (output_section)) 203133965Sjdp { 203233965Sjdp if (bfd_abs_section_ptr->symbol == sym) 203333965Sjdp { 203433965Sjdp /* Whoops, looked like an abs symbol, but is really an offset 203533965Sjdp from the abs section */ 203633965Sjdp r_index = N_ABS; 203733965Sjdp r_extern = 0; 203833965Sjdp } 203933965Sjdp else 204033965Sjdp { 204133965Sjdp /* Fill in symbol */ 204233965Sjdp r_extern = 1; 204333965Sjdp r_index = (*(g->sym_ptr_ptr))->KEEPIT; 204433965Sjdp 204533965Sjdp } 204633965Sjdp } 204733965Sjdp else 204833965Sjdp { 204933965Sjdp /* Just an ordinary section */ 205033965Sjdp r_extern = 0; 205133965Sjdp r_index = output_section->target_index; 205233965Sjdp } 205333965Sjdp 205433965Sjdp /* now the fun stuff */ 205533965Sjdp if (bfd_header_big_endian (abfd)) { 205633965Sjdp natptr->r_index[0] = r_index >> 16; 205733965Sjdp natptr->r_index[1] = r_index >> 8; 205833965Sjdp natptr->r_index[2] = r_index; 205933965Sjdp natptr->r_type[0] = 206033965Sjdp (r_extern? RELOC_STD_BITS_EXTERN_BIG: 0) 206133965Sjdp | (r_pcrel? RELOC_STD_BITS_PCREL_BIG: 0) 206233965Sjdp | (r_baserel? RELOC_STD_BITS_BASEREL_BIG: 0) 206333965Sjdp | (r_jmptable? RELOC_STD_BITS_JMPTABLE_BIG: 0) 206433965Sjdp | (r_relative? RELOC_STD_BITS_RELATIVE_BIG: 0) 206533965Sjdp | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG); 206633965Sjdp } else { 206733965Sjdp natptr->r_index[2] = r_index >> 16; 206833965Sjdp natptr->r_index[1] = r_index >> 8; 206933965Sjdp natptr->r_index[0] = r_index; 207033965Sjdp natptr->r_type[0] = 207133965Sjdp (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0) 207233965Sjdp | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0) 207333965Sjdp | (r_baserel? RELOC_STD_BITS_BASEREL_LITTLE: 0) 207433965Sjdp | (r_jmptable? RELOC_STD_BITS_JMPTABLE_LITTLE: 0) 207533965Sjdp | (r_relative? RELOC_STD_BITS_RELATIVE_LITTLE: 0) 207633965Sjdp | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE); 207733965Sjdp } 207833965Sjdp} 207933965Sjdp 208033965Sjdp 208133965Sjdp/* Extended stuff */ 208233965Sjdp/* Output extended relocation information to a file in target byte order. */ 208333965Sjdp 208433965Sjdpextern void NAME(aout,swap_ext_reloc_out) 208533965Sjdp PARAMS ((bfd *, arelent *, struct reloc_ext_external *)); 208633965Sjdp 208733965Sjdpvoid 208833965SjdpNAME(aout,swap_ext_reloc_out) (abfd, g, natptr) 208933965Sjdp bfd *abfd; 209033965Sjdp arelent *g; 209133965Sjdp register struct reloc_ext_external *natptr; 209233965Sjdp{ 209333965Sjdp int r_index; 209433965Sjdp int r_extern; 209533965Sjdp unsigned int r_type; 209633965Sjdp unsigned int r_addend; 209733965Sjdp asymbol *sym = *(g->sym_ptr_ptr); 209833965Sjdp asection *output_section = sym->section->output_section; 209933965Sjdp 210033965Sjdp PUT_WORD (abfd, g->address, natptr->r_address); 210133965Sjdp 210233965Sjdp r_type = (unsigned int) g->howto->type; 210333965Sjdp 210433965Sjdp r_addend = g->addend; 210533965Sjdp if ((sym->flags & BSF_SECTION_SYM) != 0) 210633965Sjdp r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma; 210733965Sjdp 210833965Sjdp /* If this relocation is relative to a symbol then set the 210933965Sjdp r_index to the symbols index, and the r_extern bit. 211033965Sjdp 211133965Sjdp Absolute symbols can come in in two ways, either as an offset 211233965Sjdp from the abs section, or as a symbol which has an abs value. 211333965Sjdp check for that here. */ 211433965Sjdp 211533965Sjdp if (bfd_is_abs_section (bfd_get_section (sym))) 211633965Sjdp { 211733965Sjdp r_extern = 0; 211833965Sjdp r_index = N_ABS; 211933965Sjdp } 212033965Sjdp else if ((sym->flags & BSF_SECTION_SYM) == 0) 212133965Sjdp { 212233965Sjdp if (bfd_is_und_section (bfd_get_section (sym)) 212333965Sjdp || (sym->flags & BSF_GLOBAL) != 0) 212433965Sjdp r_extern = 1; 212533965Sjdp else 212633965Sjdp r_extern = 0; 212733965Sjdp r_index = (*(g->sym_ptr_ptr))->KEEPIT; 212833965Sjdp } 212933965Sjdp else 213033965Sjdp { 213133965Sjdp /* Just an ordinary section */ 213233965Sjdp r_extern = 0; 213333965Sjdp r_index = output_section->target_index; 213433965Sjdp } 213533965Sjdp 213633965Sjdp /* now the fun stuff */ 213733965Sjdp if (bfd_header_big_endian (abfd)) { 213833965Sjdp natptr->r_index[0] = r_index >> 16; 213933965Sjdp natptr->r_index[1] = r_index >> 8; 214033965Sjdp natptr->r_index[2] = r_index; 214133965Sjdp natptr->r_type[0] = 214233965Sjdp ((r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0) 214333965Sjdp | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG)); 214433965Sjdp } else { 214533965Sjdp natptr->r_index[2] = r_index >> 16; 214633965Sjdp natptr->r_index[1] = r_index >> 8; 214733965Sjdp natptr->r_index[0] = r_index; 214833965Sjdp natptr->r_type[0] = 214933965Sjdp (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0) 215033965Sjdp | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE); 215133965Sjdp } 215233965Sjdp 215333965Sjdp PUT_WORD (abfd, r_addend, natptr->r_addend); 215433965Sjdp} 215533965Sjdp 215633965Sjdp/* BFD deals internally with all things based from the section they're 215733965Sjdp in. so, something in 10 bytes into a text section with a base of 215833965Sjdp 50 would have a symbol (.text+10) and know .text vma was 50. 215933965Sjdp 216033965Sjdp Aout keeps all it's symbols based from zero, so the symbol would 216133965Sjdp contain 60. This macro subs the base of each section from the value 216233965Sjdp to give the true offset from the section */ 216333965Sjdp 216433965Sjdp 216533965Sjdp#define MOVE_ADDRESS(ad) \ 216633965Sjdp if (r_extern) { \ 216733965Sjdp /* undefined symbol */ \ 216833965Sjdp cache_ptr->sym_ptr_ptr = symbols + r_index; \ 216933965Sjdp cache_ptr->addend = ad; \ 217033965Sjdp } else { \ 217133965Sjdp /* defined, section relative. replace symbol with pointer to \ 217233965Sjdp symbol which points to section */ \ 217333965Sjdp switch (r_index) { \ 217433965Sjdp case N_TEXT: \ 217533965Sjdp case N_TEXT | N_EXT: \ 217633965Sjdp cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \ 217733965Sjdp cache_ptr->addend = ad - su->textsec->vma; \ 217833965Sjdp break; \ 217933965Sjdp case N_DATA: \ 218033965Sjdp case N_DATA | N_EXT: \ 218133965Sjdp cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \ 218233965Sjdp cache_ptr->addend = ad - su->datasec->vma; \ 218333965Sjdp break; \ 218433965Sjdp case N_BSS: \ 218533965Sjdp case N_BSS | N_EXT: \ 218633965Sjdp cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \ 218733965Sjdp cache_ptr->addend = ad - su->bsssec->vma; \ 218833965Sjdp break; \ 218933965Sjdp default: \ 219033965Sjdp case N_ABS: \ 219133965Sjdp case N_ABS | N_EXT: \ 219233965Sjdp cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \ 219333965Sjdp cache_ptr->addend = ad; \ 219433965Sjdp break; \ 219533965Sjdp } \ 219633965Sjdp } \ 219733965Sjdp 219833965Sjdpvoid 219933965SjdpNAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) 220033965Sjdp bfd *abfd; 220133965Sjdp struct reloc_ext_external *bytes; 220233965Sjdp arelent *cache_ptr; 220333965Sjdp asymbol **symbols; 220433965Sjdp bfd_size_type symcount; 220533965Sjdp{ 220633965Sjdp unsigned int r_index; 220733965Sjdp int r_extern; 220833965Sjdp unsigned int r_type; 220933965Sjdp struct aoutdata *su = &(abfd->tdata.aout_data->a); 221033965Sjdp 221133965Sjdp cache_ptr->address = (GET_SWORD (abfd, bytes->r_address)); 221233965Sjdp 221333965Sjdp /* now the fun stuff */ 221433965Sjdp if (bfd_header_big_endian (abfd)) { 221533965Sjdp r_index = (bytes->r_index[0] << 16) 221633965Sjdp | (bytes->r_index[1] << 8) 221733965Sjdp | bytes->r_index[2]; 221833965Sjdp r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 221933965Sjdp r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 222033965Sjdp >> RELOC_EXT_BITS_TYPE_SH_BIG; 222133965Sjdp } else { 222233965Sjdp r_index = (bytes->r_index[2] << 16) 222333965Sjdp | (bytes->r_index[1] << 8) 222433965Sjdp | bytes->r_index[0]; 222533965Sjdp r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 222633965Sjdp r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 222733965Sjdp >> RELOC_EXT_BITS_TYPE_SH_LITTLE; 222833965Sjdp } 222933965Sjdp 223033965Sjdp cache_ptr->howto = howto_table_ext + r_type; 223133965Sjdp 223233965Sjdp /* Base relative relocs are always against the symbol table, 223333965Sjdp regardless of the setting of r_extern. r_extern just reflects 223433965Sjdp whether the symbol the reloc is against is local or global. */ 223533965Sjdp if (r_type == RELOC_BASE10 223633965Sjdp || r_type == RELOC_BASE13 223733965Sjdp || r_type == RELOC_BASE22) 223833965Sjdp r_extern = 1; 223933965Sjdp 224033965Sjdp if (r_extern && r_index > symcount) 224133965Sjdp { 224233965Sjdp /* We could arrange to return an error, but it might be useful 224333965Sjdp to see the file even if it is bad. */ 224433965Sjdp r_extern = 0; 224533965Sjdp r_index = N_ABS; 224633965Sjdp } 224733965Sjdp 224833965Sjdp MOVE_ADDRESS(GET_SWORD(abfd, bytes->r_addend)); 224933965Sjdp} 225033965Sjdp 225133965Sjdpvoid 225233965SjdpNAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) 225333965Sjdp bfd *abfd; 225433965Sjdp struct reloc_std_external *bytes; 225533965Sjdp arelent *cache_ptr; 225633965Sjdp asymbol **symbols; 225733965Sjdp bfd_size_type symcount; 225833965Sjdp{ 225933965Sjdp unsigned int r_index; 226033965Sjdp int r_extern; 226133965Sjdp unsigned int r_length; 226233965Sjdp int r_pcrel; 226333965Sjdp int r_baserel, r_jmptable, r_relative; 226433965Sjdp struct aoutdata *su = &(abfd->tdata.aout_data->a); 226533965Sjdp unsigned int howto_idx; 226633965Sjdp 226733965Sjdp cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address); 226833965Sjdp 226933965Sjdp /* now the fun stuff */ 227033965Sjdp if (bfd_header_big_endian (abfd)) { 227133965Sjdp r_index = (bytes->r_index[0] << 16) 227233965Sjdp | (bytes->r_index[1] << 8) 227333965Sjdp | bytes->r_index[2]; 227433965Sjdp r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); 227533965Sjdp r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 227633965Sjdp r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 227733965Sjdp r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 227833965Sjdp r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); 227933965Sjdp r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) 228033965Sjdp >> RELOC_STD_BITS_LENGTH_SH_BIG; 228133965Sjdp } else { 228233965Sjdp r_index = (bytes->r_index[2] << 16) 228333965Sjdp | (bytes->r_index[1] << 8) 228433965Sjdp | bytes->r_index[0]; 228533965Sjdp r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); 228633965Sjdp r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 228733965Sjdp r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); 228833965Sjdp r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); 228933965Sjdp r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE)); 229033965Sjdp r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) 229133965Sjdp >> RELOC_STD_BITS_LENGTH_SH_LITTLE; 229233965Sjdp } 229333965Sjdp 229433965Sjdp howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel 229533965Sjdp + 16 * r_jmptable + 32 * r_relative; 229633965Sjdp BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); 229733965Sjdp cache_ptr->howto = howto_table_std + howto_idx; 229833965Sjdp BFD_ASSERT (cache_ptr->howto->type != (unsigned int) -1); 229933965Sjdp 230033965Sjdp /* Base relative relocs are always against the symbol table, 230133965Sjdp regardless of the setting of r_extern. r_extern just reflects 230233965Sjdp whether the symbol the reloc is against is local or global. */ 230333965Sjdp if (r_baserel) 230433965Sjdp r_extern = 1; 230533965Sjdp 230633965Sjdp if (r_extern && r_index > symcount) 230733965Sjdp { 230833965Sjdp /* We could arrange to return an error, but it might be useful 230933965Sjdp to see the file even if it is bad. */ 231033965Sjdp r_extern = 0; 231133965Sjdp r_index = N_ABS; 231233965Sjdp } 231333965Sjdp 231433965Sjdp MOVE_ADDRESS(0); 231533965Sjdp} 231633965Sjdp 231733965Sjdp/* Read and swap the relocs for a section. */ 231833965Sjdp 231933965Sjdpboolean 232033965SjdpNAME(aout,slurp_reloc_table) (abfd, asect, symbols) 232133965Sjdp bfd *abfd; 232233965Sjdp sec_ptr asect; 232333965Sjdp asymbol **symbols; 232433965Sjdp{ 232533965Sjdp unsigned int count; 232633965Sjdp bfd_size_type reloc_size; 232733965Sjdp PTR relocs; 232833965Sjdp arelent *reloc_cache; 232933965Sjdp size_t each_size; 233033965Sjdp unsigned int counter = 0; 233133965Sjdp arelent *cache_ptr; 233233965Sjdp 233333965Sjdp if (asect->relocation) 233433965Sjdp return true; 233533965Sjdp 233633965Sjdp if (asect->flags & SEC_CONSTRUCTOR) 233733965Sjdp return true; 233833965Sjdp 233933965Sjdp if (asect == obj_datasec (abfd)) 234033965Sjdp reloc_size = exec_hdr(abfd)->a_drsize; 234133965Sjdp else if (asect == obj_textsec (abfd)) 234233965Sjdp reloc_size = exec_hdr(abfd)->a_trsize; 234333965Sjdp else if (asect == obj_bsssec (abfd)) 234433965Sjdp reloc_size = 0; 234533965Sjdp else 234633965Sjdp { 234733965Sjdp bfd_set_error (bfd_error_invalid_operation); 234833965Sjdp return false; 234933965Sjdp } 235033965Sjdp 235133965Sjdp if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) 235233965Sjdp return false; 235333965Sjdp 235433965Sjdp each_size = obj_reloc_entry_size (abfd); 235533965Sjdp 235633965Sjdp count = reloc_size / each_size; 235733965Sjdp 235833965Sjdp reloc_cache = (arelent *) bfd_malloc ((size_t) (count * sizeof (arelent))); 235933965Sjdp if (reloc_cache == NULL && count != 0) 236033965Sjdp return false; 236133965Sjdp memset (reloc_cache, 0, count * sizeof (arelent)); 236233965Sjdp 236333965Sjdp relocs = bfd_malloc ((size_t) reloc_size); 236433965Sjdp if (relocs == NULL && reloc_size != 0) 236533965Sjdp { 236633965Sjdp free (reloc_cache); 236733965Sjdp return false; 236833965Sjdp } 236933965Sjdp 237033965Sjdp if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) 237133965Sjdp { 237233965Sjdp free (relocs); 237333965Sjdp free (reloc_cache); 237433965Sjdp return false; 237533965Sjdp } 237633965Sjdp 237733965Sjdp cache_ptr = reloc_cache; 237833965Sjdp if (each_size == RELOC_EXT_SIZE) 237933965Sjdp { 238033965Sjdp register struct reloc_ext_external *rptr = 238133965Sjdp (struct reloc_ext_external *) relocs; 238233965Sjdp 238333965Sjdp for (; counter < count; counter++, rptr++, cache_ptr++) 238433965Sjdp NAME(aout,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols, 238533965Sjdp bfd_get_symcount (abfd)); 238633965Sjdp } 238733965Sjdp else 238833965Sjdp { 238933965Sjdp register struct reloc_std_external *rptr = 239033965Sjdp (struct reloc_std_external *) relocs; 239133965Sjdp 239233965Sjdp for (; counter < count; counter++, rptr++, cache_ptr++) 239333965Sjdp MY_swap_std_reloc_in (abfd, rptr, cache_ptr, symbols, 239433965Sjdp bfd_get_symcount (abfd)); 239533965Sjdp } 239633965Sjdp 239733965Sjdp free (relocs); 239833965Sjdp 239933965Sjdp asect->relocation = reloc_cache; 240033965Sjdp asect->reloc_count = cache_ptr - reloc_cache; 240133965Sjdp 240233965Sjdp return true; 240333965Sjdp} 240433965Sjdp 240533965Sjdp/* Write out a relocation section into an object file. */ 240633965Sjdp 240733965Sjdpboolean 240833965SjdpNAME(aout,squirt_out_relocs) (abfd, section) 240933965Sjdp bfd *abfd; 241033965Sjdp asection *section; 241133965Sjdp{ 241233965Sjdp arelent **generic; 241333965Sjdp unsigned char *native, *natptr; 241433965Sjdp size_t each_size; 241533965Sjdp 241633965Sjdp unsigned int count = section->reloc_count; 241733965Sjdp size_t natsize; 241833965Sjdp 241933965Sjdp if (count == 0 || section->orelocation == NULL) 242033965Sjdp return true; 242133965Sjdp 242233965Sjdp each_size = obj_reloc_entry_size (abfd); 242333965Sjdp natsize = each_size * count; 242433965Sjdp native = (unsigned char *) bfd_zalloc (abfd, natsize); 242533965Sjdp if (!native) 242633965Sjdp return false; 242733965Sjdp 242833965Sjdp generic = section->orelocation; 242933965Sjdp 243033965Sjdp if (each_size == RELOC_EXT_SIZE) 243133965Sjdp { 243233965Sjdp for (natptr = native; 243333965Sjdp count != 0; 243433965Sjdp --count, natptr += each_size, ++generic) 243533965Sjdp NAME(aout,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr); 243633965Sjdp } 243733965Sjdp else 243833965Sjdp { 243933965Sjdp for (natptr = native; 244033965Sjdp count != 0; 244133965Sjdp --count, natptr += each_size, ++generic) 244233965Sjdp MY_swap_std_reloc_out(abfd, *generic, (struct reloc_std_external *)natptr); 244333965Sjdp } 244433965Sjdp 244533965Sjdp if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) { 244633965Sjdp bfd_release(abfd, native); 244733965Sjdp return false; 244833965Sjdp } 244933965Sjdp bfd_release (abfd, native); 245033965Sjdp 245133965Sjdp return true; 245233965Sjdp} 245333965Sjdp 245433965Sjdp/* This is stupid. This function should be a boolean predicate */ 245533965Sjdplong 245633965SjdpNAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols) 245733965Sjdp bfd *abfd; 245833965Sjdp sec_ptr section; 245933965Sjdp arelent **relptr; 246033965Sjdp asymbol **symbols; 246133965Sjdp{ 246233965Sjdp arelent *tblptr = section->relocation; 246333965Sjdp unsigned int count; 246433965Sjdp 246533965Sjdp if (section == obj_bsssec (abfd)) 246633965Sjdp { 246733965Sjdp *relptr = NULL; 246833965Sjdp return 0; 246933965Sjdp } 247033965Sjdp 247133965Sjdp if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols))) 247233965Sjdp return -1; 247333965Sjdp 247433965Sjdp if (section->flags & SEC_CONSTRUCTOR) { 247533965Sjdp arelent_chain *chain = section->constructor_chain; 247633965Sjdp for (count = 0; count < section->reloc_count; count ++) { 247733965Sjdp *relptr ++ = &chain->relent; 247833965Sjdp chain = chain->next; 247933965Sjdp } 248033965Sjdp } 248133965Sjdp else { 248233965Sjdp tblptr = section->relocation; 248333965Sjdp 248433965Sjdp for (count = 0; count++ < section->reloc_count;) 248533965Sjdp { 248633965Sjdp *relptr++ = tblptr++; 248733965Sjdp } 248833965Sjdp } 248933965Sjdp *relptr = 0; 249033965Sjdp 249133965Sjdp return section->reloc_count; 249233965Sjdp} 249333965Sjdp 249433965Sjdplong 249533965SjdpNAME(aout,get_reloc_upper_bound) (abfd, asect) 249633965Sjdp bfd *abfd; 249733965Sjdp sec_ptr asect; 249833965Sjdp{ 249933965Sjdp if (bfd_get_format (abfd) != bfd_object) { 250033965Sjdp bfd_set_error (bfd_error_invalid_operation); 250133965Sjdp return -1; 250233965Sjdp } 250333965Sjdp if (asect->flags & SEC_CONSTRUCTOR) { 250433965Sjdp return (sizeof (arelent *) * (asect->reloc_count+1)); 250533965Sjdp } 250633965Sjdp 250733965Sjdp if (asect == obj_datasec (abfd)) 250833965Sjdp return (sizeof (arelent *) 250933965Sjdp * ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd)) 251033965Sjdp + 1)); 251133965Sjdp 251233965Sjdp if (asect == obj_textsec (abfd)) 251333965Sjdp return (sizeof (arelent *) 251433965Sjdp * ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd)) 251533965Sjdp + 1)); 251633965Sjdp 251733965Sjdp if (asect == obj_bsssec (abfd)) 251833965Sjdp return sizeof (arelent *); 251933965Sjdp 252033965Sjdp if (asect == obj_bsssec (abfd)) 252133965Sjdp return 0; 252233965Sjdp 252333965Sjdp bfd_set_error (bfd_error_invalid_operation); 252433965Sjdp return -1; 252533965Sjdp} 252633965Sjdp 252733965Sjdp 252833965Sjdplong 252933965SjdpNAME(aout,get_symtab_upper_bound) (abfd) 253033965Sjdp bfd *abfd; 253133965Sjdp{ 253233965Sjdp if (!NAME(aout,slurp_symbol_table)(abfd)) 253333965Sjdp return -1; 253433965Sjdp 253533965Sjdp return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *)); 253633965Sjdp} 253733965Sjdp 253833965Sjdp/*ARGSUSED*/ 253933965Sjdp alent * 254033965SjdpNAME(aout,get_lineno) (ignore_abfd, ignore_symbol) 254160484Sobrien bfd *ignore_abfd ATTRIBUTE_UNUSED; 254260484Sobrien asymbol *ignore_symbol ATTRIBUTE_UNUSED; 254333965Sjdp{ 254460484Sobrien return (alent *)NULL; 254533965Sjdp} 254633965Sjdp 254733965Sjdp/*ARGSUSED*/ 254833965Sjdpvoid 254933965SjdpNAME(aout,get_symbol_info) (ignore_abfd, symbol, ret) 255060484Sobrien bfd *ignore_abfd ATTRIBUTE_UNUSED; 255133965Sjdp asymbol *symbol; 255233965Sjdp symbol_info *ret; 255333965Sjdp{ 255433965Sjdp bfd_symbol_info (symbol, ret); 255533965Sjdp 255633965Sjdp if (ret->type == '?') 255733965Sjdp { 255833965Sjdp int type_code = aout_symbol(symbol)->type & 0xff; 255933965Sjdp const char *stab_name = bfd_get_stab_name (type_code); 256033965Sjdp static char buf[10]; 256133965Sjdp 256233965Sjdp if (stab_name == NULL) 256333965Sjdp { 256433965Sjdp sprintf(buf, "(%d)", type_code); 256533965Sjdp stab_name = buf; 256633965Sjdp } 256733965Sjdp ret->type = '-'; 256833965Sjdp ret->stab_type = type_code; 256933965Sjdp ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff); 257033965Sjdp ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff); 257133965Sjdp ret->stab_name = stab_name; 257233965Sjdp } 257333965Sjdp} 257433965Sjdp 257533965Sjdp/*ARGSUSED*/ 257633965Sjdpvoid 257733965SjdpNAME(aout,print_symbol) (ignore_abfd, afile, symbol, how) 257860484Sobrien bfd *ignore_abfd ATTRIBUTE_UNUSED; 257933965Sjdp PTR afile; 258033965Sjdp asymbol *symbol; 258133965Sjdp bfd_print_symbol_type how; 258233965Sjdp{ 258333965Sjdp FILE *file = (FILE *)afile; 258433965Sjdp 258533965Sjdp switch (how) { 258633965Sjdp case bfd_print_symbol_name: 258733965Sjdp if (symbol->name) 258833965Sjdp fprintf(file,"%s", symbol->name); 258933965Sjdp break; 259033965Sjdp case bfd_print_symbol_more: 259133965Sjdp fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff), 259233965Sjdp (unsigned)(aout_symbol(symbol)->other & 0xff), 259333965Sjdp (unsigned)(aout_symbol(symbol)->type)); 259433965Sjdp break; 259533965Sjdp case bfd_print_symbol_all: 259633965Sjdp { 259733965Sjdp CONST char *section_name = symbol->section->name; 259833965Sjdp 259933965Sjdp 260033965Sjdp bfd_print_symbol_vandf((PTR)file,symbol); 260133965Sjdp 260233965Sjdp fprintf(file," %-5s %04x %02x %02x", 260333965Sjdp section_name, 260433965Sjdp (unsigned)(aout_symbol(symbol)->desc & 0xffff), 260533965Sjdp (unsigned)(aout_symbol(symbol)->other & 0xff), 260633965Sjdp (unsigned)(aout_symbol(symbol)->type & 0xff)); 260733965Sjdp if (symbol->name) 260833965Sjdp fprintf(file," %s", symbol->name); 260933965Sjdp } 261033965Sjdp break; 261133965Sjdp } 261233965Sjdp} 261333965Sjdp 261433965Sjdp/* If we don't have to allocate more than 1MB to hold the generic 261533965Sjdp symbols, we use the generic minisymbol methord: it's faster, since 261633965Sjdp it only translates the symbols once, not multiple times. */ 261733965Sjdp#define MINISYM_THRESHOLD (1000000 / sizeof (asymbol)) 261833965Sjdp 261933965Sjdp/* Read minisymbols. For minisymbols, we use the unmodified a.out 262033965Sjdp symbols. The minisymbol_to_symbol function translates these into 262133965Sjdp BFD asymbol structures. */ 262233965Sjdp 262333965Sjdplong 262433965SjdpNAME(aout,read_minisymbols) (abfd, dynamic, minisymsp, sizep) 262533965Sjdp bfd *abfd; 262633965Sjdp boolean dynamic; 262733965Sjdp PTR *minisymsp; 262833965Sjdp unsigned int *sizep; 262933965Sjdp{ 263033965Sjdp if (dynamic) 263133965Sjdp { 263233965Sjdp /* We could handle the dynamic symbols here as well, but it's 263333965Sjdp easier to hand them off. */ 263433965Sjdp return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); 263533965Sjdp } 263633965Sjdp 263733965Sjdp if (! aout_get_external_symbols (abfd)) 263833965Sjdp return -1; 263933965Sjdp 264033965Sjdp if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD) 264133965Sjdp return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); 264233965Sjdp 264333965Sjdp *minisymsp = (PTR) obj_aout_external_syms (abfd); 264433965Sjdp 264533965Sjdp /* By passing the external symbols back from this routine, we are 264633965Sjdp giving up control over the memory block. Clear 264733965Sjdp obj_aout_external_syms, so that we do not try to free it 264833965Sjdp ourselves. */ 264933965Sjdp obj_aout_external_syms (abfd) = NULL; 265033965Sjdp 265133965Sjdp *sizep = EXTERNAL_NLIST_SIZE; 265233965Sjdp return obj_aout_external_sym_count (abfd); 265333965Sjdp} 265433965Sjdp 265533965Sjdp/* Convert a minisymbol to a BFD asymbol. A minisymbol is just an 265633965Sjdp unmodified a.out symbol. The SYM argument is a structure returned 265733965Sjdp by bfd_make_empty_symbol, which we fill in here. */ 265833965Sjdp 265933965Sjdpasymbol * 266033965SjdpNAME(aout,minisymbol_to_symbol) (abfd, dynamic, minisym, sym) 266133965Sjdp bfd *abfd; 266233965Sjdp boolean dynamic; 266333965Sjdp const PTR minisym; 266433965Sjdp asymbol *sym; 266533965Sjdp{ 266633965Sjdp if (dynamic 266733965Sjdp || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD) 266833965Sjdp return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym); 266933965Sjdp 267033965Sjdp memset (sym, 0, sizeof (aout_symbol_type)); 267133965Sjdp 267233965Sjdp /* We call translate_symbol_table to translate a single symbol. */ 267333965Sjdp if (! (NAME(aout,translate_symbol_table) 267433965Sjdp (abfd, 267533965Sjdp (aout_symbol_type *) sym, 267633965Sjdp (struct external_nlist *) minisym, 267733965Sjdp (bfd_size_type) 1, 267833965Sjdp obj_aout_external_strings (abfd), 267933965Sjdp obj_aout_external_string_size (abfd), 268033965Sjdp false))) 268133965Sjdp return NULL; 268233965Sjdp 268333965Sjdp return sym; 268433965Sjdp} 268533965Sjdp 268633965Sjdp/* 268733965Sjdp provided a BFD, a section and an offset into the section, calculate 268833965Sjdp and return the name of the source file and the line nearest to the 268933965Sjdp wanted location. 269033965Sjdp*/ 269133965Sjdp 269233965Sjdpboolean 269333965SjdpNAME(aout,find_nearest_line) 269433965Sjdp (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr) 269533965Sjdp bfd *abfd; 269633965Sjdp asection *section; 269733965Sjdp asymbol **symbols; 269833965Sjdp bfd_vma offset; 269933965Sjdp CONST char **filename_ptr; 270033965Sjdp CONST char **functionname_ptr; 270133965Sjdp unsigned int *line_ptr; 270233965Sjdp{ 270333965Sjdp /* Run down the file looking for the filename, function and linenumber */ 270433965Sjdp asymbol **p; 270533965Sjdp CONST char *directory_name = NULL; 270633965Sjdp CONST char *main_file_name = NULL; 270733965Sjdp CONST char *current_file_name = NULL; 270833965Sjdp CONST char *line_file_name = NULL; /* Value of current_file_name at line number. */ 270960484Sobrien CONST char *line_directory_name = NULL; /* Value of directory_name at line number. */ 271033965Sjdp bfd_vma low_line_vma = 0; 271133965Sjdp bfd_vma low_func_vma = 0; 271233965Sjdp asymbol *func = 0; 271333965Sjdp size_t filelen, funclen; 271433965Sjdp char *buf; 271533965Sjdp 271633965Sjdp *filename_ptr = abfd->filename; 271733965Sjdp *functionname_ptr = 0; 271833965Sjdp *line_ptr = 0; 271933965Sjdp if (symbols != (asymbol **)NULL) { 272033965Sjdp for (p = symbols; *p; p++) { 272133965Sjdp aout_symbol_type *q = (aout_symbol_type *)(*p); 272233965Sjdp next: 272333965Sjdp switch (q->type){ 272433965Sjdp case N_TEXT: 272533965Sjdp /* If this looks like a file name symbol, and it comes after 272633965Sjdp the line number we have found so far, but before the 272733965Sjdp offset, then we have probably not found the right line 272833965Sjdp number. */ 272933965Sjdp if (q->symbol.value <= offset 273033965Sjdp && ((q->symbol.value > low_line_vma 273133965Sjdp && (line_file_name != NULL 273233965Sjdp || *line_ptr != 0)) 273333965Sjdp || (q->symbol.value > low_func_vma 273433965Sjdp && func != NULL))) 273533965Sjdp { 273633965Sjdp const char *symname; 273733965Sjdp 273833965Sjdp symname = q->symbol.name; 273933965Sjdp if (strcmp (symname + strlen (symname) - 2, ".o") == 0) 274033965Sjdp { 274133965Sjdp if (q->symbol.value > low_line_vma) 274233965Sjdp { 274333965Sjdp *line_ptr = 0; 274433965Sjdp line_file_name = NULL; 274533965Sjdp } 274633965Sjdp if (q->symbol.value > low_func_vma) 274733965Sjdp func = NULL; 274833965Sjdp } 274933965Sjdp } 275033965Sjdp break; 275133965Sjdp 275233965Sjdp case N_SO: 275333965Sjdp /* If this symbol is less than the offset, but greater than 275433965Sjdp the line number we have found so far, then we have not 275533965Sjdp found the right line number. */ 275633965Sjdp if (q->symbol.value <= offset) 275733965Sjdp { 275833965Sjdp if (q->symbol.value > low_line_vma) 275933965Sjdp { 276033965Sjdp *line_ptr = 0; 276133965Sjdp line_file_name = NULL; 276233965Sjdp } 276333965Sjdp if (q->symbol.value > low_func_vma) 276433965Sjdp func = NULL; 276533965Sjdp } 276633965Sjdp 276733965Sjdp main_file_name = current_file_name = q->symbol.name; 276833965Sjdp /* Look ahead to next symbol to check if that too is an N_SO. */ 276933965Sjdp p++; 277033965Sjdp if (*p == NULL) 277133965Sjdp break; 277233965Sjdp q = (aout_symbol_type *)(*p); 277333965Sjdp if (q->type != (int)N_SO) 277433965Sjdp goto next; 277533965Sjdp 277633965Sjdp /* Found a second N_SO First is directory; second is filename. */ 277733965Sjdp directory_name = current_file_name; 277833965Sjdp main_file_name = current_file_name = q->symbol.name; 277933965Sjdp if (obj_textsec(abfd) != section) 278033965Sjdp goto done; 278133965Sjdp break; 278233965Sjdp case N_SOL: 278333965Sjdp current_file_name = q->symbol.name; 278433965Sjdp break; 278533965Sjdp 278633965Sjdp case N_SLINE: 278733965Sjdp 278833965Sjdp case N_DSLINE: 278933965Sjdp case N_BSLINE: 279033965Sjdp /* We'll keep this if it resolves nearer than the one we have 279133965Sjdp already. */ 279233965Sjdp if (q->symbol.value >= low_line_vma 279333965Sjdp && q->symbol.value <= offset) 279433965Sjdp { 279533965Sjdp *line_ptr = q->desc; 279633965Sjdp low_line_vma = q->symbol.value; 279733965Sjdp line_file_name = current_file_name; 279860484Sobrien line_directory_name = directory_name; 279933965Sjdp } 280033965Sjdp break; 280133965Sjdp case N_FUN: 280233965Sjdp { 280333965Sjdp /* We'll keep this if it is nearer than the one we have already */ 280433965Sjdp if (q->symbol.value >= low_func_vma && 280533965Sjdp q->symbol.value <= offset) { 280633965Sjdp low_func_vma = q->symbol.value; 280733965Sjdp func = (asymbol *)q; 280833965Sjdp } 280933965Sjdp else if (q->symbol.value > offset) 281033965Sjdp goto done; 281133965Sjdp } 281233965Sjdp break; 281333965Sjdp } 281433965Sjdp } 281533965Sjdp } 281633965Sjdp 281733965Sjdp done: 281833965Sjdp if (*line_ptr != 0) 281960484Sobrien { 282060484Sobrien main_file_name = line_file_name; 282160484Sobrien directory_name = line_directory_name; 282260484Sobrien } 282333965Sjdp 282433965Sjdp if (main_file_name == NULL 282561843Sobrien || IS_ABSOLUTE_PATH (main_file_name) 282633965Sjdp || directory_name == NULL) 282733965Sjdp filelen = 0; 282833965Sjdp else 282933965Sjdp filelen = strlen (directory_name) + strlen (main_file_name); 283033965Sjdp if (func == NULL) 283133965Sjdp funclen = 0; 283233965Sjdp else 283333965Sjdp funclen = strlen (bfd_asymbol_name (func)); 283433965Sjdp 283533965Sjdp if (adata (abfd).line_buf != NULL) 283633965Sjdp free (adata (abfd).line_buf); 283733965Sjdp if (filelen + funclen == 0) 283833965Sjdp adata (abfd).line_buf = buf = NULL; 283933965Sjdp else 284033965Sjdp { 284133965Sjdp buf = (char *) bfd_malloc (filelen + funclen + 3); 284233965Sjdp adata (abfd).line_buf = buf; 284333965Sjdp if (buf == NULL) 284433965Sjdp return false; 284533965Sjdp } 284633965Sjdp 284733965Sjdp if (main_file_name != NULL) 284833965Sjdp { 284961843Sobrien if (IS_ABSOLUTE_PATH (main_file_name) || directory_name == NULL) 285033965Sjdp *filename_ptr = main_file_name; 285133965Sjdp else 285233965Sjdp { 285333965Sjdp sprintf (buf, "%s%s", directory_name, main_file_name); 285433965Sjdp *filename_ptr = buf; 285533965Sjdp buf += filelen + 1; 285633965Sjdp } 285733965Sjdp } 285833965Sjdp 285933965Sjdp if (func) 286033965Sjdp { 286133965Sjdp const char *function = func->name; 286233965Sjdp char *p; 286333965Sjdp 286433965Sjdp /* The caller expects a symbol name. We actually have a 286533965Sjdp function name, without the leading underscore. Put the 286633965Sjdp underscore back in, so that the caller gets a symbol name. */ 286733965Sjdp if (bfd_get_symbol_leading_char (abfd) == '\0') 286833965Sjdp strcpy (buf, function); 286933965Sjdp else 287033965Sjdp { 287133965Sjdp buf[0] = bfd_get_symbol_leading_char (abfd); 287233965Sjdp strcpy (buf + 1, function); 287333965Sjdp } 287433965Sjdp /* Have to remove : stuff */ 287533965Sjdp p = strchr (buf, ':'); 287633965Sjdp if (p != NULL) 287733965Sjdp *p = '\0'; 287833965Sjdp *functionname_ptr = buf; 287933965Sjdp } 288033965Sjdp 288133965Sjdp return true; 288233965Sjdp} 288333965Sjdp 288433965Sjdp/*ARGSUSED*/ 288533965Sjdpint 288633965SjdpNAME(aout,sizeof_headers) (abfd, execable) 288733965Sjdp bfd *abfd; 288860484Sobrien boolean execable ATTRIBUTE_UNUSED; 288933965Sjdp{ 289033965Sjdp return adata(abfd).exec_bytes_size; 289133965Sjdp} 289233965Sjdp 289333965Sjdp/* Free all information we have cached for this BFD. We can always 289433965Sjdp read it again later if we need it. */ 289533965Sjdp 289633965Sjdpboolean 289733965SjdpNAME(aout,bfd_free_cached_info) (abfd) 289833965Sjdp bfd *abfd; 289933965Sjdp{ 290033965Sjdp asection *o; 290133965Sjdp 290233965Sjdp if (bfd_get_format (abfd) != bfd_object) 290333965Sjdp return true; 290433965Sjdp 290533965Sjdp#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; } 290633965Sjdp BFCI_FREE (obj_aout_symbols (abfd)); 290733965Sjdp#ifdef USE_MMAP 290833965Sjdp obj_aout_external_syms (abfd) = 0; 290933965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 291033965Sjdp bfd_free_window (&obj_aout_string_window (abfd)); 291133965Sjdp obj_aout_external_strings (abfd) = 0; 291233965Sjdp#else 291333965Sjdp BFCI_FREE (obj_aout_external_syms (abfd)); 291433965Sjdp BFCI_FREE (obj_aout_external_strings (abfd)); 291533965Sjdp#endif 291633965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 291733965Sjdp BFCI_FREE (o->relocation); 291833965Sjdp#undef BFCI_FREE 291933965Sjdp 292033965Sjdp return true; 292133965Sjdp} 292233965Sjdp 292333965Sjdp/* a.out link code. */ 292433965Sjdp 292533965Sjdpstatic boolean aout_link_add_object_symbols 292633965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 292733965Sjdpstatic boolean aout_link_check_archive_element 292833965Sjdp PARAMS ((bfd *, struct bfd_link_info *, boolean *)); 292933965Sjdpstatic boolean aout_link_free_symbols PARAMS ((bfd *)); 293033965Sjdpstatic boolean aout_link_check_ar_symbols 293133965Sjdp PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded)); 293233965Sjdpstatic boolean aout_link_add_symbols 293333965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 293433965Sjdp 293533965Sjdp/* Routine to create an entry in an a.out link hash table. */ 293633965Sjdp 293733965Sjdpstruct bfd_hash_entry * 293833965SjdpNAME(aout,link_hash_newfunc) (entry, table, string) 293933965Sjdp struct bfd_hash_entry *entry; 294033965Sjdp struct bfd_hash_table *table; 294133965Sjdp const char *string; 294233965Sjdp{ 294333965Sjdp struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry; 294433965Sjdp 294533965Sjdp /* Allocate the structure if it has not already been allocated by a 294633965Sjdp subclass. */ 294733965Sjdp if (ret == (struct aout_link_hash_entry *) NULL) 294833965Sjdp ret = ((struct aout_link_hash_entry *) 294933965Sjdp bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry))); 295033965Sjdp if (ret == (struct aout_link_hash_entry *) NULL) 295133965Sjdp return (struct bfd_hash_entry *) ret; 295233965Sjdp 295333965Sjdp /* Call the allocation method of the superclass. */ 295433965Sjdp ret = ((struct aout_link_hash_entry *) 295533965Sjdp _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, 295633965Sjdp table, string)); 295733965Sjdp if (ret) 295833965Sjdp { 295933965Sjdp /* Set local fields. */ 296033965Sjdp ret->written = false; 296133965Sjdp ret->indx = -1; 296233965Sjdp } 296333965Sjdp 296433965Sjdp return (struct bfd_hash_entry *) ret; 296533965Sjdp} 296633965Sjdp 296733965Sjdp/* Initialize an a.out link hash table. */ 296833965Sjdp 296933965Sjdpboolean 297033965SjdpNAME(aout,link_hash_table_init) (table, abfd, newfunc) 297133965Sjdp struct aout_link_hash_table *table; 297233965Sjdp bfd *abfd; 297333965Sjdp struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, 297433965Sjdp struct bfd_hash_table *, 297533965Sjdp const char *)); 297633965Sjdp{ 297733965Sjdp return _bfd_link_hash_table_init (&table->root, abfd, newfunc); 297833965Sjdp} 297933965Sjdp 298033965Sjdp/* Create an a.out link hash table. */ 298133965Sjdp 298233965Sjdpstruct bfd_link_hash_table * 298333965SjdpNAME(aout,link_hash_table_create) (abfd) 298433965Sjdp bfd *abfd; 298533965Sjdp{ 298633965Sjdp struct aout_link_hash_table *ret; 298733965Sjdp 298833965Sjdp ret = ((struct aout_link_hash_table *) 298933965Sjdp bfd_alloc (abfd, sizeof (struct aout_link_hash_table))); 299033965Sjdp if (ret == NULL) 299133965Sjdp return (struct bfd_link_hash_table *) NULL; 299233965Sjdp if (! NAME(aout,link_hash_table_init) (ret, abfd, 299333965Sjdp NAME(aout,link_hash_newfunc))) 299433965Sjdp { 299533965Sjdp free (ret); 299633965Sjdp return (struct bfd_link_hash_table *) NULL; 299733965Sjdp } 299833965Sjdp return &ret->root; 299933965Sjdp} 300033965Sjdp 300133965Sjdp/* Given an a.out BFD, add symbols to the global hash table as 300233965Sjdp appropriate. */ 300333965Sjdp 300433965Sjdpboolean 300533965SjdpNAME(aout,link_add_symbols) (abfd, info) 300633965Sjdp bfd *abfd; 300733965Sjdp struct bfd_link_info *info; 300833965Sjdp{ 300933965Sjdp switch (bfd_get_format (abfd)) 301033965Sjdp { 301133965Sjdp case bfd_object: 301233965Sjdp return aout_link_add_object_symbols (abfd, info); 301333965Sjdp case bfd_archive: 301433965Sjdp return _bfd_generic_link_add_archive_symbols 301533965Sjdp (abfd, info, aout_link_check_archive_element); 301633965Sjdp default: 301733965Sjdp bfd_set_error (bfd_error_wrong_format); 301833965Sjdp return false; 301933965Sjdp } 302033965Sjdp} 302133965Sjdp 302233965Sjdp/* Add symbols from an a.out object file. */ 302333965Sjdp 302433965Sjdpstatic boolean 302533965Sjdpaout_link_add_object_symbols (abfd, info) 302633965Sjdp bfd *abfd; 302733965Sjdp struct bfd_link_info *info; 302833965Sjdp{ 302933965Sjdp if (! aout_get_external_symbols (abfd)) 303033965Sjdp return false; 303133965Sjdp if (! aout_link_add_symbols (abfd, info)) 303233965Sjdp return false; 303333965Sjdp if (! info->keep_memory) 303433965Sjdp { 303533965Sjdp if (! aout_link_free_symbols (abfd)) 303633965Sjdp return false; 303733965Sjdp } 303833965Sjdp return true; 303933965Sjdp} 304033965Sjdp 304133965Sjdp/* Check a single archive element to see if we need to include it in 304233965Sjdp the link. *PNEEDED is set according to whether this element is 304333965Sjdp needed in the link or not. This is called from 304433965Sjdp _bfd_generic_link_add_archive_symbols. */ 304533965Sjdp 304633965Sjdpstatic boolean 304733965Sjdpaout_link_check_archive_element (abfd, info, pneeded) 304833965Sjdp bfd *abfd; 304933965Sjdp struct bfd_link_info *info; 305033965Sjdp boolean *pneeded; 305133965Sjdp{ 305233965Sjdp if (! aout_get_external_symbols (abfd)) 305333965Sjdp return false; 305433965Sjdp 305533965Sjdp if (! aout_link_check_ar_symbols (abfd, info, pneeded)) 305633965Sjdp return false; 305733965Sjdp 305833965Sjdp if (*pneeded) 305933965Sjdp { 306033965Sjdp if (! aout_link_add_symbols (abfd, info)) 306133965Sjdp return false; 306233965Sjdp } 306333965Sjdp 306433965Sjdp if (! info->keep_memory || ! *pneeded) 306533965Sjdp { 306633965Sjdp if (! aout_link_free_symbols (abfd)) 306733965Sjdp return false; 306833965Sjdp } 306933965Sjdp 307033965Sjdp return true; 307133965Sjdp} 307233965Sjdp 307333965Sjdp/* Free up the internal symbols read from an a.out file. */ 307433965Sjdp 307533965Sjdpstatic boolean 307633965Sjdpaout_link_free_symbols (abfd) 307733965Sjdp bfd *abfd; 307833965Sjdp{ 307933965Sjdp if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) 308033965Sjdp { 308133965Sjdp#ifdef USE_MMAP 308233965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 308333965Sjdp#else 308433965Sjdp free ((PTR) obj_aout_external_syms (abfd)); 308533965Sjdp#endif 308633965Sjdp obj_aout_external_syms (abfd) = (struct external_nlist *) NULL; 308733965Sjdp } 308833965Sjdp if (obj_aout_external_strings (abfd) != (char *) NULL) 308933965Sjdp { 309033965Sjdp#ifdef USE_MMAP 309133965Sjdp bfd_free_window (&obj_aout_string_window (abfd)); 309233965Sjdp#else 309333965Sjdp free ((PTR) obj_aout_external_strings (abfd)); 309433965Sjdp#endif 309533965Sjdp obj_aout_external_strings (abfd) = (char *) NULL; 309633965Sjdp } 309733965Sjdp return true; 309833965Sjdp} 309933965Sjdp 310033965Sjdp/* Look through the internal symbols to see if this object file should 310133965Sjdp be included in the link. We should include this object file if it 310233965Sjdp defines any symbols which are currently undefined. If this object 310333965Sjdp file defines a common symbol, then we may adjust the size of the 310433965Sjdp known symbol but we do not include the object file in the link 310533965Sjdp (unless there is some other reason to include it). */ 310633965Sjdp 310733965Sjdpstatic boolean 310833965Sjdpaout_link_check_ar_symbols (abfd, info, pneeded) 310933965Sjdp bfd *abfd; 311033965Sjdp struct bfd_link_info *info; 311133965Sjdp boolean *pneeded; 311233965Sjdp{ 311333965Sjdp register struct external_nlist *p; 311433965Sjdp struct external_nlist *pend; 311533965Sjdp char *strings; 311633965Sjdp 311733965Sjdp *pneeded = false; 311833965Sjdp 311933965Sjdp /* Look through all the symbols. */ 312033965Sjdp p = obj_aout_external_syms (abfd); 312133965Sjdp pend = p + obj_aout_external_sym_count (abfd); 312233965Sjdp strings = obj_aout_external_strings (abfd); 312333965Sjdp for (; p < pend; p++) 312433965Sjdp { 312533965Sjdp int type = bfd_h_get_8 (abfd, p->e_type); 312633965Sjdp const char *name; 312733965Sjdp struct bfd_link_hash_entry *h; 312833965Sjdp 312933965Sjdp /* Ignore symbols that are not externally visible. This is an 313033965Sjdp optimization only, as we check the type more thoroughly 313133965Sjdp below. */ 313233965Sjdp if (((type & N_EXT) == 0 313333965Sjdp || (type & N_STAB) != 0 313433965Sjdp || type == N_FN) 313533965Sjdp && type != N_WEAKA 313633965Sjdp && type != N_WEAKT 313733965Sjdp && type != N_WEAKD 313833965Sjdp && type != N_WEAKB) 313933965Sjdp { 314033965Sjdp if (type == N_WARNING 314133965Sjdp || type == N_INDR) 314233965Sjdp ++p; 314333965Sjdp continue; 314433965Sjdp } 314533965Sjdp 314633965Sjdp name = strings + GET_WORD (abfd, p->e_strx); 314733965Sjdp h = bfd_link_hash_lookup (info->hash, name, false, false, true); 314833965Sjdp 314933965Sjdp /* We are only interested in symbols that are currently 315033965Sjdp undefined or common. */ 315133965Sjdp if (h == (struct bfd_link_hash_entry *) NULL 315233965Sjdp || (h->type != bfd_link_hash_undefined 315333965Sjdp && h->type != bfd_link_hash_common)) 315433965Sjdp { 315533965Sjdp if (type == (N_INDR | N_EXT)) 315633965Sjdp ++p; 315733965Sjdp continue; 315833965Sjdp } 315933965Sjdp 316033965Sjdp if (type == (N_TEXT | N_EXT) 316133965Sjdp || type == (N_DATA | N_EXT) 316233965Sjdp || type == (N_BSS | N_EXT) 316333965Sjdp || type == (N_ABS | N_EXT) 316433965Sjdp || type == (N_INDR | N_EXT)) 316533965Sjdp { 316633965Sjdp /* This object file defines this symbol. We must link it 316733965Sjdp in. This is true regardless of whether the current 316833965Sjdp definition of the symbol is undefined or common. If the 316933965Sjdp current definition is common, we have a case in which we 317033965Sjdp have already seen an object file including 317133965Sjdp int a; 317233965Sjdp and this object file from the archive includes 317333965Sjdp int a = 5; 317433965Sjdp In such a case we must include this object file. 317533965Sjdp 317633965Sjdp FIXME: The SunOS 4.1.3 linker will pull in the archive 317733965Sjdp element if the symbol is defined in the .data section, 317833965Sjdp but not if it is defined in the .text section. That 317933965Sjdp seems a bit crazy to me, and I haven't implemented it. 318033965Sjdp However, it might be correct. */ 318133965Sjdp if (! (*info->callbacks->add_archive_element) (info, abfd, name)) 318233965Sjdp return false; 318333965Sjdp *pneeded = true; 318433965Sjdp return true; 318533965Sjdp } 318633965Sjdp 318733965Sjdp if (type == (N_UNDF | N_EXT)) 318833965Sjdp { 318933965Sjdp bfd_vma value; 319033965Sjdp 319133965Sjdp value = GET_WORD (abfd, p->e_value); 319233965Sjdp if (value != 0) 319333965Sjdp { 319433965Sjdp /* This symbol is common in the object from the archive 319533965Sjdp file. */ 319633965Sjdp if (h->type == bfd_link_hash_undefined) 319733965Sjdp { 319833965Sjdp bfd *symbfd; 319933965Sjdp unsigned int power; 320033965Sjdp 320133965Sjdp symbfd = h->u.undef.abfd; 320233965Sjdp if (symbfd == (bfd *) NULL) 320333965Sjdp { 320433965Sjdp /* This symbol was created as undefined from 320533965Sjdp outside BFD. We assume that we should link 320633965Sjdp in the object file. This is done for the -u 320733965Sjdp option in the linker. */ 320833965Sjdp if (! (*info->callbacks->add_archive_element) (info, 320933965Sjdp abfd, 321033965Sjdp name)) 321133965Sjdp return false; 321233965Sjdp *pneeded = true; 321333965Sjdp return true; 321433965Sjdp } 321533965Sjdp /* Turn the current link symbol into a common 321633965Sjdp symbol. It is already on the undefs list. */ 321733965Sjdp h->type = bfd_link_hash_common; 321833965Sjdp h->u.c.p = ((struct bfd_link_hash_common_entry *) 321933965Sjdp bfd_hash_allocate (&info->hash->table, 322033965Sjdp sizeof (struct bfd_link_hash_common_entry))); 322133965Sjdp if (h->u.c.p == NULL) 322233965Sjdp return false; 322333965Sjdp 322433965Sjdp h->u.c.size = value; 322533965Sjdp 322633965Sjdp /* FIXME: This isn't quite right. The maximum 322733965Sjdp alignment of a common symbol should be set by the 322833965Sjdp architecture of the output file, not of the input 322933965Sjdp file. */ 323033965Sjdp power = bfd_log2 (value); 323133965Sjdp if (power > bfd_get_arch_info (abfd)->section_align_power) 323233965Sjdp power = bfd_get_arch_info (abfd)->section_align_power; 323333965Sjdp h->u.c.p->alignment_power = power; 323433965Sjdp 323533965Sjdp h->u.c.p->section = bfd_make_section_old_way (symbfd, 323633965Sjdp "COMMON"); 323733965Sjdp } 323833965Sjdp else 323933965Sjdp { 324033965Sjdp /* Adjust the size of the common symbol if 324133965Sjdp necessary. */ 324233965Sjdp if (value > h->u.c.size) 324333965Sjdp h->u.c.size = value; 324433965Sjdp } 324533965Sjdp } 324633965Sjdp } 324733965Sjdp 324833965Sjdp if (type == N_WEAKA 324933965Sjdp || type == N_WEAKT 325033965Sjdp || type == N_WEAKD 325133965Sjdp || type == N_WEAKB) 325233965Sjdp { 325333965Sjdp /* This symbol is weak but defined. We must pull it in if 325433965Sjdp the current link symbol is undefined, but we don't want 325533965Sjdp it if the current link symbol is common. */ 325633965Sjdp if (h->type == bfd_link_hash_undefined) 325733965Sjdp { 325833965Sjdp if (! (*info->callbacks->add_archive_element) (info, abfd, name)) 325933965Sjdp return false; 326033965Sjdp *pneeded = true; 326133965Sjdp return true; 326233965Sjdp } 326333965Sjdp } 326433965Sjdp } 326533965Sjdp 326633965Sjdp /* We do not need this object file. */ 326733965Sjdp return true; 326833965Sjdp} 326933965Sjdp 327033965Sjdp/* Add all symbols from an object file to the hash table. */ 327133965Sjdp 327233965Sjdpstatic boolean 327333965Sjdpaout_link_add_symbols (abfd, info) 327433965Sjdp bfd *abfd; 327533965Sjdp struct bfd_link_info *info; 327633965Sjdp{ 327733965Sjdp boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *, 327833965Sjdp const char *, flagword, asection *, 327933965Sjdp bfd_vma, const char *, boolean, 328033965Sjdp boolean, 328133965Sjdp struct bfd_link_hash_entry **)); 328233965Sjdp struct external_nlist *syms; 328333965Sjdp bfd_size_type sym_count; 328433965Sjdp char *strings; 328533965Sjdp boolean copy; 328633965Sjdp struct aout_link_hash_entry **sym_hash; 328733965Sjdp register struct external_nlist *p; 328833965Sjdp struct external_nlist *pend; 328933965Sjdp 329033965Sjdp syms = obj_aout_external_syms (abfd); 329133965Sjdp sym_count = obj_aout_external_sym_count (abfd); 329233965Sjdp strings = obj_aout_external_strings (abfd); 329333965Sjdp if (info->keep_memory) 329433965Sjdp copy = false; 329533965Sjdp else 329633965Sjdp copy = true; 329733965Sjdp 329833965Sjdp if (aout_backend_info (abfd)->add_dynamic_symbols != NULL) 329933965Sjdp { 330033965Sjdp if (! ((*aout_backend_info (abfd)->add_dynamic_symbols) 330133965Sjdp (abfd, info, &syms, &sym_count, &strings))) 330233965Sjdp return false; 330333965Sjdp } 330433965Sjdp 330533965Sjdp /* We keep a list of the linker hash table entries that correspond 330633965Sjdp to particular symbols. We could just look them up in the hash 330733965Sjdp table, but keeping the list is more efficient. Perhaps this 330833965Sjdp should be conditional on info->keep_memory. */ 330933965Sjdp sym_hash = ((struct aout_link_hash_entry **) 331033965Sjdp bfd_alloc (abfd, 331133965Sjdp ((size_t) sym_count 331233965Sjdp * sizeof (struct aout_link_hash_entry *)))); 331333965Sjdp if (sym_hash == NULL && sym_count != 0) 331433965Sjdp return false; 331533965Sjdp obj_aout_sym_hashes (abfd) = sym_hash; 331633965Sjdp 331733965Sjdp add_one_symbol = aout_backend_info (abfd)->add_one_symbol; 331833965Sjdp if (add_one_symbol == NULL) 331933965Sjdp add_one_symbol = _bfd_generic_link_add_one_symbol; 332033965Sjdp 332133965Sjdp p = syms; 332233965Sjdp pend = p + sym_count; 332333965Sjdp for (; p < pend; p++, sym_hash++) 332433965Sjdp { 332533965Sjdp int type; 332633965Sjdp const char *name; 332733965Sjdp bfd_vma value; 332833965Sjdp asection *section; 332933965Sjdp flagword flags; 333033965Sjdp const char *string; 333133965Sjdp 333233965Sjdp *sym_hash = NULL; 333333965Sjdp 333433965Sjdp type = bfd_h_get_8 (abfd, p->e_type); 333533965Sjdp 333633965Sjdp /* Ignore debugging symbols. */ 333733965Sjdp if ((type & N_STAB) != 0) 333833965Sjdp continue; 333933965Sjdp 334033965Sjdp name = strings + GET_WORD (abfd, p->e_strx); 334133965Sjdp value = GET_WORD (abfd, p->e_value); 334233965Sjdp flags = BSF_GLOBAL; 334333965Sjdp string = NULL; 334433965Sjdp switch (type) 334533965Sjdp { 334633965Sjdp default: 334733965Sjdp abort (); 334833965Sjdp 334933965Sjdp case N_UNDF: 335033965Sjdp case N_ABS: 335133965Sjdp case N_TEXT: 335233965Sjdp case N_DATA: 335333965Sjdp case N_BSS: 335433965Sjdp case N_FN_SEQ: 335533965Sjdp case N_COMM: 335633965Sjdp case N_SETV: 335733965Sjdp case N_FN: 335833965Sjdp /* Ignore symbols that are not externally visible. */ 335933965Sjdp continue; 336033965Sjdp case N_INDR: 336133965Sjdp /* Ignore local indirect symbol. */ 336233965Sjdp ++p; 336333965Sjdp ++sym_hash; 336433965Sjdp continue; 336533965Sjdp 336633965Sjdp case N_UNDF | N_EXT: 336733965Sjdp if (value == 0) 336833965Sjdp { 336933965Sjdp section = bfd_und_section_ptr; 337033965Sjdp flags = 0; 337133965Sjdp } 337233965Sjdp else 337333965Sjdp section = bfd_com_section_ptr; 337433965Sjdp break; 337533965Sjdp case N_ABS | N_EXT: 337633965Sjdp section = bfd_abs_section_ptr; 337733965Sjdp break; 337833965Sjdp case N_TEXT | N_EXT: 337933965Sjdp section = obj_textsec (abfd); 338033965Sjdp value -= bfd_get_section_vma (abfd, section); 338133965Sjdp break; 338233965Sjdp case N_DATA | N_EXT: 338333965Sjdp case N_SETV | N_EXT: 338433965Sjdp /* Treat N_SETV symbols as N_DATA symbol; see comment in 338533965Sjdp translate_from_native_sym_flags. */ 338633965Sjdp section = obj_datasec (abfd); 338733965Sjdp value -= bfd_get_section_vma (abfd, section); 338833965Sjdp break; 338933965Sjdp case N_BSS | N_EXT: 339033965Sjdp section = obj_bsssec (abfd); 339133965Sjdp value -= bfd_get_section_vma (abfd, section); 339233965Sjdp break; 339333965Sjdp case N_INDR | N_EXT: 339433965Sjdp /* An indirect symbol. The next symbol is the symbol 339533965Sjdp which this one really is. */ 339633965Sjdp BFD_ASSERT (p + 1 < pend); 339733965Sjdp ++p; 339833965Sjdp string = strings + GET_WORD (abfd, p->e_strx); 339933965Sjdp section = bfd_ind_section_ptr; 340033965Sjdp flags |= BSF_INDIRECT; 340133965Sjdp break; 340233965Sjdp case N_COMM | N_EXT: 340333965Sjdp section = bfd_com_section_ptr; 340433965Sjdp break; 340533965Sjdp case N_SETA: case N_SETA | N_EXT: 340633965Sjdp section = bfd_abs_section_ptr; 340733965Sjdp flags |= BSF_CONSTRUCTOR; 340833965Sjdp break; 340933965Sjdp case N_SETT: case N_SETT | N_EXT: 341033965Sjdp section = obj_textsec (abfd); 341133965Sjdp flags |= BSF_CONSTRUCTOR; 341233965Sjdp value -= bfd_get_section_vma (abfd, section); 341333965Sjdp break; 341433965Sjdp case N_SETD: case N_SETD | N_EXT: 341533965Sjdp section = obj_datasec (abfd); 341633965Sjdp flags |= BSF_CONSTRUCTOR; 341733965Sjdp value -= bfd_get_section_vma (abfd, section); 341833965Sjdp break; 341933965Sjdp case N_SETB: case N_SETB | N_EXT: 342033965Sjdp section = obj_bsssec (abfd); 342133965Sjdp flags |= BSF_CONSTRUCTOR; 342233965Sjdp value -= bfd_get_section_vma (abfd, section); 342333965Sjdp break; 342433965Sjdp case N_WARNING: 342533965Sjdp /* A warning symbol. The next symbol is the one to warn 342633965Sjdp about. */ 342733965Sjdp BFD_ASSERT (p + 1 < pend); 342833965Sjdp ++p; 342933965Sjdp string = name; 343033965Sjdp name = strings + GET_WORD (abfd, p->e_strx); 343133965Sjdp section = bfd_und_section_ptr; 343233965Sjdp flags |= BSF_WARNING; 343333965Sjdp break; 343433965Sjdp case N_WEAKU: 343533965Sjdp section = bfd_und_section_ptr; 343633965Sjdp flags = BSF_WEAK; 343733965Sjdp break; 343833965Sjdp case N_WEAKA: 343933965Sjdp section = bfd_abs_section_ptr; 344033965Sjdp flags = BSF_WEAK; 344133965Sjdp break; 344233965Sjdp case N_WEAKT: 344333965Sjdp section = obj_textsec (abfd); 344433965Sjdp value -= bfd_get_section_vma (abfd, section); 344533965Sjdp flags = BSF_WEAK; 344633965Sjdp break; 344733965Sjdp case N_WEAKD: 344833965Sjdp section = obj_datasec (abfd); 344933965Sjdp value -= bfd_get_section_vma (abfd, section); 345033965Sjdp flags = BSF_WEAK; 345133965Sjdp break; 345233965Sjdp case N_WEAKB: 345333965Sjdp section = obj_bsssec (abfd); 345433965Sjdp value -= bfd_get_section_vma (abfd, section); 345533965Sjdp flags = BSF_WEAK; 345633965Sjdp break; 345733965Sjdp } 345833965Sjdp 345933965Sjdp if (! ((*add_one_symbol) 346033965Sjdp (info, abfd, name, flags, section, value, string, copy, false, 346133965Sjdp (struct bfd_link_hash_entry **) sym_hash))) 346233965Sjdp return false; 346333965Sjdp 346433965Sjdp /* Restrict the maximum alignment of a common symbol based on 346533965Sjdp the architecture, since a.out has no way to represent 346633965Sjdp alignment requirements of a section in a .o file. FIXME: 346733965Sjdp This isn't quite right: it should use the architecture of the 346833965Sjdp output file, not the input files. */ 346933965Sjdp if ((*sym_hash)->root.type == bfd_link_hash_common 347033965Sjdp && ((*sym_hash)->root.u.c.p->alignment_power > 347133965Sjdp bfd_get_arch_info (abfd)->section_align_power)) 347233965Sjdp (*sym_hash)->root.u.c.p->alignment_power = 347333965Sjdp bfd_get_arch_info (abfd)->section_align_power; 347433965Sjdp 347533965Sjdp /* If this is a set symbol, and we are not building sets, then 347633965Sjdp it is possible for the hash entry to not have been set. In 347733965Sjdp such a case, treat the symbol as not globally defined. */ 347833965Sjdp if ((*sym_hash)->root.type == bfd_link_hash_new) 347933965Sjdp { 348033965Sjdp BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0); 348133965Sjdp *sym_hash = NULL; 348233965Sjdp } 348333965Sjdp 348433965Sjdp if (type == (N_INDR | N_EXT) || type == N_WARNING) 348533965Sjdp ++sym_hash; 348633965Sjdp } 348733965Sjdp 348833965Sjdp return true; 348933965Sjdp} 349033965Sjdp 349133965Sjdp/* A hash table used for header files with N_BINCL entries. */ 349233965Sjdp 349333965Sjdpstruct aout_link_includes_table 349433965Sjdp{ 349533965Sjdp struct bfd_hash_table root; 349633965Sjdp}; 349733965Sjdp 349833965Sjdp/* A linked list of totals that we have found for a particular header 349933965Sjdp file. */ 350033965Sjdp 350133965Sjdpstruct aout_link_includes_totals 350233965Sjdp{ 350333965Sjdp struct aout_link_includes_totals *next; 350433965Sjdp bfd_vma total; 350533965Sjdp}; 350633965Sjdp 350733965Sjdp/* An entry in the header file hash table. */ 350833965Sjdp 350933965Sjdpstruct aout_link_includes_entry 351033965Sjdp{ 351133965Sjdp struct bfd_hash_entry root; 351233965Sjdp /* List of totals we have found for this file. */ 351333965Sjdp struct aout_link_includes_totals *totals; 351433965Sjdp}; 351533965Sjdp 351633965Sjdp/* Look up an entry in an the header file hash table. */ 351733965Sjdp 351833965Sjdp#define aout_link_includes_lookup(table, string, create, copy) \ 351933965Sjdp ((struct aout_link_includes_entry *) \ 352033965Sjdp bfd_hash_lookup (&(table)->root, (string), (create), (copy))) 352133965Sjdp 352233965Sjdp/* During the final link step we need to pass around a bunch of 352333965Sjdp information, so we do it in an instance of this structure. */ 352433965Sjdp 352533965Sjdpstruct aout_final_link_info 352633965Sjdp{ 352733965Sjdp /* General link information. */ 352833965Sjdp struct bfd_link_info *info; 352933965Sjdp /* Output bfd. */ 353033965Sjdp bfd *output_bfd; 353133965Sjdp /* Reloc file positions. */ 353233965Sjdp file_ptr treloff, dreloff; 353333965Sjdp /* File position of symbols. */ 353433965Sjdp file_ptr symoff; 353533965Sjdp /* String table. */ 353633965Sjdp struct bfd_strtab_hash *strtab; 353733965Sjdp /* Header file hash table. */ 353833965Sjdp struct aout_link_includes_table includes; 353933965Sjdp /* A buffer large enough to hold the contents of any section. */ 354033965Sjdp bfd_byte *contents; 354133965Sjdp /* A buffer large enough to hold the relocs of any section. */ 354233965Sjdp PTR relocs; 354333965Sjdp /* A buffer large enough to hold the symbol map of any input BFD. */ 354433965Sjdp int *symbol_map; 354533965Sjdp /* A buffer large enough to hold output symbols of any input BFD. */ 354633965Sjdp struct external_nlist *output_syms; 354733965Sjdp}; 354833965Sjdp 354933965Sjdpstatic struct bfd_hash_entry *aout_link_includes_newfunc 355033965Sjdp PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 355133965Sjdpstatic boolean aout_link_input_bfd 355233965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd)); 355333965Sjdpstatic boolean aout_link_write_symbols 355433965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd)); 355533965Sjdpstatic boolean aout_link_write_other_symbol 355633965Sjdp PARAMS ((struct aout_link_hash_entry *, PTR)); 355733965Sjdpstatic boolean aout_link_input_section 355833965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd, 355933965Sjdp asection *input_section, file_ptr *reloff_ptr, 356033965Sjdp bfd_size_type rel_size)); 356133965Sjdpstatic boolean aout_link_input_section_std 356233965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd, 356333965Sjdp asection *input_section, struct reloc_std_external *, 356433965Sjdp bfd_size_type rel_size, bfd_byte *contents)); 356533965Sjdpstatic boolean aout_link_input_section_ext 356633965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd, 356733965Sjdp asection *input_section, struct reloc_ext_external *, 356833965Sjdp bfd_size_type rel_size, bfd_byte *contents)); 356933965Sjdpstatic INLINE asection *aout_reloc_index_to_section 357033965Sjdp PARAMS ((bfd *, int)); 357133965Sjdpstatic boolean aout_link_reloc_link_order 357233965Sjdp PARAMS ((struct aout_final_link_info *, asection *, 357333965Sjdp struct bfd_link_order *)); 357433965Sjdp 357533965Sjdp/* The function to create a new entry in the header file hash table. */ 357633965Sjdp 357733965Sjdpstatic struct bfd_hash_entry * 357833965Sjdpaout_link_includes_newfunc (entry, table, string) 357933965Sjdp struct bfd_hash_entry *entry; 358033965Sjdp struct bfd_hash_table *table; 358133965Sjdp const char *string; 358233965Sjdp{ 358333965Sjdp struct aout_link_includes_entry *ret = 358433965Sjdp (struct aout_link_includes_entry *) entry; 358533965Sjdp 358633965Sjdp /* Allocate the structure if it has not already been allocated by a 358733965Sjdp subclass. */ 358833965Sjdp if (ret == (struct aout_link_includes_entry *) NULL) 358933965Sjdp ret = ((struct aout_link_includes_entry *) 359033965Sjdp bfd_hash_allocate (table, 359133965Sjdp sizeof (struct aout_link_includes_entry))); 359233965Sjdp if (ret == (struct aout_link_includes_entry *) NULL) 359333965Sjdp return (struct bfd_hash_entry *) ret; 359433965Sjdp 359533965Sjdp /* Call the allocation method of the superclass. */ 359633965Sjdp ret = ((struct aout_link_includes_entry *) 359733965Sjdp bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); 359833965Sjdp if (ret) 359933965Sjdp { 360033965Sjdp /* Set local fields. */ 360133965Sjdp ret->totals = NULL; 360233965Sjdp } 360333965Sjdp 360433965Sjdp return (struct bfd_hash_entry *) ret; 360533965Sjdp} 360633965Sjdp 360733965Sjdp/* Do the final link step. This is called on the output BFD. The 360833965Sjdp INFO structure should point to a list of BFDs linked through the 360933965Sjdp link_next field which can be used to find each BFD which takes part 361033965Sjdp in the output. Also, each section in ABFD should point to a list 361133965Sjdp of bfd_link_order structures which list all the input sections for 361233965Sjdp the output section. */ 361333965Sjdp 361433965Sjdpboolean 361533965SjdpNAME(aout,final_link) (abfd, info, callback) 361633965Sjdp bfd *abfd; 361733965Sjdp struct bfd_link_info *info; 361833965Sjdp void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); 361933965Sjdp{ 362033965Sjdp struct aout_final_link_info aout_info; 362133965Sjdp boolean includes_hash_initialized = false; 362233965Sjdp register bfd *sub; 362333965Sjdp bfd_size_type trsize, drsize; 362433965Sjdp size_t max_contents_size; 362533965Sjdp size_t max_relocs_size; 362633965Sjdp size_t max_sym_count; 362733965Sjdp bfd_size_type text_size; 362833965Sjdp file_ptr text_end; 362933965Sjdp register struct bfd_link_order *p; 363033965Sjdp asection *o; 363133965Sjdp boolean have_link_order_relocs; 363233965Sjdp 363333965Sjdp if (info->shared) 363433965Sjdp abfd->flags |= DYNAMIC; 363533965Sjdp 363633965Sjdp aout_info.info = info; 363733965Sjdp aout_info.output_bfd = abfd; 363833965Sjdp aout_info.contents = NULL; 363933965Sjdp aout_info.relocs = NULL; 364033965Sjdp aout_info.symbol_map = NULL; 364133965Sjdp aout_info.output_syms = NULL; 364233965Sjdp 364333965Sjdp if (! bfd_hash_table_init_n (&aout_info.includes.root, 364433965Sjdp aout_link_includes_newfunc, 364533965Sjdp 251)) 364633965Sjdp goto error_return; 364733965Sjdp includes_hash_initialized = true; 364833965Sjdp 364933965Sjdp /* Figure out the largest section size. Also, if generating 365033965Sjdp relocateable output, count the relocs. */ 365133965Sjdp trsize = 0; 365233965Sjdp drsize = 0; 365333965Sjdp max_contents_size = 0; 365433965Sjdp max_relocs_size = 0; 365533965Sjdp max_sym_count = 0; 365633965Sjdp for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) 365733965Sjdp { 365833965Sjdp size_t sz; 365933965Sjdp 366033965Sjdp if (info->relocateable) 366133965Sjdp { 366233965Sjdp if (bfd_get_flavour (sub) == bfd_target_aout_flavour) 366333965Sjdp { 366433965Sjdp trsize += exec_hdr (sub)->a_trsize; 366533965Sjdp drsize += exec_hdr (sub)->a_drsize; 366633965Sjdp } 366733965Sjdp else 366833965Sjdp { 366933965Sjdp /* FIXME: We need to identify the .text and .data sections 367033965Sjdp and call get_reloc_upper_bound and canonicalize_reloc to 367133965Sjdp work out the number of relocs needed, and then multiply 367233965Sjdp by the reloc size. */ 367333965Sjdp (*_bfd_error_handler) 367460484Sobrien (_("%s: relocateable link from %s to %s not supported"), 367533965Sjdp bfd_get_filename (abfd), 367633965Sjdp sub->xvec->name, abfd->xvec->name); 367733965Sjdp bfd_set_error (bfd_error_invalid_operation); 367833965Sjdp goto error_return; 367933965Sjdp } 368033965Sjdp } 368133965Sjdp 368233965Sjdp if (bfd_get_flavour (sub) == bfd_target_aout_flavour) 368333965Sjdp { 368433965Sjdp sz = bfd_section_size (sub, obj_textsec (sub)); 368533965Sjdp if (sz > max_contents_size) 368633965Sjdp max_contents_size = sz; 368733965Sjdp sz = bfd_section_size (sub, obj_datasec (sub)); 368833965Sjdp if (sz > max_contents_size) 368933965Sjdp max_contents_size = sz; 369033965Sjdp 369133965Sjdp sz = exec_hdr (sub)->a_trsize; 369233965Sjdp if (sz > max_relocs_size) 369333965Sjdp max_relocs_size = sz; 369433965Sjdp sz = exec_hdr (sub)->a_drsize; 369533965Sjdp if (sz > max_relocs_size) 369633965Sjdp max_relocs_size = sz; 369733965Sjdp 369833965Sjdp sz = obj_aout_external_sym_count (sub); 369933965Sjdp if (sz > max_sym_count) 370033965Sjdp max_sym_count = sz; 370133965Sjdp } 370233965Sjdp } 370333965Sjdp 370433965Sjdp if (info->relocateable) 370533965Sjdp { 370633965Sjdp if (obj_textsec (abfd) != (asection *) NULL) 370733965Sjdp trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd) 370833965Sjdp ->link_order_head) 370933965Sjdp * obj_reloc_entry_size (abfd)); 371033965Sjdp if (obj_datasec (abfd) != (asection *) NULL) 371133965Sjdp drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd) 371233965Sjdp ->link_order_head) 371333965Sjdp * obj_reloc_entry_size (abfd)); 371433965Sjdp } 371533965Sjdp 371633965Sjdp exec_hdr (abfd)->a_trsize = trsize; 371733965Sjdp exec_hdr (abfd)->a_drsize = drsize; 371833965Sjdp 371933965Sjdp exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd); 372033965Sjdp 372133965Sjdp /* Adjust the section sizes and vmas according to the magic number. 372233965Sjdp This sets a_text, a_data and a_bss in the exec_hdr and sets the 372333965Sjdp filepos for each section. */ 372433965Sjdp if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) 372533965Sjdp goto error_return; 372633965Sjdp 372733965Sjdp /* The relocation and symbol file positions differ among a.out 372833965Sjdp targets. We are passed a callback routine from the backend 372933965Sjdp specific code to handle this. 373033965Sjdp FIXME: At this point we do not know how much space the symbol 373133965Sjdp table will require. This will not work for any (nonstandard) 373233965Sjdp a.out target that needs to know the symbol table size before it 373333965Sjdp can compute the relocation file positions. This may or may not 373433965Sjdp be the case for the hp300hpux target, for example. */ 373533965Sjdp (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff, 373633965Sjdp &aout_info.symoff); 373733965Sjdp obj_textsec (abfd)->rel_filepos = aout_info.treloff; 373833965Sjdp obj_datasec (abfd)->rel_filepos = aout_info.dreloff; 373933965Sjdp obj_sym_filepos (abfd) = aout_info.symoff; 374033965Sjdp 374133965Sjdp /* We keep a count of the symbols as we output them. */ 374233965Sjdp obj_aout_external_sym_count (abfd) = 0; 374333965Sjdp 374433965Sjdp /* We accumulate the string table as we write out the symbols. */ 374533965Sjdp aout_info.strtab = _bfd_stringtab_init (); 374633965Sjdp if (aout_info.strtab == NULL) 374733965Sjdp goto error_return; 374833965Sjdp 374933965Sjdp /* Allocate buffers to hold section contents and relocs. */ 375033965Sjdp aout_info.contents = (bfd_byte *) bfd_malloc (max_contents_size); 375133965Sjdp aout_info.relocs = (PTR) bfd_malloc (max_relocs_size); 375233965Sjdp aout_info.symbol_map = (int *) bfd_malloc (max_sym_count * sizeof (int *)); 375333965Sjdp aout_info.output_syms = ((struct external_nlist *) 375433965Sjdp bfd_malloc ((max_sym_count + 1) 375533965Sjdp * sizeof (struct external_nlist))); 375633965Sjdp if ((aout_info.contents == NULL && max_contents_size != 0) 375733965Sjdp || (aout_info.relocs == NULL && max_relocs_size != 0) 375833965Sjdp || (aout_info.symbol_map == NULL && max_sym_count != 0) 375933965Sjdp || aout_info.output_syms == NULL) 376033965Sjdp goto error_return; 376133965Sjdp 376233965Sjdp /* If we have a symbol named __DYNAMIC, force it out now. This is 376333965Sjdp required by SunOS. Doing this here rather than in sunos.c is a 376433965Sjdp hack, but it's easier than exporting everything which would be 376533965Sjdp needed. */ 376633965Sjdp { 376733965Sjdp struct aout_link_hash_entry *h; 376833965Sjdp 376933965Sjdp h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC", 377033965Sjdp false, false, false); 377133965Sjdp if (h != NULL) 377233965Sjdp aout_link_write_other_symbol (h, &aout_info); 377333965Sjdp } 377433965Sjdp 377533965Sjdp /* The most time efficient way to do the link would be to read all 377633965Sjdp the input object files into memory and then sort out the 377733965Sjdp information into the output file. Unfortunately, that will 377833965Sjdp probably use too much memory. Another method would be to step 377933965Sjdp through everything that composes the text section and write it 378033965Sjdp out, and then everything that composes the data section and write 378133965Sjdp it out, and then write out the relocs, and then write out the 378233965Sjdp symbols. Unfortunately, that requires reading stuff from each 378333965Sjdp input file several times, and we will not be able to keep all the 378433965Sjdp input files open simultaneously, and reopening them will be slow. 378533965Sjdp 378633965Sjdp What we do is basically process one input file at a time. We do 378733965Sjdp everything we need to do with an input file once--copy over the 378833965Sjdp section contents, handle the relocation information, and write 378933965Sjdp out the symbols--and then we throw away the information we read 379033965Sjdp from it. This approach requires a lot of lseeks of the output 379133965Sjdp file, which is unfortunate but still faster than reopening a lot 379233965Sjdp of files. 379333965Sjdp 379433965Sjdp We use the output_has_begun field of the input BFDs to see 379533965Sjdp whether we have already handled it. */ 379633965Sjdp for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) 379733965Sjdp sub->output_has_begun = false; 379833965Sjdp 379933965Sjdp /* Mark all sections which are to be included in the link. This 380033965Sjdp will normally be every section. We need to do this so that we 380133965Sjdp can identify any sections which the linker has decided to not 380233965Sjdp include. */ 380333965Sjdp for (o = abfd->sections; o != NULL; o = o->next) 380433965Sjdp { 380533965Sjdp for (p = o->link_order_head; p != NULL; p = p->next) 380633965Sjdp { 380733965Sjdp if (p->type == bfd_indirect_link_order) 380833965Sjdp p->u.indirect.section->linker_mark = true; 380933965Sjdp } 381033965Sjdp } 381133965Sjdp 381233965Sjdp have_link_order_relocs = false; 381333965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 381433965Sjdp { 381533965Sjdp for (p = o->link_order_head; 381633965Sjdp p != (struct bfd_link_order *) NULL; 381733965Sjdp p = p->next) 381833965Sjdp { 381933965Sjdp if (p->type == bfd_indirect_link_order 382033965Sjdp && (bfd_get_flavour (p->u.indirect.section->owner) 382133965Sjdp == bfd_target_aout_flavour)) 382233965Sjdp { 382333965Sjdp bfd *input_bfd; 382433965Sjdp 382533965Sjdp input_bfd = p->u.indirect.section->owner; 382633965Sjdp if (! input_bfd->output_has_begun) 382733965Sjdp { 382833965Sjdp if (! aout_link_input_bfd (&aout_info, input_bfd)) 382933965Sjdp goto error_return; 383033965Sjdp input_bfd->output_has_begun = true; 383133965Sjdp } 383233965Sjdp } 383333965Sjdp else if (p->type == bfd_section_reloc_link_order 383433965Sjdp || p->type == bfd_symbol_reloc_link_order) 383533965Sjdp { 383633965Sjdp /* These are handled below. */ 383733965Sjdp have_link_order_relocs = true; 383833965Sjdp } 383933965Sjdp else 384033965Sjdp { 384133965Sjdp if (! _bfd_default_link_order (abfd, info, o, p)) 384233965Sjdp goto error_return; 384333965Sjdp } 384433965Sjdp } 384533965Sjdp } 384633965Sjdp 384733965Sjdp /* Write out any symbols that we have not already written out. */ 384833965Sjdp aout_link_hash_traverse (aout_hash_table (info), 384933965Sjdp aout_link_write_other_symbol, 385033965Sjdp (PTR) &aout_info); 385133965Sjdp 385233965Sjdp /* Now handle any relocs we were asked to create by the linker. 385333965Sjdp These did not come from any input file. We must do these after 385433965Sjdp we have written out all the symbols, so that we know the symbol 385533965Sjdp indices to use. */ 385633965Sjdp if (have_link_order_relocs) 385733965Sjdp { 385833965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 385933965Sjdp { 386033965Sjdp for (p = o->link_order_head; 386133965Sjdp p != (struct bfd_link_order *) NULL; 386233965Sjdp p = p->next) 386333965Sjdp { 386433965Sjdp if (p->type == bfd_section_reloc_link_order 386533965Sjdp || p->type == bfd_symbol_reloc_link_order) 386633965Sjdp { 386733965Sjdp if (! aout_link_reloc_link_order (&aout_info, o, p)) 386833965Sjdp goto error_return; 386933965Sjdp } 387033965Sjdp } 387133965Sjdp } 387233965Sjdp } 387333965Sjdp 387433965Sjdp if (aout_info.contents != NULL) 387533965Sjdp { 387633965Sjdp free (aout_info.contents); 387733965Sjdp aout_info.contents = NULL; 387833965Sjdp } 387933965Sjdp if (aout_info.relocs != NULL) 388033965Sjdp { 388133965Sjdp free (aout_info.relocs); 388233965Sjdp aout_info.relocs = NULL; 388333965Sjdp } 388433965Sjdp if (aout_info.symbol_map != NULL) 388533965Sjdp { 388633965Sjdp free (aout_info.symbol_map); 388733965Sjdp aout_info.symbol_map = NULL; 388833965Sjdp } 388933965Sjdp if (aout_info.output_syms != NULL) 389033965Sjdp { 389133965Sjdp free (aout_info.output_syms); 389233965Sjdp aout_info.output_syms = NULL; 389333965Sjdp } 389433965Sjdp if (includes_hash_initialized) 389533965Sjdp { 389633965Sjdp bfd_hash_table_free (&aout_info.includes.root); 389733965Sjdp includes_hash_initialized = false; 389833965Sjdp } 389933965Sjdp 390033965Sjdp /* Finish up any dynamic linking we may be doing. */ 390133965Sjdp if (aout_backend_info (abfd)->finish_dynamic_link != NULL) 390233965Sjdp { 390333965Sjdp if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info)) 390433965Sjdp goto error_return; 390533965Sjdp } 390633965Sjdp 390733965Sjdp /* Update the header information. */ 390833965Sjdp abfd->symcount = obj_aout_external_sym_count (abfd); 390933965Sjdp exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE; 391033965Sjdp obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms; 391133965Sjdp obj_textsec (abfd)->reloc_count = 391233965Sjdp exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); 391333965Sjdp obj_datasec (abfd)->reloc_count = 391433965Sjdp exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); 391533965Sjdp 391638889Sjdp /* Write out the string table, unless there are no symbols. */ 391738889Sjdp if (abfd->symcount > 0) 391838889Sjdp { 391938889Sjdp if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 392038889Sjdp || ! emit_stringtab (abfd, aout_info.strtab)) 392138889Sjdp goto error_return; 392238889Sjdp } 392338889Sjdp else if (obj_textsec (abfd)->reloc_count == 0 392438889Sjdp && obj_datasec (abfd)->reloc_count == 0) 392538889Sjdp { 392638889Sjdp bfd_byte b; 392733965Sjdp 392838889Sjdp b = 0; 392938889Sjdp if (bfd_seek (abfd, 393038889Sjdp (obj_datasec (abfd)->filepos 393138889Sjdp + exec_hdr (abfd)->a_data 393238889Sjdp - 1), 393338889Sjdp SEEK_SET) != 0 393438889Sjdp || bfd_write (&b, 1, 1, abfd) != 1) 393538889Sjdp goto error_return; 393638889Sjdp } 393738889Sjdp 393838889Sjdp return true; 393938889Sjdp 394033965Sjdp error_return: 394133965Sjdp if (aout_info.contents != NULL) 394233965Sjdp free (aout_info.contents); 394333965Sjdp if (aout_info.relocs != NULL) 394433965Sjdp free (aout_info.relocs); 394533965Sjdp if (aout_info.symbol_map != NULL) 394633965Sjdp free (aout_info.symbol_map); 394733965Sjdp if (aout_info.output_syms != NULL) 394833965Sjdp free (aout_info.output_syms); 394933965Sjdp if (includes_hash_initialized) 395033965Sjdp bfd_hash_table_free (&aout_info.includes.root); 395133965Sjdp return false; 395233965Sjdp} 395333965Sjdp 395433965Sjdp/* Link an a.out input BFD into the output file. */ 395533965Sjdp 395633965Sjdpstatic boolean 395733965Sjdpaout_link_input_bfd (finfo, input_bfd) 395833965Sjdp struct aout_final_link_info *finfo; 395933965Sjdp bfd *input_bfd; 396033965Sjdp{ 396133965Sjdp bfd_size_type sym_count; 396233965Sjdp 396333965Sjdp BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object); 396433965Sjdp 396533965Sjdp /* If this is a dynamic object, it may need special handling. */ 396633965Sjdp if ((input_bfd->flags & DYNAMIC) != 0 396733965Sjdp && aout_backend_info (input_bfd)->link_dynamic_object != NULL) 396833965Sjdp { 396933965Sjdp return ((*aout_backend_info (input_bfd)->link_dynamic_object) 397033965Sjdp (finfo->info, input_bfd)); 397133965Sjdp } 397233965Sjdp 397333965Sjdp /* Get the symbols. We probably have them already, unless 397433965Sjdp finfo->info->keep_memory is false. */ 397533965Sjdp if (! aout_get_external_symbols (input_bfd)) 397633965Sjdp return false; 397733965Sjdp 397833965Sjdp sym_count = obj_aout_external_sym_count (input_bfd); 397933965Sjdp 398033965Sjdp /* Write out the symbols and get a map of the new indices. The map 398133965Sjdp is placed into finfo->symbol_map. */ 398233965Sjdp if (! aout_link_write_symbols (finfo, input_bfd)) 398333965Sjdp return false; 398433965Sjdp 398533965Sjdp /* Relocate and write out the sections. These functions use the 398633965Sjdp symbol map created by aout_link_write_symbols. The linker_mark 398733965Sjdp field will be set if these sections are to be included in the 398833965Sjdp link, which will normally be the case. */ 398933965Sjdp if (obj_textsec (input_bfd)->linker_mark) 399033965Sjdp { 399133965Sjdp if (! aout_link_input_section (finfo, input_bfd, 399233965Sjdp obj_textsec (input_bfd), 399333965Sjdp &finfo->treloff, 399433965Sjdp exec_hdr (input_bfd)->a_trsize)) 399533965Sjdp return false; 399633965Sjdp } 399733965Sjdp if (obj_datasec (input_bfd)->linker_mark) 399833965Sjdp { 399933965Sjdp if (! aout_link_input_section (finfo, input_bfd, 400033965Sjdp obj_datasec (input_bfd), 400133965Sjdp &finfo->dreloff, 400233965Sjdp exec_hdr (input_bfd)->a_drsize)) 400333965Sjdp return false; 400433965Sjdp } 400533965Sjdp 400633965Sjdp /* If we are not keeping memory, we don't need the symbols any 400733965Sjdp longer. We still need them if we are keeping memory, because the 400833965Sjdp strings in the hash table point into them. */ 400933965Sjdp if (! finfo->info->keep_memory) 401033965Sjdp { 401133965Sjdp if (! aout_link_free_symbols (input_bfd)) 401233965Sjdp return false; 401333965Sjdp } 401433965Sjdp 401533965Sjdp return true; 401633965Sjdp} 401733965Sjdp 401833965Sjdp/* Adjust and write out the symbols for an a.out file. Set the new 401933965Sjdp symbol indices into a symbol_map. */ 402033965Sjdp 402133965Sjdpstatic boolean 402233965Sjdpaout_link_write_symbols (finfo, input_bfd) 402333965Sjdp struct aout_final_link_info *finfo; 402433965Sjdp bfd *input_bfd; 402533965Sjdp{ 402633965Sjdp bfd *output_bfd; 402733965Sjdp bfd_size_type sym_count; 402833965Sjdp char *strings; 402933965Sjdp enum bfd_link_strip strip; 403033965Sjdp enum bfd_link_discard discard; 403133965Sjdp struct external_nlist *outsym; 403233965Sjdp bfd_size_type strtab_index; 403333965Sjdp register struct external_nlist *sym; 403433965Sjdp struct external_nlist *sym_end; 403533965Sjdp struct aout_link_hash_entry **sym_hash; 403633965Sjdp int *symbol_map; 403733965Sjdp boolean pass; 403833965Sjdp boolean skip_next; 403933965Sjdp 404033965Sjdp output_bfd = finfo->output_bfd; 404133965Sjdp sym_count = obj_aout_external_sym_count (input_bfd); 404233965Sjdp strings = obj_aout_external_strings (input_bfd); 404333965Sjdp strip = finfo->info->strip; 404433965Sjdp discard = finfo->info->discard; 404533965Sjdp outsym = finfo->output_syms; 404633965Sjdp 404733965Sjdp /* First write out a symbol for this object file, unless we are 404833965Sjdp discarding such symbols. */ 404933965Sjdp if (strip != strip_all 405033965Sjdp && (strip != strip_some 405133965Sjdp || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename, 405233965Sjdp false, false) != NULL) 405333965Sjdp && discard != discard_all) 405433965Sjdp { 405533965Sjdp bfd_h_put_8 (output_bfd, N_TEXT, outsym->e_type); 405633965Sjdp bfd_h_put_8 (output_bfd, 0, outsym->e_other); 405733965Sjdp bfd_h_put_16 (output_bfd, (bfd_vma) 0, outsym->e_desc); 405833965Sjdp strtab_index = add_to_stringtab (output_bfd, finfo->strtab, 405933965Sjdp input_bfd->filename, false); 406033965Sjdp if (strtab_index == (bfd_size_type) -1) 406133965Sjdp return false; 406233965Sjdp PUT_WORD (output_bfd, strtab_index, outsym->e_strx); 406333965Sjdp PUT_WORD (output_bfd, 406433965Sjdp (bfd_get_section_vma (output_bfd, 406533965Sjdp obj_textsec (input_bfd)->output_section) 406633965Sjdp + obj_textsec (input_bfd)->output_offset), 406733965Sjdp outsym->e_value); 406833965Sjdp ++obj_aout_external_sym_count (output_bfd); 406933965Sjdp ++outsym; 407033965Sjdp } 407133965Sjdp 407233965Sjdp pass = false; 407333965Sjdp skip_next = false; 407433965Sjdp sym = obj_aout_external_syms (input_bfd); 407533965Sjdp sym_end = sym + sym_count; 407633965Sjdp sym_hash = obj_aout_sym_hashes (input_bfd); 407733965Sjdp symbol_map = finfo->symbol_map; 407833965Sjdp memset (symbol_map, 0, sym_count * sizeof *symbol_map); 407933965Sjdp for (; sym < sym_end; sym++, sym_hash++, symbol_map++) 408033965Sjdp { 408133965Sjdp const char *name; 408233965Sjdp int type; 408333965Sjdp struct aout_link_hash_entry *h; 408433965Sjdp boolean skip; 408533965Sjdp asection *symsec; 408633965Sjdp bfd_vma val = 0; 408733965Sjdp boolean copy; 408833965Sjdp 408933965Sjdp /* We set *symbol_map to 0 above for all symbols. If it has 409033965Sjdp already been set to -1 for this symbol, it means that we are 409133965Sjdp discarding it because it appears in a duplicate header file. 409233965Sjdp See the N_BINCL code below. */ 409333965Sjdp if (*symbol_map == -1) 409433965Sjdp continue; 409533965Sjdp 409633965Sjdp /* Initialize *symbol_map to -1, which means that the symbol was 409733965Sjdp not copied into the output file. We will change it later if 409833965Sjdp we do copy the symbol over. */ 409933965Sjdp *symbol_map = -1; 410033965Sjdp 410133965Sjdp type = bfd_h_get_8 (input_bfd, sym->e_type); 410233965Sjdp name = strings + GET_WORD (input_bfd, sym->e_strx); 410333965Sjdp 410433965Sjdp h = NULL; 410533965Sjdp 410633965Sjdp if (pass) 410733965Sjdp { 410833965Sjdp /* Pass this symbol through. It is the target of an 410933965Sjdp indirect or warning symbol. */ 411033965Sjdp val = GET_WORD (input_bfd, sym->e_value); 411133965Sjdp pass = false; 411233965Sjdp } 411333965Sjdp else if (skip_next) 411433965Sjdp { 411533965Sjdp /* Skip this symbol, which is the target of an indirect 411633965Sjdp symbol that we have changed to no longer be an indirect 411733965Sjdp symbol. */ 411833965Sjdp skip_next = false; 411933965Sjdp continue; 412033965Sjdp } 412133965Sjdp else 412233965Sjdp { 412333965Sjdp struct aout_link_hash_entry *hresolve; 412433965Sjdp 412533965Sjdp /* We have saved the hash table entry for this symbol, if 412633965Sjdp there is one. Note that we could just look it up again 412733965Sjdp in the hash table, provided we first check that it is an 412833965Sjdp external symbol. */ 412933965Sjdp h = *sym_hash; 413033965Sjdp 413133965Sjdp /* Use the name from the hash table, in case the symbol was 413233965Sjdp wrapped. */ 413333965Sjdp if (h != NULL) 413433965Sjdp name = h->root.root.string; 413533965Sjdp 413633965Sjdp /* If this is an indirect or warning symbol, then change 413733965Sjdp hresolve to the base symbol. We also change *sym_hash so 413833965Sjdp that the relocation routines relocate against the real 413933965Sjdp symbol. */ 414033965Sjdp hresolve = h; 414133965Sjdp if (h != (struct aout_link_hash_entry *) NULL 414233965Sjdp && (h->root.type == bfd_link_hash_indirect 414333965Sjdp || h->root.type == bfd_link_hash_warning)) 414433965Sjdp { 414533965Sjdp hresolve = (struct aout_link_hash_entry *) h->root.u.i.link; 414633965Sjdp while (hresolve->root.type == bfd_link_hash_indirect 414733965Sjdp || hresolve->root.type == bfd_link_hash_warning) 414833965Sjdp hresolve = ((struct aout_link_hash_entry *) 414933965Sjdp hresolve->root.u.i.link); 415033965Sjdp *sym_hash = hresolve; 415133965Sjdp } 415233965Sjdp 415333965Sjdp /* If the symbol has already been written out, skip it. */ 415433965Sjdp if (h != (struct aout_link_hash_entry *) NULL 415533965Sjdp && h->root.type != bfd_link_hash_warning 415633965Sjdp && h->written) 415733965Sjdp { 415833965Sjdp if ((type & N_TYPE) == N_INDR 415933965Sjdp || type == N_WARNING) 416033965Sjdp skip_next = true; 416133965Sjdp *symbol_map = h->indx; 416233965Sjdp continue; 416333965Sjdp } 416433965Sjdp 416533965Sjdp /* See if we are stripping this symbol. */ 416633965Sjdp skip = false; 416733965Sjdp switch (strip) 416833965Sjdp { 416933965Sjdp case strip_none: 417033965Sjdp break; 417133965Sjdp case strip_debugger: 417233965Sjdp if ((type & N_STAB) != 0) 417333965Sjdp skip = true; 417433965Sjdp break; 417533965Sjdp case strip_some: 417633965Sjdp if (bfd_hash_lookup (finfo->info->keep_hash, name, false, false) 417733965Sjdp == NULL) 417833965Sjdp skip = true; 417933965Sjdp break; 418033965Sjdp case strip_all: 418133965Sjdp skip = true; 418233965Sjdp break; 418333965Sjdp } 418433965Sjdp if (skip) 418533965Sjdp { 418633965Sjdp if (h != (struct aout_link_hash_entry *) NULL) 418733965Sjdp h->written = true; 418833965Sjdp continue; 418933965Sjdp } 419033965Sjdp 419133965Sjdp /* Get the value of the symbol. */ 419233965Sjdp if ((type & N_TYPE) == N_TEXT 419333965Sjdp || type == N_WEAKT) 419433965Sjdp symsec = obj_textsec (input_bfd); 419533965Sjdp else if ((type & N_TYPE) == N_DATA 419633965Sjdp || type == N_WEAKD) 419733965Sjdp symsec = obj_datasec (input_bfd); 419833965Sjdp else if ((type & N_TYPE) == N_BSS 419933965Sjdp || type == N_WEAKB) 420033965Sjdp symsec = obj_bsssec (input_bfd); 420133965Sjdp else if ((type & N_TYPE) == N_ABS 420233965Sjdp || type == N_WEAKA) 420333965Sjdp symsec = bfd_abs_section_ptr; 420433965Sjdp else if (((type & N_TYPE) == N_INDR 420533965Sjdp && (hresolve == (struct aout_link_hash_entry *) NULL 420633965Sjdp || (hresolve->root.type != bfd_link_hash_defined 420733965Sjdp && hresolve->root.type != bfd_link_hash_defweak 420833965Sjdp && hresolve->root.type != bfd_link_hash_common))) 420933965Sjdp || type == N_WARNING) 421033965Sjdp { 421133965Sjdp /* Pass the next symbol through unchanged. The 421233965Sjdp condition above for indirect symbols is so that if 421333965Sjdp the indirect symbol was defined, we output it with 421433965Sjdp the correct definition so the debugger will 421533965Sjdp understand it. */ 421633965Sjdp pass = true; 421733965Sjdp val = GET_WORD (input_bfd, sym->e_value); 421833965Sjdp symsec = NULL; 421933965Sjdp } 422033965Sjdp else if ((type & N_STAB) != 0) 422133965Sjdp { 422233965Sjdp val = GET_WORD (input_bfd, sym->e_value); 422333965Sjdp symsec = NULL; 422433965Sjdp } 422533965Sjdp else 422633965Sjdp { 422733965Sjdp /* If we get here with an indirect symbol, it means that 422833965Sjdp we are outputting it with a real definition. In such 422933965Sjdp a case we do not want to output the next symbol, 423033965Sjdp which is the target of the indirection. */ 423133965Sjdp if ((type & N_TYPE) == N_INDR) 423233965Sjdp skip_next = true; 423333965Sjdp 423433965Sjdp symsec = NULL; 423533965Sjdp 423633965Sjdp /* We need to get the value from the hash table. We use 423733965Sjdp hresolve so that if we have defined an indirect 423833965Sjdp symbol we output the final definition. */ 423933965Sjdp if (h == (struct aout_link_hash_entry *) NULL) 424033965Sjdp { 424133965Sjdp switch (type & N_TYPE) 424233965Sjdp { 424333965Sjdp case N_SETT: 424433965Sjdp symsec = obj_textsec (input_bfd); 424533965Sjdp break; 424633965Sjdp case N_SETD: 424733965Sjdp symsec = obj_datasec (input_bfd); 424833965Sjdp break; 424933965Sjdp case N_SETB: 425033965Sjdp symsec = obj_bsssec (input_bfd); 425133965Sjdp break; 425233965Sjdp case N_SETA: 425333965Sjdp symsec = bfd_abs_section_ptr; 425433965Sjdp break; 425533965Sjdp default: 425633965Sjdp val = 0; 425733965Sjdp break; 425833965Sjdp } 425933965Sjdp } 426033965Sjdp else if (hresolve->root.type == bfd_link_hash_defined 426133965Sjdp || hresolve->root.type == bfd_link_hash_defweak) 426233965Sjdp { 426333965Sjdp asection *input_section; 426433965Sjdp asection *output_section; 426533965Sjdp 426633965Sjdp /* This case usually means a common symbol which was 426733965Sjdp turned into a defined symbol. */ 426833965Sjdp input_section = hresolve->root.u.def.section; 426933965Sjdp output_section = input_section->output_section; 427033965Sjdp BFD_ASSERT (bfd_is_abs_section (output_section) 427133965Sjdp || output_section->owner == output_bfd); 427233965Sjdp val = (hresolve->root.u.def.value 427333965Sjdp + bfd_get_section_vma (output_bfd, output_section) 427433965Sjdp + input_section->output_offset); 427533965Sjdp 427633965Sjdp /* Get the correct type based on the section. If 427733965Sjdp this is a constructed set, force it to be 427833965Sjdp globally visible. */ 427933965Sjdp if (type == N_SETT 428033965Sjdp || type == N_SETD 428133965Sjdp || type == N_SETB 428233965Sjdp || type == N_SETA) 428333965Sjdp type |= N_EXT; 428433965Sjdp 428533965Sjdp type &=~ N_TYPE; 428633965Sjdp 428733965Sjdp if (output_section == obj_textsec (output_bfd)) 428833965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 428933965Sjdp ? N_TEXT 429033965Sjdp : N_WEAKT); 429133965Sjdp else if (output_section == obj_datasec (output_bfd)) 429233965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 429333965Sjdp ? N_DATA 429433965Sjdp : N_WEAKD); 429533965Sjdp else if (output_section == obj_bsssec (output_bfd)) 429633965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 429733965Sjdp ? N_BSS 429833965Sjdp : N_WEAKB); 429933965Sjdp else 430033965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 430133965Sjdp ? N_ABS 430233965Sjdp : N_WEAKA); 430333965Sjdp } 430433965Sjdp else if (hresolve->root.type == bfd_link_hash_common) 430533965Sjdp val = hresolve->root.u.c.size; 430633965Sjdp else if (hresolve->root.type == bfd_link_hash_undefweak) 430733965Sjdp { 430833965Sjdp val = 0; 430933965Sjdp type = N_WEAKU; 431033965Sjdp } 431133965Sjdp else 431233965Sjdp val = 0; 431333965Sjdp } 431433965Sjdp if (symsec != (asection *) NULL) 431533965Sjdp val = (symsec->output_section->vma 431633965Sjdp + symsec->output_offset 431733965Sjdp + (GET_WORD (input_bfd, sym->e_value) 431833965Sjdp - symsec->vma)); 431933965Sjdp 432033965Sjdp /* If this is a global symbol set the written flag, and if 432133965Sjdp it is a local symbol see if we should discard it. */ 432233965Sjdp if (h != (struct aout_link_hash_entry *) NULL) 432333965Sjdp { 432433965Sjdp h->written = true; 432533965Sjdp h->indx = obj_aout_external_sym_count (output_bfd); 432633965Sjdp } 432733965Sjdp else if ((type & N_TYPE) != N_SETT 432833965Sjdp && (type & N_TYPE) != N_SETD 432933965Sjdp && (type & N_TYPE) != N_SETB 433033965Sjdp && (type & N_TYPE) != N_SETA) 433133965Sjdp { 433233965Sjdp switch (discard) 433333965Sjdp { 433433965Sjdp case discard_none: 433533965Sjdp break; 433633965Sjdp case discard_l: 433733965Sjdp if ((type & N_STAB) == 0 433833965Sjdp && bfd_is_local_label_name (input_bfd, name)) 433933965Sjdp skip = true; 434033965Sjdp break; 434133965Sjdp case discard_all: 434233965Sjdp skip = true; 434333965Sjdp break; 434433965Sjdp } 434533965Sjdp if (skip) 434633965Sjdp { 434733965Sjdp pass = false; 434833965Sjdp continue; 434933965Sjdp } 435033965Sjdp } 435133965Sjdp 435233965Sjdp /* An N_BINCL symbol indicates the start of the stabs 435333965Sjdp entries for a header file. We need to scan ahead to the 435433965Sjdp next N_EINCL symbol, ignoring nesting, adding up all the 435533965Sjdp characters in the symbol names, not including the file 435633965Sjdp numbers in types (the first number after an open 435733965Sjdp parenthesis). */ 435833965Sjdp if (type == N_BINCL) 435933965Sjdp { 436033965Sjdp struct external_nlist *incl_sym; 436133965Sjdp int nest; 436233965Sjdp struct aout_link_includes_entry *incl_entry; 436333965Sjdp struct aout_link_includes_totals *t; 436433965Sjdp 436533965Sjdp val = 0; 436633965Sjdp nest = 0; 436733965Sjdp for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++) 436833965Sjdp { 436933965Sjdp int incl_type; 437033965Sjdp 437133965Sjdp incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type); 437233965Sjdp if (incl_type == N_EINCL) 437333965Sjdp { 437433965Sjdp if (nest == 0) 437533965Sjdp break; 437633965Sjdp --nest; 437733965Sjdp } 437833965Sjdp else if (incl_type == N_BINCL) 437933965Sjdp ++nest; 438033965Sjdp else if (nest == 0) 438133965Sjdp { 438233965Sjdp const char *s; 438333965Sjdp 438433965Sjdp s = strings + GET_WORD (input_bfd, incl_sym->e_strx); 438533965Sjdp for (; *s != '\0'; s++) 438633965Sjdp { 438733965Sjdp val += *s; 438833965Sjdp if (*s == '(') 438933965Sjdp { 439033965Sjdp /* Skip the file number. */ 439133965Sjdp ++s; 439233965Sjdp while (isdigit ((unsigned char) *s)) 439333965Sjdp ++s; 439433965Sjdp --s; 439533965Sjdp } 439633965Sjdp } 439733965Sjdp } 439833965Sjdp } 439933965Sjdp 440033965Sjdp /* If we have already included a header file with the 440133965Sjdp same value, then replace this one with an N_EXCL 440233965Sjdp symbol. */ 440333965Sjdp copy = ! finfo->info->keep_memory; 440433965Sjdp incl_entry = aout_link_includes_lookup (&finfo->includes, 440533965Sjdp name, true, copy); 440633965Sjdp if (incl_entry == NULL) 440733965Sjdp return false; 440833965Sjdp for (t = incl_entry->totals; t != NULL; t = t->next) 440933965Sjdp if (t->total == val) 441033965Sjdp break; 441133965Sjdp if (t == NULL) 441233965Sjdp { 441333965Sjdp /* This is the first time we have seen this header 441433965Sjdp file with this set of stabs strings. */ 441533965Sjdp t = ((struct aout_link_includes_totals *) 441633965Sjdp bfd_hash_allocate (&finfo->includes.root, 441733965Sjdp sizeof *t)); 441833965Sjdp if (t == NULL) 441933965Sjdp return false; 442033965Sjdp t->total = val; 442133965Sjdp t->next = incl_entry->totals; 442233965Sjdp incl_entry->totals = t; 442333965Sjdp } 442433965Sjdp else 442533965Sjdp { 442633965Sjdp int *incl_map; 442733965Sjdp 442833965Sjdp /* This is a duplicate header file. We must change 442933965Sjdp it to be an N_EXCL entry, and mark all the 443033965Sjdp included symbols to prevent outputting them. */ 443133965Sjdp type = N_EXCL; 443233965Sjdp 443333965Sjdp nest = 0; 443433965Sjdp for (incl_sym = sym + 1, incl_map = symbol_map + 1; 443533965Sjdp incl_sym < sym_end; 443633965Sjdp incl_sym++, incl_map++) 443733965Sjdp { 443833965Sjdp int incl_type; 443933965Sjdp 444033965Sjdp incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type); 444133965Sjdp if (incl_type == N_EINCL) 444233965Sjdp { 444333965Sjdp if (nest == 0) 444433965Sjdp { 444533965Sjdp *incl_map = -1; 444633965Sjdp break; 444733965Sjdp } 444833965Sjdp --nest; 444933965Sjdp } 445033965Sjdp else if (incl_type == N_BINCL) 445133965Sjdp ++nest; 445233965Sjdp else if (nest == 0) 445333965Sjdp *incl_map = -1; 445433965Sjdp } 445533965Sjdp } 445633965Sjdp } 445733965Sjdp } 445833965Sjdp 445933965Sjdp /* Copy this symbol into the list of symbols we are going to 446033965Sjdp write out. */ 446133965Sjdp bfd_h_put_8 (output_bfd, type, outsym->e_type); 446233965Sjdp bfd_h_put_8 (output_bfd, bfd_h_get_8 (input_bfd, sym->e_other), 446333965Sjdp outsym->e_other); 446433965Sjdp bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc), 446533965Sjdp outsym->e_desc); 446633965Sjdp copy = false; 446733965Sjdp if (! finfo->info->keep_memory) 446833965Sjdp { 446933965Sjdp /* name points into a string table which we are going to 447033965Sjdp free. If there is a hash table entry, use that string. 447133965Sjdp Otherwise, copy name into memory. */ 447233965Sjdp if (h != (struct aout_link_hash_entry *) NULL) 447333965Sjdp name = h->root.root.string; 447433965Sjdp else 447533965Sjdp copy = true; 447633965Sjdp } 447733965Sjdp strtab_index = add_to_stringtab (output_bfd, finfo->strtab, 447833965Sjdp name, copy); 447933965Sjdp if (strtab_index == (bfd_size_type) -1) 448033965Sjdp return false; 448133965Sjdp PUT_WORD (output_bfd, strtab_index, outsym->e_strx); 448233965Sjdp PUT_WORD (output_bfd, val, outsym->e_value); 448333965Sjdp *symbol_map = obj_aout_external_sym_count (output_bfd); 448433965Sjdp ++obj_aout_external_sym_count (output_bfd); 448533965Sjdp ++outsym; 448633965Sjdp } 448733965Sjdp 448833965Sjdp /* Write out the output symbols we have just constructed. */ 448933965Sjdp if (outsym > finfo->output_syms) 449033965Sjdp { 449133965Sjdp bfd_size_type outsym_count; 449233965Sjdp 449333965Sjdp if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0) 449433965Sjdp return false; 449533965Sjdp outsym_count = outsym - finfo->output_syms; 449633965Sjdp if (bfd_write ((PTR) finfo->output_syms, 449733965Sjdp (bfd_size_type) EXTERNAL_NLIST_SIZE, 449833965Sjdp (bfd_size_type) outsym_count, output_bfd) 449933965Sjdp != outsym_count * EXTERNAL_NLIST_SIZE) 450033965Sjdp return false; 450133965Sjdp finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE; 450233965Sjdp } 450333965Sjdp 450433965Sjdp return true; 450533965Sjdp} 450633965Sjdp 450733965Sjdp/* Write out a symbol that was not associated with an a.out input 450833965Sjdp object. */ 450933965Sjdp 451033965Sjdpstatic boolean 451133965Sjdpaout_link_write_other_symbol (h, data) 451233965Sjdp struct aout_link_hash_entry *h; 451333965Sjdp PTR data; 451433965Sjdp{ 451533965Sjdp struct aout_final_link_info *finfo = (struct aout_final_link_info *) data; 451633965Sjdp bfd *output_bfd; 451733965Sjdp int type; 451833965Sjdp bfd_vma val; 451933965Sjdp struct external_nlist outsym; 452033965Sjdp bfd_size_type indx; 452133965Sjdp 452233965Sjdp output_bfd = finfo->output_bfd; 452333965Sjdp 452433965Sjdp if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL) 452533965Sjdp { 452633965Sjdp if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol) 452733965Sjdp (output_bfd, finfo->info, h))) 452833965Sjdp { 452933965Sjdp /* FIXME: No way to handle errors. */ 453033965Sjdp abort (); 453133965Sjdp } 453233965Sjdp } 453333965Sjdp 453433965Sjdp if (h->written) 453533965Sjdp return true; 453633965Sjdp 453733965Sjdp h->written = true; 453833965Sjdp 453933965Sjdp /* An indx of -2 means the symbol must be written. */ 454033965Sjdp if (h->indx != -2 454133965Sjdp && (finfo->info->strip == strip_all 454233965Sjdp || (finfo->info->strip == strip_some 454333965Sjdp && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string, 454433965Sjdp false, false) == NULL))) 454533965Sjdp return true; 454633965Sjdp 454733965Sjdp switch (h->root.type) 454833965Sjdp { 454933965Sjdp default: 455033965Sjdp abort (); 455133965Sjdp /* Avoid variable not initialized warnings. */ 455233965Sjdp return true; 455333965Sjdp case bfd_link_hash_new: 455433965Sjdp /* This can happen for set symbols when sets are not being 455533965Sjdp built. */ 455633965Sjdp return true; 455733965Sjdp case bfd_link_hash_undefined: 455833965Sjdp type = N_UNDF | N_EXT; 455933965Sjdp val = 0; 456033965Sjdp break; 456133965Sjdp case bfd_link_hash_defined: 456233965Sjdp case bfd_link_hash_defweak: 456333965Sjdp { 456433965Sjdp asection *sec; 456533965Sjdp 456633965Sjdp sec = h->root.u.def.section->output_section; 456733965Sjdp BFD_ASSERT (bfd_is_abs_section (sec) 456833965Sjdp || sec->owner == output_bfd); 456933965Sjdp if (sec == obj_textsec (output_bfd)) 457033965Sjdp type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT; 457133965Sjdp else if (sec == obj_datasec (output_bfd)) 457233965Sjdp type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD; 457333965Sjdp else if (sec == obj_bsssec (output_bfd)) 457433965Sjdp type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB; 457533965Sjdp else 457633965Sjdp type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA; 457733965Sjdp type |= N_EXT; 457833965Sjdp val = (h->root.u.def.value 457933965Sjdp + sec->vma 458033965Sjdp + h->root.u.def.section->output_offset); 458133965Sjdp } 458233965Sjdp break; 458333965Sjdp case bfd_link_hash_common: 458433965Sjdp type = N_UNDF | N_EXT; 458533965Sjdp val = h->root.u.c.size; 458633965Sjdp break; 458733965Sjdp case bfd_link_hash_undefweak: 458833965Sjdp type = N_WEAKU; 458933965Sjdp val = 0; 459033965Sjdp case bfd_link_hash_indirect: 459133965Sjdp case bfd_link_hash_warning: 459233965Sjdp /* FIXME: Ignore these for now. The circumstances under which 459333965Sjdp they should be written out are not clear to me. */ 459433965Sjdp return true; 459533965Sjdp } 459633965Sjdp 459733965Sjdp bfd_h_put_8 (output_bfd, type, outsym.e_type); 459833965Sjdp bfd_h_put_8 (output_bfd, 0, outsym.e_other); 459933965Sjdp bfd_h_put_16 (output_bfd, 0, outsym.e_desc); 460033965Sjdp indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string, 460133965Sjdp false); 460233965Sjdp if (indx == (bfd_size_type) -1) 460333965Sjdp { 460433965Sjdp /* FIXME: No way to handle errors. */ 460533965Sjdp abort (); 460633965Sjdp } 460733965Sjdp PUT_WORD (output_bfd, indx, outsym.e_strx); 460833965Sjdp PUT_WORD (output_bfd, val, outsym.e_value); 460933965Sjdp 461033965Sjdp if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0 461133965Sjdp || bfd_write ((PTR) &outsym, (bfd_size_type) EXTERNAL_NLIST_SIZE, 461233965Sjdp (bfd_size_type) 1, output_bfd) != EXTERNAL_NLIST_SIZE) 461333965Sjdp { 461433965Sjdp /* FIXME: No way to handle errors. */ 461533965Sjdp abort (); 461633965Sjdp } 461733965Sjdp 461833965Sjdp finfo->symoff += EXTERNAL_NLIST_SIZE; 461933965Sjdp h->indx = obj_aout_external_sym_count (output_bfd); 462033965Sjdp ++obj_aout_external_sym_count (output_bfd); 462133965Sjdp 462233965Sjdp return true; 462333965Sjdp} 462433965Sjdp 462533965Sjdp/* Link an a.out section into the output file. */ 462633965Sjdp 462733965Sjdpstatic boolean 462833965Sjdpaout_link_input_section (finfo, input_bfd, input_section, reloff_ptr, 462933965Sjdp rel_size) 463033965Sjdp struct aout_final_link_info *finfo; 463133965Sjdp bfd *input_bfd; 463233965Sjdp asection *input_section; 463333965Sjdp file_ptr *reloff_ptr; 463433965Sjdp bfd_size_type rel_size; 463533965Sjdp{ 463633965Sjdp bfd_size_type input_size; 463733965Sjdp PTR relocs; 463833965Sjdp 463933965Sjdp /* Get the section contents. */ 464033965Sjdp input_size = bfd_section_size (input_bfd, input_section); 464133965Sjdp if (! bfd_get_section_contents (input_bfd, input_section, 464233965Sjdp (PTR) finfo->contents, 464333965Sjdp (file_ptr) 0, input_size)) 464433965Sjdp return false; 464533965Sjdp 464633965Sjdp /* Read in the relocs if we haven't already done it. */ 464733965Sjdp if (aout_section_data (input_section) != NULL 464833965Sjdp && aout_section_data (input_section)->relocs != NULL) 464933965Sjdp relocs = aout_section_data (input_section)->relocs; 465033965Sjdp else 465133965Sjdp { 465233965Sjdp relocs = finfo->relocs; 465333965Sjdp if (rel_size > 0) 465433965Sjdp { 465533965Sjdp if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 465633965Sjdp || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size) 465733965Sjdp return false; 465833965Sjdp } 465933965Sjdp } 466033965Sjdp 466133965Sjdp /* Relocate the section contents. */ 466233965Sjdp if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) 466333965Sjdp { 466433965Sjdp if (! aout_link_input_section_std (finfo, input_bfd, input_section, 466533965Sjdp (struct reloc_std_external *) relocs, 466633965Sjdp rel_size, finfo->contents)) 466733965Sjdp return false; 466833965Sjdp } 466933965Sjdp else 467033965Sjdp { 467133965Sjdp if (! aout_link_input_section_ext (finfo, input_bfd, input_section, 467233965Sjdp (struct reloc_ext_external *) relocs, 467333965Sjdp rel_size, finfo->contents)) 467433965Sjdp return false; 467533965Sjdp } 467633965Sjdp 467733965Sjdp /* Write out the section contents. */ 467833965Sjdp if (! bfd_set_section_contents (finfo->output_bfd, 467933965Sjdp input_section->output_section, 468033965Sjdp (PTR) finfo->contents, 468133965Sjdp input_section->output_offset, 468233965Sjdp input_size)) 468333965Sjdp return false; 468433965Sjdp 468533965Sjdp /* If we are producing relocateable output, the relocs were 468633965Sjdp modified, and we now write them out. */ 468733965Sjdp if (finfo->info->relocateable && rel_size > 0) 468833965Sjdp { 468933965Sjdp if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0) 469033965Sjdp return false; 469133965Sjdp if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd) 469233965Sjdp != rel_size) 469333965Sjdp return false; 469433965Sjdp *reloff_ptr += rel_size; 469533965Sjdp 469633965Sjdp /* Assert that the relocs have not run into the symbols, and 469733965Sjdp that if these are the text relocs they have not run into the 469833965Sjdp data relocs. */ 469933965Sjdp BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) 470033965Sjdp && (reloff_ptr != &finfo->treloff 470133965Sjdp || (*reloff_ptr 470233965Sjdp <= obj_datasec (finfo->output_bfd)->rel_filepos))); 470333965Sjdp } 470433965Sjdp 470533965Sjdp return true; 470633965Sjdp} 470733965Sjdp 470833965Sjdp/* Get the section corresponding to a reloc index. */ 470933965Sjdp 471033965Sjdpstatic INLINE asection * 471133965Sjdpaout_reloc_index_to_section (abfd, indx) 471233965Sjdp bfd *abfd; 471333965Sjdp int indx; 471433965Sjdp{ 471533965Sjdp switch (indx & N_TYPE) 471633965Sjdp { 471733965Sjdp case N_TEXT: 471833965Sjdp return obj_textsec (abfd); 471933965Sjdp case N_DATA: 472033965Sjdp return obj_datasec (abfd); 472133965Sjdp case N_BSS: 472233965Sjdp return obj_bsssec (abfd); 472333965Sjdp case N_ABS: 472433965Sjdp case N_UNDF: 472533965Sjdp return bfd_abs_section_ptr; 472633965Sjdp default: 472733965Sjdp abort (); 472833965Sjdp } 472960484Sobrien /*NOTREACHED*/ 473060484Sobrien return NULL; 473133965Sjdp} 473233965Sjdp 473333965Sjdp/* Relocate an a.out section using standard a.out relocs. */ 473433965Sjdp 473533965Sjdpstatic boolean 473633965Sjdpaout_link_input_section_std (finfo, input_bfd, input_section, relocs, 473733965Sjdp rel_size, contents) 473833965Sjdp struct aout_final_link_info *finfo; 473933965Sjdp bfd *input_bfd; 474033965Sjdp asection *input_section; 474133965Sjdp struct reloc_std_external *relocs; 474233965Sjdp bfd_size_type rel_size; 474333965Sjdp bfd_byte *contents; 474433965Sjdp{ 474533965Sjdp boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, 474633965Sjdp bfd *, asection *, 474733965Sjdp struct aout_link_hash_entry *, 474833965Sjdp PTR, bfd_byte *, boolean *, 474933965Sjdp bfd_vma *)); 475033965Sjdp bfd *output_bfd; 475133965Sjdp boolean relocateable; 475233965Sjdp struct external_nlist *syms; 475333965Sjdp char *strings; 475433965Sjdp struct aout_link_hash_entry **sym_hashes; 475533965Sjdp int *symbol_map; 475633965Sjdp bfd_size_type reloc_count; 475733965Sjdp register struct reloc_std_external *rel; 475833965Sjdp struct reloc_std_external *rel_end; 475933965Sjdp 476033965Sjdp output_bfd = finfo->output_bfd; 476133965Sjdp check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; 476233965Sjdp 476333965Sjdp BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE); 476433965Sjdp BFD_ASSERT (input_bfd->xvec->header_byteorder 476533965Sjdp == output_bfd->xvec->header_byteorder); 476633965Sjdp 476733965Sjdp relocateable = finfo->info->relocateable; 476833965Sjdp syms = obj_aout_external_syms (input_bfd); 476933965Sjdp strings = obj_aout_external_strings (input_bfd); 477033965Sjdp sym_hashes = obj_aout_sym_hashes (input_bfd); 477133965Sjdp symbol_map = finfo->symbol_map; 477233965Sjdp 477333965Sjdp reloc_count = rel_size / RELOC_STD_SIZE; 477433965Sjdp rel = relocs; 477533965Sjdp rel_end = rel + reloc_count; 477633965Sjdp for (; rel < rel_end; rel++) 477733965Sjdp { 477833965Sjdp bfd_vma r_addr; 477933965Sjdp int r_index; 478033965Sjdp int r_extern; 478133965Sjdp int r_pcrel; 478233965Sjdp int r_baserel = 0; 478333965Sjdp reloc_howto_type *howto; 478433965Sjdp struct aout_link_hash_entry *h = NULL; 478533965Sjdp bfd_vma relocation; 478633965Sjdp bfd_reloc_status_type r; 478733965Sjdp 478833965Sjdp r_addr = GET_SWORD (input_bfd, rel->r_address); 478933965Sjdp 479033965Sjdp#ifdef MY_reloc_howto 479133965Sjdp howto = MY_reloc_howto(input_bfd, rel, r_index, r_extern, r_pcrel); 479233965Sjdp#else 479333965Sjdp { 479433965Sjdp int r_jmptable; 479533965Sjdp int r_relative; 479633965Sjdp int r_length; 479733965Sjdp unsigned int howto_idx; 479833965Sjdp 479933965Sjdp if (bfd_header_big_endian (input_bfd)) 480033965Sjdp { 480133965Sjdp r_index = ((rel->r_index[0] << 16) 480233965Sjdp | (rel->r_index[1] << 8) 480333965Sjdp | rel->r_index[2]); 480433965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); 480533965Sjdp r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 480633965Sjdp r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 480733965Sjdp r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 480833965Sjdp r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); 480933965Sjdp r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) 481033965Sjdp >> RELOC_STD_BITS_LENGTH_SH_BIG); 481133965Sjdp } 481233965Sjdp else 481333965Sjdp { 481433965Sjdp r_index = ((rel->r_index[2] << 16) 481533965Sjdp | (rel->r_index[1] << 8) 481633965Sjdp | rel->r_index[0]); 481733965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); 481833965Sjdp r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 481933965Sjdp r_baserel = (0 != (rel->r_type[0] 482033965Sjdp & RELOC_STD_BITS_BASEREL_LITTLE)); 482133965Sjdp r_jmptable= (0 != (rel->r_type[0] 482233965Sjdp & RELOC_STD_BITS_JMPTABLE_LITTLE)); 482333965Sjdp r_relative= (0 != (rel->r_type[0] 482433965Sjdp & RELOC_STD_BITS_RELATIVE_LITTLE)); 482533965Sjdp r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) 482633965Sjdp >> RELOC_STD_BITS_LENGTH_SH_LITTLE); 482733965Sjdp } 482833965Sjdp 482933965Sjdp howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel 483033965Sjdp + 16 * r_jmptable + 32 * r_relative); 483133965Sjdp BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); 483233965Sjdp howto = howto_table_std + howto_idx; 483333965Sjdp } 483433965Sjdp#endif 483533965Sjdp 483633965Sjdp if (relocateable) 483733965Sjdp { 483833965Sjdp /* We are generating a relocateable output file, and must 483933965Sjdp modify the reloc accordingly. */ 484033965Sjdp if (r_extern) 484133965Sjdp { 484233965Sjdp /* If we know the symbol this relocation is against, 484333965Sjdp convert it into a relocation against a section. This 484433965Sjdp is what the native linker does. */ 484533965Sjdp h = sym_hashes[r_index]; 484633965Sjdp if (h != (struct aout_link_hash_entry *) NULL 484733965Sjdp && (h->root.type == bfd_link_hash_defined 484833965Sjdp || h->root.type == bfd_link_hash_defweak)) 484933965Sjdp { 485033965Sjdp asection *output_section; 485133965Sjdp 485233965Sjdp /* Change the r_extern value. */ 485333965Sjdp if (bfd_header_big_endian (output_bfd)) 485433965Sjdp rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; 485533965Sjdp else 485633965Sjdp rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; 485733965Sjdp 485833965Sjdp /* Compute a new r_index. */ 485933965Sjdp output_section = h->root.u.def.section->output_section; 486033965Sjdp if (output_section == obj_textsec (output_bfd)) 486133965Sjdp r_index = N_TEXT; 486233965Sjdp else if (output_section == obj_datasec (output_bfd)) 486333965Sjdp r_index = N_DATA; 486433965Sjdp else if (output_section == obj_bsssec (output_bfd)) 486533965Sjdp r_index = N_BSS; 486633965Sjdp else 486733965Sjdp r_index = N_ABS; 486833965Sjdp 486933965Sjdp /* Add the symbol value and the section VMA to the 487033965Sjdp addend stored in the contents. */ 487133965Sjdp relocation = (h->root.u.def.value 487233965Sjdp + output_section->vma 487333965Sjdp + h->root.u.def.section->output_offset); 487433965Sjdp } 487533965Sjdp else 487633965Sjdp { 487733965Sjdp /* We must change r_index according to the symbol 487833965Sjdp map. */ 487933965Sjdp r_index = symbol_map[r_index]; 488033965Sjdp 488133965Sjdp if (r_index == -1) 488233965Sjdp { 488333965Sjdp if (h != NULL) 488433965Sjdp { 488533965Sjdp /* We decided to strip this symbol, but it 488633965Sjdp turns out that we can't. Note that we 488733965Sjdp lose the other and desc information here. 488833965Sjdp I don't think that will ever matter for a 488933965Sjdp global symbol. */ 489033965Sjdp if (h->indx < 0) 489133965Sjdp { 489233965Sjdp h->indx = -2; 489333965Sjdp h->written = false; 489433965Sjdp if (! aout_link_write_other_symbol (h, 489533965Sjdp (PTR) finfo)) 489633965Sjdp return false; 489733965Sjdp } 489833965Sjdp r_index = h->indx; 489933965Sjdp } 490033965Sjdp else 490133965Sjdp { 490233965Sjdp const char *name; 490333965Sjdp 490433965Sjdp name = strings + GET_WORD (input_bfd, 490533965Sjdp syms[r_index].e_strx); 490633965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 490733965Sjdp (finfo->info, name, input_bfd, input_section, 490833965Sjdp r_addr))) 490933965Sjdp return false; 491033965Sjdp r_index = 0; 491133965Sjdp } 491233965Sjdp } 491333965Sjdp 491433965Sjdp relocation = 0; 491533965Sjdp } 491633965Sjdp 491733965Sjdp /* Write out the new r_index value. */ 491833965Sjdp if (bfd_header_big_endian (output_bfd)) 491933965Sjdp { 492033965Sjdp rel->r_index[0] = r_index >> 16; 492133965Sjdp rel->r_index[1] = r_index >> 8; 492233965Sjdp rel->r_index[2] = r_index; 492333965Sjdp } 492433965Sjdp else 492533965Sjdp { 492633965Sjdp rel->r_index[2] = r_index >> 16; 492733965Sjdp rel->r_index[1] = r_index >> 8; 492833965Sjdp rel->r_index[0] = r_index; 492933965Sjdp } 493033965Sjdp } 493133965Sjdp else 493233965Sjdp { 493333965Sjdp asection *section; 493433965Sjdp 493533965Sjdp /* This is a relocation against a section. We must 493633965Sjdp adjust by the amount that the section moved. */ 493733965Sjdp section = aout_reloc_index_to_section (input_bfd, r_index); 493833965Sjdp relocation = (section->output_section->vma 493933965Sjdp + section->output_offset 494033965Sjdp - section->vma); 494133965Sjdp } 494233965Sjdp 494333965Sjdp /* Change the address of the relocation. */ 494433965Sjdp PUT_WORD (output_bfd, 494533965Sjdp r_addr + input_section->output_offset, 494633965Sjdp rel->r_address); 494733965Sjdp 494833965Sjdp /* Adjust a PC relative relocation by removing the reference 494933965Sjdp to the original address in the section and including the 495033965Sjdp reference to the new address. */ 495133965Sjdp if (r_pcrel) 495233965Sjdp relocation -= (input_section->output_section->vma 495333965Sjdp + input_section->output_offset 495433965Sjdp - input_section->vma); 495533965Sjdp 495633965Sjdp#ifdef MY_relocatable_reloc 495733965Sjdp MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr); 495833965Sjdp#endif 495933965Sjdp 496033965Sjdp if (relocation == 0) 496133965Sjdp r = bfd_reloc_ok; 496233965Sjdp else 496333965Sjdp r = MY_relocate_contents (howto, 496433965Sjdp input_bfd, relocation, 496533965Sjdp contents + r_addr); 496633965Sjdp } 496733965Sjdp else 496833965Sjdp { 496933965Sjdp boolean hundef; 497033965Sjdp 497133965Sjdp /* We are generating an executable, and must do a full 497233965Sjdp relocation. */ 497333965Sjdp hundef = false; 497460484Sobrien 497533965Sjdp if (r_extern) 497633965Sjdp { 497733965Sjdp h = sym_hashes[r_index]; 497833965Sjdp 497933965Sjdp if (h != (struct aout_link_hash_entry *) NULL 498033965Sjdp && (h->root.type == bfd_link_hash_defined 498133965Sjdp || h->root.type == bfd_link_hash_defweak)) 498233965Sjdp { 498333965Sjdp relocation = (h->root.u.def.value 498433965Sjdp + h->root.u.def.section->output_section->vma 498533965Sjdp + h->root.u.def.section->output_offset); 498633965Sjdp } 498733965Sjdp else if (h != (struct aout_link_hash_entry *) NULL 498833965Sjdp && h->root.type == bfd_link_hash_undefweak) 498933965Sjdp relocation = 0; 499033965Sjdp else 499133965Sjdp { 499233965Sjdp hundef = true; 499333965Sjdp relocation = 0; 499433965Sjdp } 499533965Sjdp } 499633965Sjdp else 499733965Sjdp { 499833965Sjdp asection *section; 499933965Sjdp 500033965Sjdp section = aout_reloc_index_to_section (input_bfd, r_index); 500133965Sjdp relocation = (section->output_section->vma 500233965Sjdp + section->output_offset 500333965Sjdp - section->vma); 500433965Sjdp if (r_pcrel) 500533965Sjdp relocation += input_section->vma; 500633965Sjdp } 500733965Sjdp 500833965Sjdp if (check_dynamic_reloc != NULL) 500933965Sjdp { 501033965Sjdp boolean skip; 501133965Sjdp 501233965Sjdp if (! ((*check_dynamic_reloc) 501333965Sjdp (finfo->info, input_bfd, input_section, h, 501433965Sjdp (PTR) rel, contents, &skip, &relocation))) 501533965Sjdp return false; 501633965Sjdp if (skip) 501733965Sjdp continue; 501833965Sjdp } 501933965Sjdp 502033965Sjdp /* Now warn if a global symbol is undefined. We could not 502133965Sjdp do this earlier, because check_dynamic_reloc might want 502233965Sjdp to skip this reloc. */ 502333965Sjdp if (hundef && ! finfo->info->shared && ! r_baserel) 502433965Sjdp { 502533965Sjdp const char *name; 502633965Sjdp 502733965Sjdp if (h != NULL) 502833965Sjdp name = h->root.root.string; 502933965Sjdp else 503033965Sjdp name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); 503133965Sjdp if (! ((*finfo->info->callbacks->undefined_symbol) 503260484Sobrien (finfo->info, name, input_bfd, input_section, 503360484Sobrien r_addr, true))) 503433965Sjdp return false; 503533965Sjdp } 503633965Sjdp 503733965Sjdp r = MY_final_link_relocate (howto, 503833965Sjdp input_bfd, input_section, 503933965Sjdp contents, r_addr, relocation, 504033965Sjdp (bfd_vma) 0); 504133965Sjdp } 504233965Sjdp 504333965Sjdp if (r != bfd_reloc_ok) 504433965Sjdp { 504533965Sjdp switch (r) 504633965Sjdp { 504733965Sjdp default: 504833965Sjdp case bfd_reloc_outofrange: 504933965Sjdp abort (); 505033965Sjdp case bfd_reloc_overflow: 505133965Sjdp { 505233965Sjdp const char *name; 505333965Sjdp 505433965Sjdp if (h != NULL) 505533965Sjdp name = h->root.root.string; 505633965Sjdp else if (r_extern) 505733965Sjdp name = strings + GET_WORD (input_bfd, 505833965Sjdp syms[r_index].e_strx); 505933965Sjdp else 506033965Sjdp { 506133965Sjdp asection *s; 506233965Sjdp 506333965Sjdp s = aout_reloc_index_to_section (input_bfd, r_index); 506433965Sjdp name = bfd_section_name (input_bfd, s); 506533965Sjdp } 506633965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 506733965Sjdp (finfo->info, name, howto->name, 506833965Sjdp (bfd_vma) 0, input_bfd, input_section, r_addr))) 506933965Sjdp return false; 507033965Sjdp } 507133965Sjdp break; 507233965Sjdp } 507333965Sjdp } 507433965Sjdp } 507533965Sjdp 507633965Sjdp return true; 507733965Sjdp} 507833965Sjdp 507933965Sjdp/* Relocate an a.out section using extended a.out relocs. */ 508033965Sjdp 508133965Sjdpstatic boolean 508233965Sjdpaout_link_input_section_ext (finfo, input_bfd, input_section, relocs, 508333965Sjdp rel_size, contents) 508433965Sjdp struct aout_final_link_info *finfo; 508533965Sjdp bfd *input_bfd; 508633965Sjdp asection *input_section; 508733965Sjdp struct reloc_ext_external *relocs; 508833965Sjdp bfd_size_type rel_size; 508933965Sjdp bfd_byte *contents; 509033965Sjdp{ 509133965Sjdp boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, 509233965Sjdp bfd *, asection *, 509333965Sjdp struct aout_link_hash_entry *, 509433965Sjdp PTR, bfd_byte *, boolean *, 509533965Sjdp bfd_vma *)); 509633965Sjdp bfd *output_bfd; 509733965Sjdp boolean relocateable; 509833965Sjdp struct external_nlist *syms; 509933965Sjdp char *strings; 510033965Sjdp struct aout_link_hash_entry **sym_hashes; 510133965Sjdp int *symbol_map; 510233965Sjdp bfd_size_type reloc_count; 510333965Sjdp register struct reloc_ext_external *rel; 510433965Sjdp struct reloc_ext_external *rel_end; 510533965Sjdp 510633965Sjdp output_bfd = finfo->output_bfd; 510733965Sjdp check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; 510833965Sjdp 510933965Sjdp BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE); 511033965Sjdp BFD_ASSERT (input_bfd->xvec->header_byteorder 511133965Sjdp == output_bfd->xvec->header_byteorder); 511233965Sjdp 511333965Sjdp relocateable = finfo->info->relocateable; 511433965Sjdp syms = obj_aout_external_syms (input_bfd); 511533965Sjdp strings = obj_aout_external_strings (input_bfd); 511633965Sjdp sym_hashes = obj_aout_sym_hashes (input_bfd); 511733965Sjdp symbol_map = finfo->symbol_map; 511833965Sjdp 511933965Sjdp reloc_count = rel_size / RELOC_EXT_SIZE; 512033965Sjdp rel = relocs; 512133965Sjdp rel_end = rel + reloc_count; 512233965Sjdp for (; rel < rel_end; rel++) 512333965Sjdp { 512433965Sjdp bfd_vma r_addr; 512533965Sjdp int r_index; 512633965Sjdp int r_extern; 512733965Sjdp unsigned int r_type; 512833965Sjdp bfd_vma r_addend; 512933965Sjdp struct aout_link_hash_entry *h = NULL; 513033965Sjdp asection *r_section = NULL; 513133965Sjdp bfd_vma relocation; 513233965Sjdp 513333965Sjdp r_addr = GET_SWORD (input_bfd, rel->r_address); 513433965Sjdp 513533965Sjdp if (bfd_header_big_endian (input_bfd)) 513633965Sjdp { 513733965Sjdp r_index = ((rel->r_index[0] << 16) 513833965Sjdp | (rel->r_index[1] << 8) 513933965Sjdp | rel->r_index[2]); 514033965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 514133965Sjdp r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 514233965Sjdp >> RELOC_EXT_BITS_TYPE_SH_BIG); 514333965Sjdp } 514433965Sjdp else 514533965Sjdp { 514633965Sjdp r_index = ((rel->r_index[2] << 16) 514733965Sjdp | (rel->r_index[1] << 8) 514833965Sjdp | rel->r_index[0]); 514933965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 515033965Sjdp r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 515133965Sjdp >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 515233965Sjdp } 515333965Sjdp 515433965Sjdp r_addend = GET_SWORD (input_bfd, rel->r_addend); 515533965Sjdp 515633965Sjdp BFD_ASSERT (r_type < TABLE_SIZE (howto_table_ext)); 515733965Sjdp 515833965Sjdp if (relocateable) 515933965Sjdp { 516033965Sjdp /* We are generating a relocateable output file, and must 516133965Sjdp modify the reloc accordingly. */ 516233965Sjdp if (r_extern 516333965Sjdp || r_type == RELOC_BASE10 516433965Sjdp || r_type == RELOC_BASE13 516533965Sjdp || r_type == RELOC_BASE22) 516633965Sjdp { 516733965Sjdp /* If we know the symbol this relocation is against, 516833965Sjdp convert it into a relocation against a section. This 516933965Sjdp is what the native linker does. */ 517033965Sjdp if (r_type == RELOC_BASE10 517133965Sjdp || r_type == RELOC_BASE13 517233965Sjdp || r_type == RELOC_BASE22) 517333965Sjdp h = NULL; 517433965Sjdp else 517533965Sjdp h = sym_hashes[r_index]; 517633965Sjdp if (h != (struct aout_link_hash_entry *) NULL 517733965Sjdp && (h->root.type == bfd_link_hash_defined 517833965Sjdp || h->root.type == bfd_link_hash_defweak)) 517933965Sjdp { 518033965Sjdp asection *output_section; 518133965Sjdp 518233965Sjdp /* Change the r_extern value. */ 518333965Sjdp if (bfd_header_big_endian (output_bfd)) 518433965Sjdp rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; 518533965Sjdp else 518633965Sjdp rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; 518733965Sjdp 518833965Sjdp /* Compute a new r_index. */ 518933965Sjdp output_section = h->root.u.def.section->output_section; 519033965Sjdp if (output_section == obj_textsec (output_bfd)) 519133965Sjdp r_index = N_TEXT; 519233965Sjdp else if (output_section == obj_datasec (output_bfd)) 519333965Sjdp r_index = N_DATA; 519433965Sjdp else if (output_section == obj_bsssec (output_bfd)) 519533965Sjdp r_index = N_BSS; 519633965Sjdp else 519733965Sjdp r_index = N_ABS; 519833965Sjdp 519933965Sjdp /* Add the symbol value and the section VMA to the 520033965Sjdp addend. */ 520133965Sjdp relocation = (h->root.u.def.value 520233965Sjdp + output_section->vma 520333965Sjdp + h->root.u.def.section->output_offset); 520433965Sjdp 520533965Sjdp /* Now RELOCATION is the VMA of the final 520633965Sjdp destination. If this is a PC relative reloc, 520733965Sjdp then ADDEND is the negative of the source VMA. 520833965Sjdp We want to set ADDEND to the difference between 520933965Sjdp the destination VMA and the source VMA, which 521033965Sjdp means we must adjust RELOCATION by the change in 521133965Sjdp the source VMA. This is done below. */ 521233965Sjdp } 521333965Sjdp else 521433965Sjdp { 521533965Sjdp /* We must change r_index according to the symbol 521633965Sjdp map. */ 521733965Sjdp r_index = symbol_map[r_index]; 521833965Sjdp 521933965Sjdp if (r_index == -1) 522033965Sjdp { 522133965Sjdp if (h != NULL) 522233965Sjdp { 522333965Sjdp /* We decided to strip this symbol, but it 522433965Sjdp turns out that we can't. Note that we 522533965Sjdp lose the other and desc information here. 522633965Sjdp I don't think that will ever matter for a 522733965Sjdp global symbol. */ 522833965Sjdp if (h->indx < 0) 522933965Sjdp { 523033965Sjdp h->indx = -2; 523133965Sjdp h->written = false; 523233965Sjdp if (! aout_link_write_other_symbol (h, 523333965Sjdp (PTR) finfo)) 523433965Sjdp return false; 523533965Sjdp } 523633965Sjdp r_index = h->indx; 523733965Sjdp } 523833965Sjdp else 523933965Sjdp { 524033965Sjdp const char *name; 524133965Sjdp 524233965Sjdp name = strings + GET_WORD (input_bfd, 524333965Sjdp syms[r_index].e_strx); 524433965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 524533965Sjdp (finfo->info, name, input_bfd, input_section, 524633965Sjdp r_addr))) 524733965Sjdp return false; 524833965Sjdp r_index = 0; 524933965Sjdp } 525033965Sjdp } 525133965Sjdp 525233965Sjdp relocation = 0; 525333965Sjdp 525433965Sjdp /* If this is a PC relative reloc, then the addend 525533965Sjdp is the negative of the source VMA. We must 525633965Sjdp adjust it by the change in the source VMA. This 525733965Sjdp is done below. */ 525833965Sjdp } 525933965Sjdp 526033965Sjdp /* Write out the new r_index value. */ 526133965Sjdp if (bfd_header_big_endian (output_bfd)) 526233965Sjdp { 526333965Sjdp rel->r_index[0] = r_index >> 16; 526433965Sjdp rel->r_index[1] = r_index >> 8; 526533965Sjdp rel->r_index[2] = r_index; 526633965Sjdp } 526733965Sjdp else 526833965Sjdp { 526933965Sjdp rel->r_index[2] = r_index >> 16; 527033965Sjdp rel->r_index[1] = r_index >> 8; 527133965Sjdp rel->r_index[0] = r_index; 527233965Sjdp } 527333965Sjdp } 527433965Sjdp else 527533965Sjdp { 527633965Sjdp /* This is a relocation against a section. We must 527733965Sjdp adjust by the amount that the section moved. */ 527833965Sjdp r_section = aout_reloc_index_to_section (input_bfd, r_index); 527933965Sjdp relocation = (r_section->output_section->vma 528033965Sjdp + r_section->output_offset 528133965Sjdp - r_section->vma); 528233965Sjdp 528333965Sjdp /* If this is a PC relative reloc, then the addend is 528433965Sjdp the difference in VMA between the destination and the 528533965Sjdp source. We have just adjusted for the change in VMA 528633965Sjdp of the destination, so we must also adjust by the 528733965Sjdp change in VMA of the source. This is done below. */ 528833965Sjdp } 528933965Sjdp 529033965Sjdp /* As described above, we must always adjust a PC relative 529133965Sjdp reloc by the change in VMA of the source. However, if 529233965Sjdp pcrel_offset is set, then the addend does not include the 529333965Sjdp location within the section, in which case we don't need 529433965Sjdp to adjust anything. */ 529533965Sjdp if (howto_table_ext[r_type].pc_relative 529633965Sjdp && ! howto_table_ext[r_type].pcrel_offset) 529733965Sjdp relocation -= (input_section->output_section->vma 529833965Sjdp + input_section->output_offset 529933965Sjdp - input_section->vma); 530033965Sjdp 530133965Sjdp /* Change the addend if necessary. */ 530233965Sjdp if (relocation != 0) 530333965Sjdp PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend); 530433965Sjdp 530533965Sjdp /* Change the address of the relocation. */ 530633965Sjdp PUT_WORD (output_bfd, 530733965Sjdp r_addr + input_section->output_offset, 530833965Sjdp rel->r_address); 530933965Sjdp } 531033965Sjdp else 531133965Sjdp { 531233965Sjdp boolean hundef; 531333965Sjdp bfd_reloc_status_type r; 531433965Sjdp 531533965Sjdp /* We are generating an executable, and must do a full 531633965Sjdp relocation. */ 531733965Sjdp hundef = false; 531860484Sobrien 531933965Sjdp if (r_extern) 532033965Sjdp { 532133965Sjdp h = sym_hashes[r_index]; 532233965Sjdp 532333965Sjdp if (h != (struct aout_link_hash_entry *) NULL 532433965Sjdp && (h->root.type == bfd_link_hash_defined 532533965Sjdp || h->root.type == bfd_link_hash_defweak)) 532633965Sjdp { 532733965Sjdp relocation = (h->root.u.def.value 532833965Sjdp + h->root.u.def.section->output_section->vma 532933965Sjdp + h->root.u.def.section->output_offset); 533033965Sjdp } 533133965Sjdp else if (h != (struct aout_link_hash_entry *) NULL 533233965Sjdp && h->root.type == bfd_link_hash_undefweak) 533333965Sjdp relocation = 0; 533433965Sjdp else 533533965Sjdp { 533633965Sjdp hundef = true; 533733965Sjdp relocation = 0; 533833965Sjdp } 533933965Sjdp } 534033965Sjdp else if (r_type == RELOC_BASE10 534133965Sjdp || r_type == RELOC_BASE13 534233965Sjdp || r_type == RELOC_BASE22) 534333965Sjdp { 534433965Sjdp struct external_nlist *sym; 534533965Sjdp int type; 534633965Sjdp 534733965Sjdp /* For base relative relocs, r_index is always an index 534833965Sjdp into the symbol table, even if r_extern is 0. */ 534933965Sjdp sym = syms + r_index; 535033965Sjdp type = bfd_h_get_8 (input_bfd, sym->e_type); 535133965Sjdp if ((type & N_TYPE) == N_TEXT 535233965Sjdp || type == N_WEAKT) 535333965Sjdp r_section = obj_textsec (input_bfd); 535433965Sjdp else if ((type & N_TYPE) == N_DATA 535533965Sjdp || type == N_WEAKD) 535633965Sjdp r_section = obj_datasec (input_bfd); 535733965Sjdp else if ((type & N_TYPE) == N_BSS 535833965Sjdp || type == N_WEAKB) 535933965Sjdp r_section = obj_bsssec (input_bfd); 536033965Sjdp else if ((type & N_TYPE) == N_ABS 536133965Sjdp || type == N_WEAKA) 536233965Sjdp r_section = bfd_abs_section_ptr; 536333965Sjdp else 536433965Sjdp abort (); 536533965Sjdp relocation = (r_section->output_section->vma 536633965Sjdp + r_section->output_offset 536733965Sjdp + (GET_WORD (input_bfd, sym->e_value) 536833965Sjdp - r_section->vma)); 536933965Sjdp } 537033965Sjdp else 537133965Sjdp { 537233965Sjdp r_section = aout_reloc_index_to_section (input_bfd, r_index); 537333965Sjdp 537433965Sjdp /* If this is a PC relative reloc, then R_ADDEND is the 537533965Sjdp difference between the two vmas, or 537633965Sjdp old_dest_sec + old_dest_off - (old_src_sec + old_src_off) 537733965Sjdp where 537833965Sjdp old_dest_sec == section->vma 537933965Sjdp and 538033965Sjdp old_src_sec == input_section->vma 538133965Sjdp and 538233965Sjdp old_src_off == r_addr 538333965Sjdp 538433965Sjdp _bfd_final_link_relocate expects RELOCATION + 538533965Sjdp R_ADDEND to be the VMA of the destination minus 538633965Sjdp r_addr (the minus r_addr is because this relocation 538733965Sjdp is not pcrel_offset, which is a bit confusing and 538833965Sjdp should, perhaps, be changed), or 538933965Sjdp new_dest_sec 539033965Sjdp where 539133965Sjdp new_dest_sec == output_section->vma + output_offset 539233965Sjdp We arrange for this to happen by setting RELOCATION to 539333965Sjdp new_dest_sec + old_src_sec - old_dest_sec 539433965Sjdp 539533965Sjdp If this is not a PC relative reloc, then R_ADDEND is 539633965Sjdp simply the VMA of the destination, so we set 539733965Sjdp RELOCATION to the change in the destination VMA, or 539833965Sjdp new_dest_sec - old_dest_sec 539933965Sjdp */ 540033965Sjdp relocation = (r_section->output_section->vma 540133965Sjdp + r_section->output_offset 540233965Sjdp - r_section->vma); 540333965Sjdp if (howto_table_ext[r_type].pc_relative) 540433965Sjdp relocation += input_section->vma; 540533965Sjdp } 540633965Sjdp 540733965Sjdp if (check_dynamic_reloc != NULL) 540833965Sjdp { 540933965Sjdp boolean skip; 541033965Sjdp 541133965Sjdp if (! ((*check_dynamic_reloc) 541233965Sjdp (finfo->info, input_bfd, input_section, h, 541333965Sjdp (PTR) rel, contents, &skip, &relocation))) 541433965Sjdp return false; 541533965Sjdp if (skip) 541633965Sjdp continue; 541733965Sjdp } 541833965Sjdp 541933965Sjdp /* Now warn if a global symbol is undefined. We could not 542033965Sjdp do this earlier, because check_dynamic_reloc might want 542133965Sjdp to skip this reloc. */ 542233965Sjdp if (hundef 542333965Sjdp && ! finfo->info->shared 542433965Sjdp && r_type != RELOC_BASE10 542533965Sjdp && r_type != RELOC_BASE13 542633965Sjdp && r_type != RELOC_BASE22) 542733965Sjdp { 542833965Sjdp const char *name; 542933965Sjdp 543033965Sjdp if (h != NULL) 543133965Sjdp name = h->root.root.string; 543233965Sjdp else 543333965Sjdp name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); 543433965Sjdp if (! ((*finfo->info->callbacks->undefined_symbol) 543560484Sobrien (finfo->info, name, input_bfd, input_section, 543660484Sobrien r_addr, true))) 543733965Sjdp return false; 543833965Sjdp } 543933965Sjdp 544060484Sobrien if (r_type != RELOC_SPARC_REV32) 544160484Sobrien r = MY_final_link_relocate (howto_table_ext + r_type, 544260484Sobrien input_bfd, input_section, 544360484Sobrien contents, r_addr, relocation, 544460484Sobrien r_addend); 544560484Sobrien else 544660484Sobrien { 544760484Sobrien bfd_vma x; 544860484Sobrien 544960484Sobrien x = bfd_get_32 (input_bfd, contents + r_addr); 545060484Sobrien x = x + relocation + r_addend; 545160484Sobrien bfd_putl32 (/*input_bfd,*/ x, contents + r_addr); 545260484Sobrien r = bfd_reloc_ok; 545360484Sobrien } 545460484Sobrien 545533965Sjdp if (r != bfd_reloc_ok) 545633965Sjdp { 545733965Sjdp switch (r) 545833965Sjdp { 545933965Sjdp default: 546033965Sjdp case bfd_reloc_outofrange: 546133965Sjdp abort (); 546233965Sjdp case bfd_reloc_overflow: 546333965Sjdp { 546433965Sjdp const char *name; 546533965Sjdp 546633965Sjdp if (h != NULL) 546733965Sjdp name = h->root.root.string; 546833965Sjdp else if (r_extern 546933965Sjdp || r_type == RELOC_BASE10 547033965Sjdp || r_type == RELOC_BASE13 547133965Sjdp || r_type == RELOC_BASE22) 547233965Sjdp name = strings + GET_WORD (input_bfd, 547333965Sjdp syms[r_index].e_strx); 547433965Sjdp else 547533965Sjdp { 547633965Sjdp asection *s; 547733965Sjdp 547833965Sjdp s = aout_reloc_index_to_section (input_bfd, r_index); 547933965Sjdp name = bfd_section_name (input_bfd, s); 548033965Sjdp } 548133965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 548233965Sjdp (finfo->info, name, howto_table_ext[r_type].name, 548333965Sjdp r_addend, input_bfd, input_section, r_addr))) 548433965Sjdp return false; 548533965Sjdp } 548633965Sjdp break; 548733965Sjdp } 548833965Sjdp } 548933965Sjdp } 549033965Sjdp } 549133965Sjdp 549233965Sjdp return true; 549333965Sjdp} 549433965Sjdp 549533965Sjdp/* Handle a link order which is supposed to generate a reloc. */ 549633965Sjdp 549733965Sjdpstatic boolean 549833965Sjdpaout_link_reloc_link_order (finfo, o, p) 549933965Sjdp struct aout_final_link_info *finfo; 550033965Sjdp asection *o; 550133965Sjdp struct bfd_link_order *p; 550233965Sjdp{ 550333965Sjdp struct bfd_link_order_reloc *pr; 550433965Sjdp int r_index; 550533965Sjdp int r_extern; 550633965Sjdp reloc_howto_type *howto; 550760484Sobrien file_ptr *reloff_ptr = NULL; 550833965Sjdp struct reloc_std_external srel; 550933965Sjdp struct reloc_ext_external erel; 551033965Sjdp PTR rel_ptr; 551133965Sjdp 551233965Sjdp pr = p->u.reloc.p; 551333965Sjdp 551433965Sjdp if (p->type == bfd_section_reloc_link_order) 551533965Sjdp { 551633965Sjdp r_extern = 0; 551733965Sjdp if (bfd_is_abs_section (pr->u.section)) 551833965Sjdp r_index = N_ABS | N_EXT; 551933965Sjdp else 552033965Sjdp { 552133965Sjdp BFD_ASSERT (pr->u.section->owner == finfo->output_bfd); 552233965Sjdp r_index = pr->u.section->target_index; 552333965Sjdp } 552433965Sjdp } 552533965Sjdp else 552633965Sjdp { 552733965Sjdp struct aout_link_hash_entry *h; 552833965Sjdp 552933965Sjdp BFD_ASSERT (p->type == bfd_symbol_reloc_link_order); 553033965Sjdp r_extern = 1; 553133965Sjdp h = ((struct aout_link_hash_entry *) 553233965Sjdp bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info, 553333965Sjdp pr->u.name, false, false, true)); 553433965Sjdp if (h != (struct aout_link_hash_entry *) NULL 553533965Sjdp && h->indx >= 0) 553633965Sjdp r_index = h->indx; 553733965Sjdp else if (h != NULL) 553833965Sjdp { 553933965Sjdp /* We decided to strip this symbol, but it turns out that we 554033965Sjdp can't. Note that we lose the other and desc information 554133965Sjdp here. I don't think that will ever matter for a global 554233965Sjdp symbol. */ 554333965Sjdp h->indx = -2; 554433965Sjdp h->written = false; 554533965Sjdp if (! aout_link_write_other_symbol (h, (PTR) finfo)) 554633965Sjdp return false; 554733965Sjdp r_index = h->indx; 554833965Sjdp } 554933965Sjdp else 555033965Sjdp { 555133965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 555233965Sjdp (finfo->info, pr->u.name, (bfd *) NULL, 555333965Sjdp (asection *) NULL, (bfd_vma) 0))) 555433965Sjdp return false; 555533965Sjdp r_index = 0; 555633965Sjdp } 555733965Sjdp } 555833965Sjdp 555933965Sjdp howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc); 556033965Sjdp if (howto == 0) 556133965Sjdp { 556233965Sjdp bfd_set_error (bfd_error_bad_value); 556333965Sjdp return false; 556433965Sjdp } 556533965Sjdp 556633965Sjdp if (o == obj_textsec (finfo->output_bfd)) 556733965Sjdp reloff_ptr = &finfo->treloff; 556833965Sjdp else if (o == obj_datasec (finfo->output_bfd)) 556933965Sjdp reloff_ptr = &finfo->dreloff; 557033965Sjdp else 557133965Sjdp abort (); 557233965Sjdp 557333965Sjdp if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE) 557433965Sjdp { 557533965Sjdp#ifdef MY_put_reloc 557633965Sjdp MY_put_reloc(finfo->output_bfd, r_extern, r_index, p->offset, howto, 557733965Sjdp &srel); 557833965Sjdp#else 557933965Sjdp { 558033965Sjdp int r_pcrel; 558133965Sjdp int r_baserel; 558233965Sjdp int r_jmptable; 558333965Sjdp int r_relative; 558433965Sjdp int r_length; 558533965Sjdp 558633965Sjdp r_pcrel = howto->pc_relative; 558733965Sjdp r_baserel = (howto->type & 8) != 0; 558833965Sjdp r_jmptable = (howto->type & 16) != 0; 558933965Sjdp r_relative = (howto->type & 32) != 0; 559033965Sjdp r_length = howto->size; 559133965Sjdp 559233965Sjdp PUT_WORD (finfo->output_bfd, p->offset, srel.r_address); 559333965Sjdp if (bfd_header_big_endian (finfo->output_bfd)) 559433965Sjdp { 559533965Sjdp srel.r_index[0] = r_index >> 16; 559633965Sjdp srel.r_index[1] = r_index >> 8; 559733965Sjdp srel.r_index[2] = r_index; 559833965Sjdp srel.r_type[0] = 559933965Sjdp ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) 560033965Sjdp | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) 560133965Sjdp | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) 560233965Sjdp | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) 560333965Sjdp | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) 560433965Sjdp | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); 560533965Sjdp } 560633965Sjdp else 560733965Sjdp { 560833965Sjdp srel.r_index[2] = r_index >> 16; 560933965Sjdp srel.r_index[1] = r_index >> 8; 561033965Sjdp srel.r_index[0] = r_index; 561133965Sjdp srel.r_type[0] = 561233965Sjdp ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) 561333965Sjdp | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) 561433965Sjdp | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) 561533965Sjdp | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) 561633965Sjdp | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) 561733965Sjdp | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 561833965Sjdp } 561933965Sjdp } 562033965Sjdp#endif 562133965Sjdp rel_ptr = (PTR) &srel; 562233965Sjdp 562333965Sjdp /* We have to write the addend into the object file, since 562433965Sjdp standard a.out relocs are in place. It would be more 562533965Sjdp reliable if we had the current contents of the file here, 562633965Sjdp rather than assuming zeroes, but we can't read the file since 562733965Sjdp it was opened using bfd_openw. */ 562833965Sjdp if (pr->addend != 0) 562933965Sjdp { 563033965Sjdp bfd_size_type size; 563133965Sjdp bfd_reloc_status_type r; 563233965Sjdp bfd_byte *buf; 563333965Sjdp boolean ok; 563433965Sjdp 563533965Sjdp size = bfd_get_reloc_size (howto); 563633965Sjdp buf = (bfd_byte *) bfd_zmalloc (size); 563733965Sjdp if (buf == (bfd_byte *) NULL) 563833965Sjdp return false; 563933965Sjdp r = MY_relocate_contents (howto, finfo->output_bfd, 564033965Sjdp pr->addend, buf); 564133965Sjdp switch (r) 564233965Sjdp { 564333965Sjdp case bfd_reloc_ok: 564433965Sjdp break; 564533965Sjdp default: 564633965Sjdp case bfd_reloc_outofrange: 564733965Sjdp abort (); 564833965Sjdp case bfd_reloc_overflow: 564933965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 565033965Sjdp (finfo->info, 565133965Sjdp (p->type == bfd_section_reloc_link_order 565233965Sjdp ? bfd_section_name (finfo->output_bfd, 565333965Sjdp pr->u.section) 565433965Sjdp : pr->u.name), 565533965Sjdp howto->name, pr->addend, (bfd *) NULL, 565633965Sjdp (asection *) NULL, (bfd_vma) 0))) 565733965Sjdp { 565833965Sjdp free (buf); 565933965Sjdp return false; 566033965Sjdp } 566133965Sjdp break; 566233965Sjdp } 566333965Sjdp ok = bfd_set_section_contents (finfo->output_bfd, o, 566433965Sjdp (PTR) buf, 566533965Sjdp (file_ptr) p->offset, 566633965Sjdp size); 566733965Sjdp free (buf); 566833965Sjdp if (! ok) 566933965Sjdp return false; 567033965Sjdp } 567133965Sjdp } 567233965Sjdp else 567333965Sjdp { 567433965Sjdp PUT_WORD (finfo->output_bfd, p->offset, erel.r_address); 567533965Sjdp 567633965Sjdp if (bfd_header_big_endian (finfo->output_bfd)) 567733965Sjdp { 567833965Sjdp erel.r_index[0] = r_index >> 16; 567933965Sjdp erel.r_index[1] = r_index >> 8; 568033965Sjdp erel.r_index[2] = r_index; 568133965Sjdp erel.r_type[0] = 568233965Sjdp ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) 568333965Sjdp | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG)); 568433965Sjdp } 568533965Sjdp else 568633965Sjdp { 568733965Sjdp erel.r_index[2] = r_index >> 16; 568833965Sjdp erel.r_index[1] = r_index >> 8; 568933965Sjdp erel.r_index[0] = r_index; 569033965Sjdp erel.r_type[0] = 569133965Sjdp (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) 569233965Sjdp | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE); 569333965Sjdp } 569433965Sjdp 569533965Sjdp PUT_WORD (finfo->output_bfd, pr->addend, erel.r_addend); 569633965Sjdp 569733965Sjdp rel_ptr = (PTR) &erel; 569833965Sjdp } 569933965Sjdp 570033965Sjdp if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0 570133965Sjdp || (bfd_write (rel_ptr, (bfd_size_type) 1, 570233965Sjdp obj_reloc_entry_size (finfo->output_bfd), 570333965Sjdp finfo->output_bfd) 570433965Sjdp != obj_reloc_entry_size (finfo->output_bfd))) 570533965Sjdp return false; 570633965Sjdp 570733965Sjdp *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd); 570833965Sjdp 570933965Sjdp /* Assert that the relocs have not run into the symbols, and that n 571033965Sjdp the text relocs have not run into the data relocs. */ 571133965Sjdp BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) 571233965Sjdp && (reloff_ptr != &finfo->treloff 571333965Sjdp || (*reloff_ptr 571433965Sjdp <= obj_datasec (finfo->output_bfd)->rel_filepos))); 571533965Sjdp 571633965Sjdp return true; 571733965Sjdp} 5718