aoutx.h revision 104834
133965Sjdp/* BFD semi-generic back-end for a.out binaries. 278828Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 394536Sobrien 2001, 2002 438889Sjdp Free Software Foundation, Inc. 533965Sjdp Written by Cygnus Support. 633965Sjdp 733965SjdpThis file is part of BFD, the Binary File Descriptor library. 833965Sjdp 933965SjdpThis program is free software; you can redistribute it and/or modify 1033965Sjdpit under the terms of the GNU General Public License as published by 1133965Sjdpthe Free Software Foundation; either version 2 of the License, or 1233965Sjdp(at your option) any later version. 1333965Sjdp 1433965SjdpThis program is distributed in the hope that it will be useful, 1533965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1633965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1733965SjdpGNU General Public License for more details. 1833965Sjdp 1933965SjdpYou should have received a copy of the GNU General Public License 2033965Sjdpalong with this program; if not, write to the Free Software 2133965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2233965Sjdp 2333965Sjdp/* 2433965SjdpSECTION 2533965Sjdp a.out backends 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 "bfd.h" 12460484Sobrien#include "sysdep.h" 12589857Sobrien#include "safe-ctype.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 *)); 14289857Sobrienreloc_howto_type * NAME(aout,reloc_type_lookup) 14389857Sobrien PARAMS ((bfd *, bfd_reloc_code_real_type)); 14433965Sjdp 14533965Sjdp/* 14633965SjdpSUBSECTION 14733965Sjdp Relocations 14833965Sjdp 14933965SjdpDESCRIPTION 15033965Sjdp The file @file{aoutx.h} provides for both the @emph{standard} 15133965Sjdp and @emph{extended} forms of a.out relocation records. 15233965Sjdp 15333965Sjdp The standard records contain only an 15433965Sjdp address, a symbol index, and a type field. The extended records 15533965Sjdp (used on 29ks and sparcs) also have a full integer for an 15633965Sjdp addend. 15733965Sjdp 15833965Sjdp*/ 15933965Sjdp#ifndef CTOR_TABLE_RELOC_HOWTO 16033965Sjdp#define CTOR_TABLE_RELOC_IDX 2 16189857Sobrien#define CTOR_TABLE_RELOC_HOWTO(BFD) \ 16289857Sobrien ((obj_reloc_entry_size (BFD) == RELOC_EXT_SIZE \ 16389857Sobrien ? howto_table_ext : howto_table_std) \ 16489857Sobrien + CTOR_TABLE_RELOC_IDX) 16533965Sjdp#endif 16633965Sjdp 16733965Sjdp#ifndef MY_swap_std_reloc_in 16833965Sjdp#define MY_swap_std_reloc_in NAME(aout,swap_std_reloc_in) 16933965Sjdp#endif 17033965Sjdp 17177298Sobrien#ifndef MY_swap_ext_reloc_in 17277298Sobrien#define MY_swap_ext_reloc_in NAME(aout,swap_ext_reloc_in) 17377298Sobrien#endif 17477298Sobrien 17533965Sjdp#ifndef MY_swap_std_reloc_out 17633965Sjdp#define MY_swap_std_reloc_out NAME(aout,swap_std_reloc_out) 17733965Sjdp#endif 17833965Sjdp 17977298Sobrien#ifndef MY_swap_ext_reloc_out 18077298Sobrien#define MY_swap_ext_reloc_out NAME(aout,swap_ext_reloc_out) 18177298Sobrien#endif 18277298Sobrien 18333965Sjdp#ifndef MY_final_link_relocate 18433965Sjdp#define MY_final_link_relocate _bfd_final_link_relocate 18533965Sjdp#endif 18633965Sjdp 18733965Sjdp#ifndef MY_relocate_contents 18833965Sjdp#define MY_relocate_contents _bfd_relocate_contents 18933965Sjdp#endif 19033965Sjdp 19133965Sjdp#define howto_table_ext NAME(aout,ext_howto_table) 19233965Sjdp#define howto_table_std NAME(aout,std_howto_table) 19333965Sjdp 19433965Sjdpreloc_howto_type howto_table_ext[] = 19533965Sjdp{ 19633965Sjdp /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ 19733965Sjdp HOWTO(RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", false, 0,0x000000ff, false), 19833965Sjdp HOWTO(RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", false, 0,0x0000ffff, false), 19933965Sjdp HOWTO(RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", false, 0,0xffffffff, false), 20033965Sjdp HOWTO(RELOC_DISP8, 0, 0, 8, true, 0, complain_overflow_signed,0,"DISP8", false, 0,0x000000ff, false), 20133965Sjdp HOWTO(RELOC_DISP16, 0, 1, 16, true, 0, complain_overflow_signed,0,"DISP16", false, 0,0x0000ffff, false), 20233965Sjdp HOWTO(RELOC_DISP32, 0, 2, 32, true, 0, complain_overflow_signed,0,"DISP32", false, 0,0xffffffff, false), 20333965Sjdp HOWTO(RELOC_WDISP30,2, 2, 30, true, 0, complain_overflow_signed,0,"WDISP30", false, 0,0x3fffffff, false), 20433965Sjdp HOWTO(RELOC_WDISP22,2, 2, 22, true, 0, complain_overflow_signed,0,"WDISP22", false, 0,0x003fffff, false), 20533965Sjdp HOWTO(RELOC_HI22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"HI22", false, 0,0x003fffff, false), 20633965Sjdp HOWTO(RELOC_22, 0, 2, 22, false, 0, complain_overflow_bitfield,0,"22", false, 0,0x003fffff, false), 20733965Sjdp HOWTO(RELOC_13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"13", false, 0,0x00001fff, false), 20833965Sjdp HOWTO(RELOC_LO10, 0, 2, 10, false, 0, complain_overflow_dont,0,"LO10", false, 0,0x000003ff, false), 20933965Sjdp HOWTO(RELOC_SFA_BASE,0, 2, 32, false, 0, complain_overflow_bitfield,0,"SFA_BASE", false, 0,0xffffffff, false), 21033965Sjdp HOWTO(RELOC_SFA_OFF13,0,2, 32, false, 0, complain_overflow_bitfield,0,"SFA_OFF13",false, 0,0xffffffff, false), 21133965Sjdp HOWTO(RELOC_BASE10, 0, 2, 10, false, 0, complain_overflow_dont,0,"BASE10", false, 0,0x000003ff, false), 21260484Sobrien HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, complain_overflow_signed,0,"BASE13", false, 0,0x00001fff, false), 21333965Sjdp HOWTO(RELOC_BASE22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"BASE22", false, 0,0x003fffff, false), 21433965Sjdp HOWTO(RELOC_PC10, 0, 2, 10, true, 0, complain_overflow_dont,0,"PC10", false, 0,0x000003ff, true), 21533965Sjdp HOWTO(RELOC_PC22, 10, 2, 22, true, 0, complain_overflow_signed,0,"PC22", false, 0,0x003fffff, true), 21633965Sjdp HOWTO(RELOC_JMP_TBL,2, 2, 30, true, 0, complain_overflow_signed,0,"JMP_TBL", false, 0,0x3fffffff, false), 21733965Sjdp HOWTO(RELOC_SEGOFF16,0, 2, 0, false, 0, complain_overflow_bitfield,0,"SEGOFF16", false, 0,0x00000000, false), 21833965Sjdp HOWTO(RELOC_GLOB_DAT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"GLOB_DAT", false, 0,0x00000000, false), 21933965Sjdp HOWTO(RELOC_JMP_SLOT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_SLOT", false, 0,0x00000000, false), 22033965Sjdp HOWTO(RELOC_RELATIVE,0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false), 22160484Sobrien HOWTO(0, 0, 0, 0, false, 0, complain_overflow_dont, 0, "R_SPARC_NONE", false,0,0x00000000,true), 22260484Sobrien HOWTO(0, 0, 0, 0, false, 0, complain_overflow_dont, 0, "R_SPARC_NONE", false,0,0x00000000,true), 22360484Sobrien#define RELOC_SPARC_REV32 RELOC_WDISP19 22460484Sobrien HOWTO(RELOC_SPARC_REV32, 0, 2, 32, false, 0, complain_overflow_dont,0,"R_SPARC_REV32", false, 0,0xffffffff, false), 22533965Sjdp}; 22633965Sjdp 22733965Sjdp/* Convert standard reloc records to "arelent" format (incl byte swap). */ 22833965Sjdp 22933965Sjdpreloc_howto_type howto_table_std[] = { 23033965Sjdp /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ 23189857SobrienHOWTO ( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false), 23289857SobrienHOWTO ( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false), 23389857SobrienHOWTO ( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false), 23489857SobrienHOWTO ( 3, 0, 4, 64, false, 0, complain_overflow_bitfield,0,"64", true, 0xdeaddead,0xdeaddead, false), 23589857SobrienHOWTO ( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", true, 0x000000ff,0x000000ff, false), 23689857SobrienHOWTO ( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, false), 23789857SobrienHOWTO ( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, false), 23889857SobrienHOWTO ( 7, 0, 4, 64, true, 0, complain_overflow_signed, 0,"DISP64", true, 0xfeedface,0xfeedface, false), 23989857SobrienHOWTO ( 8, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"GOT_REL", false, 0,0x00000000, false), 24089857SobrienHOWTO ( 9, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"BASE16", false,0xffffffff,0xffffffff, false), 24189857SobrienHOWTO (10, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"BASE32", false,0xffffffff,0xffffffff, false), 24260484SobrienEMPTY_HOWTO (-1), 24360484SobrienEMPTY_HOWTO (-1), 24460484SobrienEMPTY_HOWTO (-1), 24560484SobrienEMPTY_HOWTO (-1), 24660484SobrienEMPTY_HOWTO (-1), 24789857Sobrien HOWTO (16, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_TABLE", false, 0,0x00000000, false), 24860484SobrienEMPTY_HOWTO (-1), 24960484SobrienEMPTY_HOWTO (-1), 25060484SobrienEMPTY_HOWTO (-1), 25160484SobrienEMPTY_HOWTO (-1), 25260484SobrienEMPTY_HOWTO (-1), 25360484SobrienEMPTY_HOWTO (-1), 25460484SobrienEMPTY_HOWTO (-1), 25560484SobrienEMPTY_HOWTO (-1), 25660484SobrienEMPTY_HOWTO (-1), 25760484SobrienEMPTY_HOWTO (-1), 25860484SobrienEMPTY_HOWTO (-1), 25960484SobrienEMPTY_HOWTO (-1), 26060484SobrienEMPTY_HOWTO (-1), 26160484SobrienEMPTY_HOWTO (-1), 26260484SobrienEMPTY_HOWTO (-1), 26389857Sobrien HOWTO (32, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false), 26460484SobrienEMPTY_HOWTO (-1), 26560484SobrienEMPTY_HOWTO (-1), 26660484SobrienEMPTY_HOWTO (-1), 26760484SobrienEMPTY_HOWTO (-1), 26860484SobrienEMPTY_HOWTO (-1), 26960484SobrienEMPTY_HOWTO (-1), 27060484SobrienEMPTY_HOWTO (-1), 27189857Sobrien HOWTO (40, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASEREL", false, 0,0x00000000, false), 27233965Sjdp}; 27333965Sjdp 27489857Sobrien#define TABLE_SIZE(TABLE) (sizeof (TABLE) / sizeof (TABLE[0])) 27533965Sjdp 27633965Sjdpreloc_howto_type * 27733965SjdpNAME(aout,reloc_type_lookup) (abfd,code) 27833965Sjdp bfd *abfd; 27933965Sjdp bfd_reloc_code_real_type code; 28033965Sjdp{ 28189857Sobrien#define EXT(i, j) case i: return &howto_table_ext[j] 28289857Sobrien#define STD(i, j) case i: return &howto_table_std[j] 28333965Sjdp int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE; 28433965Sjdp if (code == BFD_RELOC_CTOR) 28533965Sjdp switch (bfd_get_arch_info (abfd)->bits_per_address) 28633965Sjdp { 28733965Sjdp case 32: 28833965Sjdp code = BFD_RELOC_32; 28933965Sjdp break; 29033965Sjdp case 64: 29133965Sjdp code = BFD_RELOC_64; 29233965Sjdp break; 29333965Sjdp } 29433965Sjdp if (ext) 29533965Sjdp switch (code) 29633965Sjdp { 29777298Sobrien EXT (BFD_RELOC_8, 0); 29877298Sobrien EXT (BFD_RELOC_16, 1); 29933965Sjdp EXT (BFD_RELOC_32, 2); 30033965Sjdp EXT (BFD_RELOC_HI22, 8); 30133965Sjdp EXT (BFD_RELOC_LO10, 11); 30233965Sjdp EXT (BFD_RELOC_32_PCREL_S2, 6); 30333965Sjdp EXT (BFD_RELOC_SPARC_WDISP22, 7); 30433965Sjdp EXT (BFD_RELOC_SPARC13, 10); 30533965Sjdp EXT (BFD_RELOC_SPARC_GOT10, 14); 30633965Sjdp EXT (BFD_RELOC_SPARC_BASE13, 15); 30733965Sjdp EXT (BFD_RELOC_SPARC_GOT13, 15); 30833965Sjdp EXT (BFD_RELOC_SPARC_GOT22, 16); 30933965Sjdp EXT (BFD_RELOC_SPARC_PC10, 17); 31033965Sjdp EXT (BFD_RELOC_SPARC_PC22, 18); 31133965Sjdp EXT (BFD_RELOC_SPARC_WPLT30, 19); 31260484Sobrien EXT (BFD_RELOC_SPARC_REV32, 26); 31333965Sjdp default: return (reloc_howto_type *) NULL; 31433965Sjdp } 31533965Sjdp else 31633965Sjdp /* std relocs */ 31733965Sjdp switch (code) 31833965Sjdp { 31933965Sjdp STD (BFD_RELOC_16, 1); 32033965Sjdp STD (BFD_RELOC_32, 2); 32133965Sjdp STD (BFD_RELOC_8_PCREL, 4); 32233965Sjdp STD (BFD_RELOC_16_PCREL, 5); 32333965Sjdp STD (BFD_RELOC_32_PCREL, 6); 32433965Sjdp STD (BFD_RELOC_16_BASEREL, 9); 32533965Sjdp STD (BFD_RELOC_32_BASEREL, 10); 32633965Sjdp default: return (reloc_howto_type *) NULL; 32733965Sjdp } 32833965Sjdp} 32933965Sjdp 33033965Sjdp/* 33133965SjdpSUBSECTION 33233965Sjdp Internal entry points 33333965Sjdp 33433965SjdpDESCRIPTION 33533965Sjdp @file{aoutx.h} exports several routines for accessing the 33633965Sjdp contents of an a.out file, which are gathered and exported in 33733965Sjdp turn by various format specific files (eg sunos.c). 33833965Sjdp 33933965Sjdp*/ 34033965Sjdp 34133965Sjdp/* 34233965SjdpFUNCTION 34333965Sjdp aout_@var{size}_swap_exec_header_in 34433965Sjdp 34533965SjdpSYNOPSIS 34633965Sjdp void aout_@var{size}_swap_exec_header_in, 34733965Sjdp (bfd *abfd, 34833965Sjdp struct external_exec *raw_bytes, 34933965Sjdp struct internal_exec *execp); 35033965Sjdp 35133965SjdpDESCRIPTION 35233965Sjdp Swap the information in an executable header @var{raw_bytes} taken 35333965Sjdp from a raw byte stream memory image into the internal exec header 35433965Sjdp structure @var{execp}. 35533965Sjdp*/ 35633965Sjdp 35733965Sjdp#ifndef NAME_swap_exec_header_in 35833965Sjdpvoid 35933965SjdpNAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp) 36033965Sjdp bfd *abfd; 36133965Sjdp struct external_exec *raw_bytes; 36233965Sjdp struct internal_exec *execp; 36333965Sjdp{ 36433965Sjdp struct external_exec *bytes = (struct external_exec *)raw_bytes; 36533965Sjdp 36633965Sjdp /* The internal_exec structure has some fields that are unused in this 36733965Sjdp configuration (IE for i960), so ensure that all such uninitialized 36833965Sjdp fields are zero'd out. There are places where two of these structs 36977298Sobrien are memcmp'd, and thus the contents do matter. */ 37033965Sjdp memset ((PTR) execp, 0, sizeof (struct internal_exec)); 37133965Sjdp /* Now fill in fields in the execp, from the bytes in the raw data. */ 37289857Sobrien execp->a_info = H_GET_32 (abfd, bytes->e_info); 37333965Sjdp execp->a_text = GET_WORD (abfd, bytes->e_text); 37433965Sjdp execp->a_data = GET_WORD (abfd, bytes->e_data); 37533965Sjdp execp->a_bss = GET_WORD (abfd, bytes->e_bss); 37633965Sjdp execp->a_syms = GET_WORD (abfd, bytes->e_syms); 37733965Sjdp execp->a_entry = GET_WORD (abfd, bytes->e_entry); 37833965Sjdp execp->a_trsize = GET_WORD (abfd, bytes->e_trsize); 37933965Sjdp execp->a_drsize = GET_WORD (abfd, bytes->e_drsize); 38033965Sjdp} 38133965Sjdp#define NAME_swap_exec_header_in NAME(aout,swap_exec_header_in) 38233965Sjdp#endif 38333965Sjdp 38433965Sjdp/* 38533965SjdpFUNCTION 38633965Sjdp aout_@var{size}_swap_exec_header_out 38733965Sjdp 38833965SjdpSYNOPSIS 38933965Sjdp void aout_@var{size}_swap_exec_header_out 39033965Sjdp (bfd *abfd, 39133965Sjdp struct internal_exec *execp, 39233965Sjdp struct external_exec *raw_bytes); 39333965Sjdp 39433965SjdpDESCRIPTION 39533965Sjdp Swap the information in an internal exec header structure 39633965Sjdp @var{execp} into the buffer @var{raw_bytes} ready for writing to disk. 39733965Sjdp*/ 39833965Sjdpvoid 39933965SjdpNAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes) 40033965Sjdp bfd *abfd; 40133965Sjdp struct internal_exec *execp; 40233965Sjdp struct external_exec *raw_bytes; 40333965Sjdp{ 40433965Sjdp struct external_exec *bytes = (struct external_exec *)raw_bytes; 40533965Sjdp 40677298Sobrien /* Now fill in fields in the raw data, from the fields in the exec struct. */ 40789857Sobrien H_PUT_32 (abfd, execp->a_info , bytes->e_info); 40833965Sjdp PUT_WORD (abfd, execp->a_text , bytes->e_text); 40933965Sjdp PUT_WORD (abfd, execp->a_data , bytes->e_data); 41033965Sjdp PUT_WORD (abfd, execp->a_bss , bytes->e_bss); 41133965Sjdp PUT_WORD (abfd, execp->a_syms , bytes->e_syms); 41233965Sjdp PUT_WORD (abfd, execp->a_entry , bytes->e_entry); 41333965Sjdp PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize); 41433965Sjdp PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize); 41533965Sjdp} 41633965Sjdp 41733965Sjdp/* Make all the section for an a.out file. */ 41833965Sjdp 41933965Sjdpboolean 42033965SjdpNAME(aout,make_sections) (abfd) 42133965Sjdp bfd *abfd; 42233965Sjdp{ 42333965Sjdp if (obj_textsec (abfd) == (asection *) NULL 42433965Sjdp && bfd_make_section (abfd, ".text") == (asection *) NULL) 42533965Sjdp return false; 42633965Sjdp if (obj_datasec (abfd) == (asection *) NULL 42733965Sjdp && bfd_make_section (abfd, ".data") == (asection *) NULL) 42833965Sjdp return false; 42933965Sjdp if (obj_bsssec (abfd) == (asection *) NULL 43033965Sjdp && bfd_make_section (abfd, ".bss") == (asection *) NULL) 43133965Sjdp return false; 43233965Sjdp return true; 43333965Sjdp} 43433965Sjdp 43533965Sjdp/* 43633965SjdpFUNCTION 43733965Sjdp aout_@var{size}_some_aout_object_p 43833965Sjdp 43933965SjdpSYNOPSIS 44033965Sjdp const bfd_target *aout_@var{size}_some_aout_object_p 44133965Sjdp (bfd *abfd, 44277298Sobrien const bfd_target *(*callback_to_real_object_p) ()); 44333965Sjdp 44433965SjdpDESCRIPTION 44533965Sjdp Some a.out variant thinks that the file open in @var{abfd} 44633965Sjdp checking is an a.out file. Do some more checking, and set up 44733965Sjdp for access if it really is. Call back to the calling 44833965Sjdp environment's "finish up" function just before returning, to 44933965Sjdp handle any last-minute setup. 45033965Sjdp*/ 45133965Sjdp 45233965Sjdpconst bfd_target * 45333965SjdpNAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p) 45433965Sjdp bfd *abfd; 45533965Sjdp struct internal_exec *execp; 45633965Sjdp const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *)); 45733965Sjdp{ 45833965Sjdp struct aout_data_struct *rawptr, *oldrawptr; 45933965Sjdp const bfd_target *result; 46089857Sobrien bfd_size_type amt = sizeof (struct aout_data_struct); 46133965Sjdp 46289857Sobrien rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt); 46333965Sjdp if (rawptr == NULL) 46433965Sjdp return 0; 46533965Sjdp 46633965Sjdp oldrawptr = abfd->tdata.aout_data; 46733965Sjdp abfd->tdata.aout_data = rawptr; 46833965Sjdp 46933965Sjdp /* Copy the contents of the old tdata struct. 47033965Sjdp In particular, we want the subformat, since for hpux it was set in 47133965Sjdp hp300hpux.c:swap_exec_header_in and will be used in 47233965Sjdp hp300hpux.c:callback. */ 47333965Sjdp if (oldrawptr != NULL) 47433965Sjdp *abfd->tdata.aout_data = *oldrawptr; 47533965Sjdp 47633965Sjdp abfd->tdata.aout_data->a.hdr = &rawptr->e; 47733965Sjdp *(abfd->tdata.aout_data->a.hdr) = *execp; /* Copy in the internal_exec struct */ 47833965Sjdp execp = abfd->tdata.aout_data->a.hdr; 47933965Sjdp 48033965Sjdp /* Set the file flags */ 48133965Sjdp abfd->flags = BFD_NO_FLAGS; 48233965Sjdp if (execp->a_drsize || execp->a_trsize) 48333965Sjdp abfd->flags |= HAS_RELOC; 48433965Sjdp /* Setting of EXEC_P has been deferred to the bottom of this function */ 48533965Sjdp if (execp->a_syms) 48633965Sjdp abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; 48789857Sobrien if (N_DYNAMIC (*execp)) 48833965Sjdp abfd->flags |= DYNAMIC; 48933965Sjdp 49033965Sjdp if (N_MAGIC (*execp) == ZMAGIC) 49133965Sjdp { 49233965Sjdp abfd->flags |= D_PAGED | WP_TEXT; 49333965Sjdp adata (abfd).magic = z_magic; 49433965Sjdp } 49533965Sjdp else if (N_MAGIC (*execp) == QMAGIC) 49633965Sjdp { 49733965Sjdp abfd->flags |= D_PAGED | WP_TEXT; 49833965Sjdp adata (abfd).magic = z_magic; 49933965Sjdp adata (abfd).subformat = q_magic_format; 50033965Sjdp } 50133965Sjdp else if (N_MAGIC (*execp) == NMAGIC) 50233965Sjdp { 50333965Sjdp abfd->flags |= WP_TEXT; 50433965Sjdp adata (abfd).magic = n_magic; 50533965Sjdp } 50633965Sjdp else if (N_MAGIC (*execp) == OMAGIC 50733965Sjdp || N_MAGIC (*execp) == BMAGIC) 50833965Sjdp adata (abfd).magic = o_magic; 50933965Sjdp else 51033965Sjdp { 51133965Sjdp /* Should have been checked with N_BADMAG before this routine 51233965Sjdp was called. */ 51333965Sjdp abort (); 51433965Sjdp } 51533965Sjdp 51633965Sjdp bfd_get_start_address (abfd) = execp->a_entry; 51733965Sjdp 51833965Sjdp obj_aout_symbols (abfd) = (aout_symbol_type *)NULL; 51933965Sjdp bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist); 52033965Sjdp 52133965Sjdp /* The default relocation entry size is that of traditional V7 Unix. */ 52233965Sjdp obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 52333965Sjdp 52477298Sobrien /* The default symbol entry size is that of traditional Unix. */ 52533965Sjdp obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE; 52633965Sjdp 52733965Sjdp#ifdef USE_MMAP 52833965Sjdp bfd_init_window (&obj_aout_sym_window (abfd)); 52933965Sjdp bfd_init_window (&obj_aout_string_window (abfd)); 53033965Sjdp#endif 53133965Sjdp obj_aout_external_syms (abfd) = NULL; 53233965Sjdp obj_aout_external_strings (abfd) = NULL; 53333965Sjdp obj_aout_sym_hashes (abfd) = NULL; 53433965Sjdp 53533965Sjdp if (! NAME(aout,make_sections) (abfd)) 536104834Sobrien goto error_ret; 53733965Sjdp 53833965Sjdp obj_datasec (abfd)->_raw_size = execp->a_data; 53933965Sjdp obj_bsssec (abfd)->_raw_size = execp->a_bss; 54033965Sjdp 54133965Sjdp obj_textsec (abfd)->flags = 54233965Sjdp (execp->a_trsize != 0 54333965Sjdp ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) 54433965Sjdp : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); 54533965Sjdp obj_datasec (abfd)->flags = 54633965Sjdp (execp->a_drsize != 0 54733965Sjdp ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) 54833965Sjdp : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); 54933965Sjdp obj_bsssec (abfd)->flags = SEC_ALLOC; 55033965Sjdp 55133965Sjdp#ifdef THIS_IS_ONLY_DOCUMENTATION 55233965Sjdp /* The common code can't fill in these things because they depend 55333965Sjdp on either the start address of the text segment, the rounding 55433965Sjdp up of virtual addresses between segments, or the starting file 55533965Sjdp position of the text segment -- all of which varies among different 55633965Sjdp versions of a.out. */ 55733965Sjdp 55833965Sjdp /* Call back to the format-dependent code to fill in the rest of the 55933965Sjdp fields and do any further cleanup. Things that should be filled 56033965Sjdp in by the callback: */ 56133965Sjdp 56233965Sjdp struct exec *execp = exec_hdr (abfd); 56333965Sjdp 56489857Sobrien obj_textsec (abfd)->size = N_TXTSIZE (*execp); 56589857Sobrien obj_textsec (abfd)->raw_size = N_TXTSIZE (*execp); 56633965Sjdp /* data and bss are already filled in since they're so standard */ 56733965Sjdp 56833965Sjdp /* The virtual memory addresses of the sections */ 56989857Sobrien obj_textsec (abfd)->vma = N_TXTADDR (*execp); 57089857Sobrien obj_datasec (abfd)->vma = N_DATADDR (*execp); 57189857Sobrien obj_bsssec (abfd)->vma = N_BSSADDR (*execp); 57233965Sjdp 57333965Sjdp /* The file offsets of the sections */ 57489857Sobrien obj_textsec (abfd)->filepos = N_TXTOFF (*execp); 57589857Sobrien obj_datasec (abfd)->filepos = N_DATOFF (*execp); 57633965Sjdp 57733965Sjdp /* The file offsets of the relocation info */ 57889857Sobrien obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp); 57989857Sobrien obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp); 58033965Sjdp 58133965Sjdp /* The file offsets of the string table and symbol table. */ 58233965Sjdp obj_str_filepos (abfd) = N_STROFF (*execp); 58333965Sjdp obj_sym_filepos (abfd) = N_SYMOFF (*execp); 58433965Sjdp 58533965Sjdp /* Determine the architecture and machine type of the object file. */ 58689857Sobrien switch (N_MACHTYPE (*exec_hdr (abfd))) 58789857Sobrien { 58889857Sobrien default: 58989857Sobrien abfd->obj_arch = bfd_arch_obscure; 59089857Sobrien break; 59189857Sobrien } 59233965Sjdp 59389857Sobrien adata (abfd)->page_size = TARGET_PAGE_SIZE; 59489857Sobrien adata (abfd)->segment_size = SEGMENT_SIZE; 59589857Sobrien adata (abfd)->exec_bytes_size = EXEC_BYTES_SIZE; 59633965Sjdp 59733965Sjdp return abfd->xvec; 59833965Sjdp 59933965Sjdp /* The architecture is encoded in various ways in various a.out variants, 60033965Sjdp or is not encoded at all in some of them. The relocation size depends 60133965Sjdp on the architecture and the a.out variant. Finally, the return value 60233965Sjdp is the bfd_target vector in use. If an error occurs, return zero and 60333965Sjdp set bfd_error to the appropriate error code. 60433965Sjdp 60533965Sjdp Formats such as b.out, which have additional fields in the a.out 60633965Sjdp header, should cope with them in this callback as well. */ 60733965Sjdp#endif /* DOCUMENTATION */ 60833965Sjdp 60977298Sobrien result = (*callback_to_real_object_p) (abfd); 61033965Sjdp 61133965Sjdp /* Now that the segment addresses have been worked out, take a better 61233965Sjdp guess at whether the file is executable. If the entry point 61333965Sjdp is within the text segment, assume it is. (This makes files 61433965Sjdp executable even if their entry point address is 0, as long as 61533965Sjdp their text starts at zero.). 61633965Sjdp 61733965Sjdp This test had to be changed to deal with systems where the text segment 61833965Sjdp runs at a different location than the default. The problem is that the 61933965Sjdp entry address can appear to be outside the text segment, thus causing an 62033965Sjdp erroneous conclusion that the file isn't executable. 62133965Sjdp 62233965Sjdp To fix this, we now accept any non-zero entry point as an indication of 62333965Sjdp executability. This will work most of the time, since only the linker 62477298Sobrien sets the entry point, and that is likely to be non-zero for most systems. */ 62533965Sjdp 62633965Sjdp if (execp->a_entry != 0 62789857Sobrien || (execp->a_entry >= obj_textsec (abfd)->vma 62889857Sobrien && execp->a_entry < (obj_textsec (abfd)->vma 62989857Sobrien + obj_textsec (abfd)->_raw_size))) 63033965Sjdp abfd->flags |= EXEC_P; 63133965Sjdp#ifdef STAT_FOR_EXEC 63233965Sjdp else 63333965Sjdp { 63433965Sjdp struct stat stat_buf; 63533965Sjdp 63633965Sjdp /* The original heuristic doesn't work in some important cases. 63733965Sjdp The a.out file has no information about the text start 63833965Sjdp address. For files (like kernels) linked to non-standard 63933965Sjdp addresses (ld -Ttext nnn) the entry point may not be between 64033965Sjdp the default text start (obj_textsec(abfd)->vma) and 64133965Sjdp (obj_textsec(abfd)->vma) + text size. This is not just a mach 64233965Sjdp issue. Many kernels are loaded at non standard addresses. */ 64333965Sjdp if (abfd->iostream != NULL 64433965Sjdp && (abfd->flags & BFD_IN_MEMORY) == 0 64589857Sobrien && (fstat (fileno ((FILE *) (abfd->iostream)), &stat_buf) == 0) 64633965Sjdp && ((stat_buf.st_mode & 0111) != 0)) 64733965Sjdp abfd->flags |= EXEC_P; 64833965Sjdp } 64933965Sjdp#endif /* STAT_FOR_EXEC */ 65033965Sjdp 65133965Sjdp if (result) 65233965Sjdp { 65333965Sjdp#if 0 /* These should be set correctly anyways. */ 65433965Sjdp abfd->sections = obj_textsec (abfd); 65533965Sjdp obj_textsec (abfd)->next = obj_datasec (abfd); 65633965Sjdp obj_datasec (abfd)->next = obj_bsssec (abfd); 65733965Sjdp#endif 658104834Sobrien return result; 65933965Sjdp } 660104834Sobrien 661104834Sobrien error_ret: 662104834Sobrien bfd_release (abfd, rawptr); 663104834Sobrien abfd->tdata.aout_data = oldrawptr; 664104834Sobrien return NULL; 66533965Sjdp} 66633965Sjdp 66733965Sjdp/* 66833965SjdpFUNCTION 66933965Sjdp aout_@var{size}_mkobject 67033965Sjdp 67133965SjdpSYNOPSIS 67233965Sjdp boolean aout_@var{size}_mkobject, (bfd *abfd); 67333965Sjdp 67433965SjdpDESCRIPTION 67533965Sjdp Initialize BFD @var{abfd} for use with a.out files. 67633965Sjdp*/ 67733965Sjdp 67833965Sjdpboolean 67933965SjdpNAME(aout,mkobject) (abfd) 68033965Sjdp bfd *abfd; 68133965Sjdp{ 68289857Sobrien struct aout_data_struct *rawptr; 68389857Sobrien bfd_size_type amt = sizeof (struct aout_data_struct); 68433965Sjdp 68533965Sjdp bfd_set_error (bfd_error_system_call); 68633965Sjdp 68789857Sobrien rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt); 68833965Sjdp if (rawptr == NULL) 68933965Sjdp return false; 69033965Sjdp 69133965Sjdp abfd->tdata.aout_data = rawptr; 69233965Sjdp exec_hdr (abfd) = &(rawptr->e); 69333965Sjdp 69489857Sobrien obj_textsec (abfd) = (asection *) NULL; 69589857Sobrien obj_datasec (abfd) = (asection *) NULL; 69689857Sobrien obj_bsssec (abfd) = (asection *) NULL; 69733965Sjdp 69833965Sjdp return true; 69933965Sjdp} 70033965Sjdp 70133965Sjdp/* 70233965SjdpFUNCTION 70333965Sjdp aout_@var{size}_machine_type 70433965Sjdp 70533965SjdpSYNOPSIS 70633965Sjdp enum machine_type aout_@var{size}_machine_type 70733965Sjdp (enum bfd_architecture arch, 70833965Sjdp unsigned long machine)); 70933965Sjdp 71033965SjdpDESCRIPTION 71133965Sjdp Keep track of machine architecture and machine type for 71233965Sjdp a.out's. Return the <<machine_type>> for a particular 71333965Sjdp architecture and machine, or <<M_UNKNOWN>> if that exact architecture 71433965Sjdp and machine can't be represented in a.out format. 71533965Sjdp 71633965Sjdp If the architecture is understood, machine type 0 (default) 71733965Sjdp is always understood. 71833965Sjdp*/ 71933965Sjdp 72033965Sjdpenum machine_type 72133965SjdpNAME(aout,machine_type) (arch, machine, unknown) 72233965Sjdp enum bfd_architecture arch; 72333965Sjdp unsigned long machine; 72433965Sjdp boolean *unknown; 72533965Sjdp{ 72633965Sjdp enum machine_type arch_flags; 72733965Sjdp 72833965Sjdp arch_flags = M_UNKNOWN; 72933965Sjdp *unknown = true; 73033965Sjdp 73189857Sobrien switch (arch) 73289857Sobrien { 73389857Sobrien case bfd_arch_sparc: 73489857Sobrien if (machine == 0 73589857Sobrien || machine == bfd_mach_sparc 73689857Sobrien || machine == bfd_mach_sparc_sparclite 73789857Sobrien || machine == bfd_mach_sparc_sparclite_le 73889857Sobrien || machine == bfd_mach_sparc_v9) 73989857Sobrien arch_flags = M_SPARC; 74089857Sobrien else if (machine == bfd_mach_sparc_sparclet) 74189857Sobrien arch_flags = M_SPARCLET; 74289857Sobrien break; 74333965Sjdp 74489857Sobrien case bfd_arch_m68k: 74589857Sobrien switch (machine) 74689857Sobrien { 74789857Sobrien case 0: arch_flags = M_68010; break; 74889857Sobrien case bfd_mach_m68000: arch_flags = M_UNKNOWN; *unknown = false; break; 74989857Sobrien case bfd_mach_m68010: arch_flags = M_68010; break; 75089857Sobrien case bfd_mach_m68020: arch_flags = M_68020; break; 75189857Sobrien default: arch_flags = M_UNKNOWN; break; 75289857Sobrien } 75389857Sobrien break; 75433965Sjdp 75589857Sobrien case bfd_arch_i386: 75689857Sobrien if (machine == 0) 75789857Sobrien arch_flags = M_386; 75889857Sobrien break; 75933965Sjdp 76089857Sobrien case bfd_arch_a29k: 76189857Sobrien if (machine == 0) 76289857Sobrien arch_flags = M_29K; 76389857Sobrien break; 76433965Sjdp 76589857Sobrien case bfd_arch_arm: 76689857Sobrien if (machine == 0) 76789857Sobrien arch_flags = M_ARM; 76889857Sobrien break; 76977298Sobrien 77089857Sobrien case bfd_arch_mips: 77189857Sobrien switch (machine) 77289857Sobrien { 77389857Sobrien case 0: 77489857Sobrien case bfd_mach_mips3000: 77589857Sobrien case bfd_mach_mips3900: 77689857Sobrien arch_flags = M_MIPS1; 77789857Sobrien break; 77889857Sobrien case bfd_mach_mips6000: 77989857Sobrien arch_flags = M_MIPS2; 78089857Sobrien break; 78189857Sobrien case bfd_mach_mips4000: 78289857Sobrien case bfd_mach_mips4010: 78389857Sobrien case bfd_mach_mips4100: 78489857Sobrien case bfd_mach_mips4300: 78589857Sobrien case bfd_mach_mips4400: 78689857Sobrien case bfd_mach_mips4600: 78789857Sobrien case bfd_mach_mips4650: 78889857Sobrien case bfd_mach_mips8000: 78989857Sobrien case bfd_mach_mips10000: 79089857Sobrien case bfd_mach_mips12000: 79189857Sobrien case bfd_mach_mips16: 79289857Sobrien case bfd_mach_mipsisa32: 79389857Sobrien case bfd_mach_mips5: 79489857Sobrien case bfd_mach_mipsisa64: 79589857Sobrien case bfd_mach_mips_sb1: 79689857Sobrien /* FIXME: These should be MIPS3, MIPS4, MIPS16, MIPS32, etc. */ 79789857Sobrien arch_flags = M_MIPS2; 79889857Sobrien break; 79989857Sobrien default: 80089857Sobrien arch_flags = M_UNKNOWN; 80189857Sobrien break; 80289857Sobrien } 80360484Sobrien break; 80489857Sobrien 80589857Sobrien case bfd_arch_ns32k: 80689857Sobrien switch (machine) 80789857Sobrien { 80889857Sobrien case 0: arch_flags = M_NS32532; break; 80989857Sobrien case 32032: arch_flags = M_NS32032; break; 81089857Sobrien case 32532: arch_flags = M_NS32532; break; 81189857Sobrien default: arch_flags = M_UNKNOWN; break; 81289857Sobrien } 81360484Sobrien break; 81489857Sobrien 81589857Sobrien case bfd_arch_vax: 81689857Sobrien *unknown = false; 81760484Sobrien break; 81889857Sobrien 81989857Sobrien case bfd_arch_cris: 82089857Sobrien if (machine == 0 || machine == 255) 82189857Sobrien arch_flags = M_CRIS; 82289857Sobrien break; 82389857Sobrien 82460484Sobrien default: 82560484Sobrien arch_flags = M_UNKNOWN; 82633965Sjdp } 82733965Sjdp 82833965Sjdp if (arch_flags != M_UNKNOWN) 82933965Sjdp *unknown = false; 83033965Sjdp 83133965Sjdp return arch_flags; 83233965Sjdp} 83333965Sjdp 83433965Sjdp/* 83533965SjdpFUNCTION 83633965Sjdp aout_@var{size}_set_arch_mach 83733965Sjdp 83833965SjdpSYNOPSIS 83933965Sjdp boolean aout_@var{size}_set_arch_mach, 84033965Sjdp (bfd *, 84133965Sjdp enum bfd_architecture arch, 84233965Sjdp unsigned long machine)); 84333965Sjdp 84433965SjdpDESCRIPTION 84533965Sjdp Set the architecture and the machine of the BFD @var{abfd} to the 84633965Sjdp values @var{arch} and @var{machine}. Verify that @var{abfd}'s format 84733965Sjdp can support the architecture required. 84833965Sjdp*/ 84933965Sjdp 85033965Sjdpboolean 85133965SjdpNAME(aout,set_arch_mach) (abfd, arch, machine) 85233965Sjdp bfd *abfd; 85333965Sjdp enum bfd_architecture arch; 85433965Sjdp unsigned long machine; 85533965Sjdp{ 85633965Sjdp if (! bfd_default_set_arch_mach (abfd, arch, machine)) 85733965Sjdp return false; 85833965Sjdp 85933965Sjdp if (arch != bfd_arch_unknown) 86033965Sjdp { 86133965Sjdp boolean unknown; 86233965Sjdp 86333965Sjdp NAME(aout,machine_type) (arch, machine, &unknown); 86433965Sjdp if (unknown) 86533965Sjdp return false; 86633965Sjdp } 86733965Sjdp 86833965Sjdp /* Determine the size of a relocation entry */ 86989857Sobrien switch (arch) 87089857Sobrien { 87189857Sobrien case bfd_arch_sparc: 87289857Sobrien case bfd_arch_a29k: 87389857Sobrien case bfd_arch_mips: 87489857Sobrien obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE; 87589857Sobrien break; 87689857Sobrien default: 87789857Sobrien obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 87889857Sobrien break; 87989857Sobrien } 88033965Sjdp 88189857Sobrien return (*aout_backend_info (abfd)->set_sizes) (abfd); 88233965Sjdp} 88333965Sjdp 88433965Sjdpstatic void 88533965Sjdpadjust_o_magic (abfd, execp) 88633965Sjdp bfd *abfd; 88733965Sjdp struct internal_exec *execp; 88833965Sjdp{ 88933965Sjdp file_ptr pos = adata (abfd).exec_bytes_size; 89033965Sjdp bfd_vma vma = 0; 89133965Sjdp int pad = 0; 89233965Sjdp 89333965Sjdp /* Text. */ 89489857Sobrien obj_textsec (abfd)->filepos = pos; 89589857Sobrien if (!obj_textsec (abfd)->user_set_vma) 89689857Sobrien obj_textsec (abfd)->vma = vma; 89733965Sjdp else 89889857Sobrien vma = obj_textsec (abfd)->vma; 89933965Sjdp 90089857Sobrien pos += obj_textsec (abfd)->_raw_size; 90189857Sobrien vma += obj_textsec (abfd)->_raw_size; 90233965Sjdp 90333965Sjdp /* Data. */ 90489857Sobrien if (!obj_datasec (abfd)->user_set_vma) 90533965Sjdp { 90633965Sjdp#if 0 /* ?? Does alignment in the file image really matter? */ 90789857Sobrien pad = align_power (vma, obj_datasec (abfd)->alignment_power) - vma; 90833965Sjdp#endif 90989857Sobrien obj_textsec (abfd)->_raw_size += pad; 91033965Sjdp pos += pad; 91133965Sjdp vma += pad; 91289857Sobrien obj_datasec (abfd)->vma = vma; 91333965Sjdp } 91433965Sjdp else 91589857Sobrien vma = obj_datasec (abfd)->vma; 91689857Sobrien obj_datasec (abfd)->filepos = pos; 91789857Sobrien pos += obj_datasec (abfd)->_raw_size; 91889857Sobrien vma += obj_datasec (abfd)->_raw_size; 91933965Sjdp 92033965Sjdp /* BSS. */ 92189857Sobrien if (!obj_bsssec (abfd)->user_set_vma) 92233965Sjdp { 92333965Sjdp#if 0 92489857Sobrien pad = align_power (vma, obj_bsssec (abfd)->alignment_power) - vma; 92533965Sjdp#endif 92689857Sobrien obj_datasec (abfd)->_raw_size += pad; 92733965Sjdp pos += pad; 92833965Sjdp vma += pad; 92989857Sobrien obj_bsssec (abfd)->vma = vma; 93033965Sjdp } 93133965Sjdp else 93233965Sjdp { 93389857Sobrien /* The VMA of the .bss section is set by the VMA of the 93433965Sjdp .data section plus the size of the .data section. We may 93533965Sjdp need to add padding bytes to make this true. */ 93633965Sjdp pad = obj_bsssec (abfd)->vma - vma; 93733965Sjdp if (pad > 0) 93833965Sjdp { 93933965Sjdp obj_datasec (abfd)->_raw_size += pad; 94033965Sjdp pos += pad; 94133965Sjdp } 94233965Sjdp } 94389857Sobrien obj_bsssec (abfd)->filepos = pos; 94433965Sjdp 94533965Sjdp /* Fix up the exec header. */ 94689857Sobrien execp->a_text = obj_textsec (abfd)->_raw_size; 94789857Sobrien execp->a_data = obj_datasec (abfd)->_raw_size; 94889857Sobrien execp->a_bss = obj_bsssec (abfd)->_raw_size; 94933965Sjdp N_SET_MAGIC (*execp, OMAGIC); 95033965Sjdp} 95133965Sjdp 95233965Sjdpstatic void 95333965Sjdpadjust_z_magic (abfd, execp) 95433965Sjdp bfd *abfd; 95533965Sjdp struct internal_exec *execp; 95633965Sjdp{ 95733965Sjdp bfd_size_type data_pad, text_pad; 95833965Sjdp file_ptr text_end; 95989857Sobrien const struct aout_backend_data *abdp; 96033965Sjdp int ztih; /* Nonzero if text includes exec header. */ 96177298Sobrien 96233965Sjdp abdp = aout_backend_info (abfd); 96333965Sjdp 96433965Sjdp /* Text. */ 96533965Sjdp ztih = (abdp != NULL 96633965Sjdp && (abdp->text_includes_header 96733965Sjdp || obj_aout_subformat (abfd) == q_magic_format)); 96889857Sobrien obj_textsec (abfd)->filepos = (ztih 96989857Sobrien ? adata (abfd).exec_bytes_size 97089857Sobrien : adata (abfd).zmagic_disk_block_size); 97189857Sobrien if (! obj_textsec (abfd)->user_set_vma) 97233965Sjdp { 97333965Sjdp /* ?? Do we really need to check for relocs here? */ 97489857Sobrien obj_textsec (abfd)->vma = ((abfd->flags & HAS_RELOC) 97589857Sobrien ? 0 97689857Sobrien : (ztih 97789857Sobrien ? (abdp->default_text_vma 97889857Sobrien + adata (abfd).exec_bytes_size) 97989857Sobrien : abdp->default_text_vma)); 98033965Sjdp text_pad = 0; 98133965Sjdp } 98233965Sjdp else 98333965Sjdp { 98433965Sjdp /* The .text section is being loaded at an unusual address. We 98533965Sjdp may need to pad it such that the .data section starts at a page 98633965Sjdp boundary. */ 98733965Sjdp if (ztih) 98833965Sjdp text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma) 98933965Sjdp & (adata (abfd).page_size - 1)); 99033965Sjdp else 99133965Sjdp text_pad = ((- obj_textsec (abfd)->vma) 99233965Sjdp & (adata (abfd).page_size - 1)); 99333965Sjdp } 99433965Sjdp 99533965Sjdp /* Find start of data. */ 99633965Sjdp if (ztih) 99733965Sjdp { 99833965Sjdp text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->_raw_size; 99933965Sjdp text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; 100033965Sjdp } 100133965Sjdp else 100233965Sjdp { 100333965Sjdp /* Note that if page_size == zmagic_disk_block_size, then 100433965Sjdp filepos == page_size, and this case is the same as the ztih 100533965Sjdp case. */ 100633965Sjdp text_end = obj_textsec (abfd)->_raw_size; 100733965Sjdp text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; 100833965Sjdp text_end += obj_textsec (abfd)->filepos; 100933965Sjdp } 101089857Sobrien obj_textsec (abfd)->_raw_size += text_pad; 101133965Sjdp text_end += text_pad; 101233965Sjdp 101333965Sjdp /* Data. */ 101489857Sobrien if (!obj_datasec (abfd)->user_set_vma) 101533965Sjdp { 101633965Sjdp bfd_vma vma; 101789857Sobrien vma = obj_textsec (abfd)->vma + obj_textsec (abfd)->_raw_size; 101889857Sobrien obj_datasec (abfd)->vma = BFD_ALIGN (vma, adata (abfd).segment_size); 101933965Sjdp } 102033965Sjdp if (abdp && abdp->zmagic_mapped_contiguous) 102133965Sjdp { 102289857Sobrien asection * text = obj_textsec (abfd); 102389857Sobrien asection * data = obj_datasec (abfd); 102489857Sobrien 102589857Sobrien text_pad = data->vma - (text->vma + text->_raw_size); 102689857Sobrien /* Only pad the text section if the data 102789857Sobrien section is going to be placed after it. */ 102889857Sobrien if (text_pad > 0) 102989857Sobrien text->_raw_size += text_pad; 103033965Sjdp } 103189857Sobrien obj_datasec (abfd)->filepos = (obj_textsec (abfd)->filepos 103289857Sobrien + obj_textsec (abfd)->_raw_size); 103377298Sobrien 103433965Sjdp /* Fix up exec header while we're at it. */ 103589857Sobrien execp->a_text = obj_textsec (abfd)->_raw_size; 103633965Sjdp if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) 103789857Sobrien execp->a_text += adata (abfd).exec_bytes_size; 103833965Sjdp if (obj_aout_subformat (abfd) == q_magic_format) 103933965Sjdp N_SET_MAGIC (*execp, QMAGIC); 104033965Sjdp else 104133965Sjdp N_SET_MAGIC (*execp, ZMAGIC); 104233965Sjdp 104333965Sjdp /* Spec says data section should be rounded up to page boundary. */ 104489857Sobrien obj_datasec (abfd)->_raw_size 104589857Sobrien = align_power (obj_datasec (abfd)->_raw_size, 104689857Sobrien obj_bsssec (abfd)->alignment_power); 104789857Sobrien execp->a_data = BFD_ALIGN (obj_datasec (abfd)->_raw_size, 104889857Sobrien adata (abfd).page_size); 104989857Sobrien data_pad = execp->a_data - obj_datasec (abfd)->_raw_size; 105033965Sjdp 105133965Sjdp /* BSS. */ 105289857Sobrien if (!obj_bsssec (abfd)->user_set_vma) 105389857Sobrien obj_bsssec (abfd)->vma = (obj_datasec (abfd)->vma 105489857Sobrien + obj_datasec (abfd)->_raw_size); 105533965Sjdp /* If the BSS immediately follows the data section and extra space 105633965Sjdp in the page is left after the data section, fudge data 105733965Sjdp in the header so that the bss section looks smaller by that 105833965Sjdp amount. We'll start the bss section there, and lie to the OS. 105933965Sjdp (Note that a linker script, as well as the above assignment, 106033965Sjdp could have explicitly set the BSS vma to immediately follow 106133965Sjdp the data section.) */ 106289857Sobrien if (align_power (obj_bsssec (abfd)->vma, obj_bsssec (abfd)->alignment_power) 106389857Sobrien == obj_datasec (abfd)->vma + obj_datasec (abfd)->_raw_size) 106489857Sobrien execp->a_bss = (data_pad > obj_bsssec (abfd)->_raw_size 106589857Sobrien ? 0 : obj_bsssec (abfd)->_raw_size - data_pad); 106633965Sjdp else 106789857Sobrien execp->a_bss = obj_bsssec (abfd)->_raw_size; 106833965Sjdp} 106933965Sjdp 107033965Sjdpstatic void 107133965Sjdpadjust_n_magic (abfd, execp) 107233965Sjdp bfd *abfd; 107333965Sjdp struct internal_exec *execp; 107433965Sjdp{ 107589857Sobrien file_ptr pos = adata (abfd).exec_bytes_size; 107633965Sjdp bfd_vma vma = 0; 107733965Sjdp int pad; 107877298Sobrien 107933965Sjdp /* Text. */ 108089857Sobrien obj_textsec (abfd)->filepos = pos; 108189857Sobrien if (!obj_textsec (abfd)->user_set_vma) 108289857Sobrien obj_textsec (abfd)->vma = vma; 108333965Sjdp else 108489857Sobrien vma = obj_textsec (abfd)->vma; 108589857Sobrien pos += obj_textsec (abfd)->_raw_size; 108689857Sobrien vma += obj_textsec (abfd)->_raw_size; 108733965Sjdp 108833965Sjdp /* Data. */ 108989857Sobrien obj_datasec (abfd)->filepos = pos; 109089857Sobrien if (!obj_datasec (abfd)->user_set_vma) 109189857Sobrien obj_datasec (abfd)->vma = BFD_ALIGN (vma, adata (abfd).segment_size); 109289857Sobrien vma = obj_datasec (abfd)->vma; 109377298Sobrien 109433965Sjdp /* Since BSS follows data immediately, see if it needs alignment. */ 109589857Sobrien vma += obj_datasec (abfd)->_raw_size; 109689857Sobrien pad = align_power (vma, obj_bsssec (abfd)->alignment_power) - vma; 109789857Sobrien obj_datasec (abfd)->_raw_size += pad; 109889857Sobrien pos += obj_datasec (abfd)->_raw_size; 109933965Sjdp 110033965Sjdp /* BSS. */ 110189857Sobrien if (!obj_bsssec (abfd)->user_set_vma) 110289857Sobrien obj_bsssec (abfd)->vma = vma; 110333965Sjdp else 110489857Sobrien vma = obj_bsssec (abfd)->vma; 110533965Sjdp 110633965Sjdp /* Fix up exec header. */ 110789857Sobrien execp->a_text = obj_textsec (abfd)->_raw_size; 110889857Sobrien execp->a_data = obj_datasec (abfd)->_raw_size; 110989857Sobrien execp->a_bss = obj_bsssec (abfd)->_raw_size; 111033965Sjdp N_SET_MAGIC (*execp, NMAGIC); 111133965Sjdp} 111233965Sjdp 111333965Sjdpboolean 111433965SjdpNAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end) 111533965Sjdp bfd *abfd; 111633965Sjdp bfd_size_type *text_size; 111760484Sobrien file_ptr *text_end ATTRIBUTE_UNUSED; 111833965Sjdp{ 111933965Sjdp struct internal_exec *execp = exec_hdr (abfd); 112033965Sjdp 112133965Sjdp if (! NAME(aout,make_sections) (abfd)) 112233965Sjdp return false; 112333965Sjdp 112489857Sobrien if (adata (abfd).magic != undecided_magic) 112533965Sjdp return true; 112633965Sjdp 112789857Sobrien obj_textsec (abfd)->_raw_size = 112889857Sobrien align_power (obj_textsec (abfd)->_raw_size, 112989857Sobrien obj_textsec (abfd)->alignment_power); 113033965Sjdp 113133965Sjdp *text_size = obj_textsec (abfd)->_raw_size; 113233965Sjdp /* Rule (heuristic) for when to pad to a new page. Note that there 113333965Sjdp are (at least) two ways demand-paged (ZMAGIC) files have been 113433965Sjdp handled. Most Berkeley-based systems start the text segment at 113533965Sjdp (TARGET_PAGE_SIZE). However, newer versions of SUNOS start the text 113633965Sjdp segment right after the exec header; the latter is counted in the 113733965Sjdp text segment size, and is paged in by the kernel with the rest of 113877298Sobrien the text. */ 113933965Sjdp 114033965Sjdp /* This perhaps isn't the right way to do this, but made it simpler for me 114133965Sjdp to understand enough to implement it. Better would probably be to go 114233965Sjdp right from BFD flags to alignment/positioning characteristics. But the 114333965Sjdp old code was sloppy enough about handling the flags, and had enough 114433965Sjdp other magic, that it was a little hard for me to understand. I think 114533965Sjdp I understand it better now, but I haven't time to do the cleanup this 114633965Sjdp minute. */ 114733965Sjdp 114833965Sjdp if (abfd->flags & D_PAGED) 114933965Sjdp /* Whether or not WP_TEXT is set -- let D_PAGED override. */ 115089857Sobrien adata (abfd).magic = z_magic; 115133965Sjdp else if (abfd->flags & WP_TEXT) 115289857Sobrien adata (abfd).magic = n_magic; 115333965Sjdp else 115489857Sobrien adata (abfd).magic = o_magic; 115533965Sjdp 115633965Sjdp#ifdef BFD_AOUT_DEBUG /* requires gcc2 */ 115733965Sjdp#if __GNUC__ >= 2 115833965Sjdp fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n", 115933965Sjdp ({ char *str; 116089857Sobrien switch (adata (abfd).magic) 116189857Sobrien { 116289857Sobrien case n_magic: str = "NMAGIC"; break; 116389857Sobrien case o_magic: str = "OMAGIC"; break; 116489857Sobrien case z_magic: str = "ZMAGIC"; break; 116589857Sobrien default: abort (); 116689857Sobrien } 116733965Sjdp str; 116833965Sjdp }), 116989857Sobrien obj_textsec (abfd)->vma, obj_textsec (abfd)->_raw_size, 117089857Sobrien obj_textsec (abfd)->alignment_power, 117189857Sobrien obj_datasec (abfd)->vma, obj_datasec (abfd)->_raw_size, 117289857Sobrien obj_datasec (abfd)->alignment_power, 117389857Sobrien obj_bsssec (abfd)->vma, obj_bsssec (abfd)->_raw_size, 117489857Sobrien obj_bsssec (abfd)->alignment_power); 117533965Sjdp#endif 117633965Sjdp#endif 117733965Sjdp 117889857Sobrien switch (adata (abfd).magic) 117933965Sjdp { 118033965Sjdp case o_magic: 118133965Sjdp adjust_o_magic (abfd, execp); 118233965Sjdp break; 118333965Sjdp case z_magic: 118433965Sjdp adjust_z_magic (abfd, execp); 118533965Sjdp break; 118633965Sjdp case n_magic: 118733965Sjdp adjust_n_magic (abfd, execp); 118833965Sjdp break; 118933965Sjdp default: 119033965Sjdp abort (); 119133965Sjdp } 119233965Sjdp 119333965Sjdp#ifdef BFD_AOUT_DEBUG 119433965Sjdp fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n", 119589857Sobrien obj_textsec (abfd)->vma, obj_textsec (abfd)->_raw_size, 119689857Sobrien obj_textsec (abfd)->filepos, 119789857Sobrien obj_datasec (abfd)->vma, obj_datasec (abfd)->_raw_size, 119889857Sobrien obj_datasec (abfd)->filepos, 119989857Sobrien obj_bsssec (abfd)->vma, obj_bsssec (abfd)->_raw_size); 120033965Sjdp#endif 120133965Sjdp 120233965Sjdp return true; 120333965Sjdp} 120433965Sjdp 120533965Sjdp/* 120633965SjdpFUNCTION 120733965Sjdp aout_@var{size}_new_section_hook 120833965Sjdp 120933965SjdpSYNOPSIS 121033965Sjdp boolean aout_@var{size}_new_section_hook, 121133965Sjdp (bfd *abfd, 121233965Sjdp asection *newsect)); 121333965Sjdp 121433965SjdpDESCRIPTION 121533965Sjdp Called by the BFD in response to a @code{bfd_make_section} 121633965Sjdp request. 121733965Sjdp*/ 121833965Sjdpboolean 121933965SjdpNAME(aout,new_section_hook) (abfd, newsect) 122033965Sjdp bfd *abfd; 122133965Sjdp asection *newsect; 122233965Sjdp{ 122333965Sjdp /* align to double at least */ 122489857Sobrien newsect->alignment_power = bfd_get_arch_info (abfd)->section_align_power; 122533965Sjdp 122633965Sjdp if (bfd_get_format (abfd) == bfd_object) 122733965Sjdp { 122889857Sobrien if (obj_textsec (abfd) == NULL && !strcmp (newsect->name, ".text")) 122989857Sobrien { 123089857Sobrien obj_textsec (abfd)= newsect; 123133965Sjdp newsect->target_index = N_TEXT; 123233965Sjdp return true; 123333965Sjdp } 123433965Sjdp 123589857Sobrien if (obj_datasec (abfd) == NULL && !strcmp (newsect->name, ".data")) 123689857Sobrien { 123789857Sobrien obj_datasec (abfd) = newsect; 123833965Sjdp newsect->target_index = N_DATA; 123933965Sjdp return true; 124033965Sjdp } 124133965Sjdp 124289857Sobrien if (obj_bsssec (abfd) == NULL && !strcmp (newsect->name, ".bss")) 124389857Sobrien { 124489857Sobrien obj_bsssec (abfd) = newsect; 124533965Sjdp newsect->target_index = N_BSS; 124633965Sjdp return true; 124733965Sjdp } 124833965Sjdp 124933965Sjdp } 125033965Sjdp 125133965Sjdp /* We allow more than three sections internally */ 125233965Sjdp return true; 125333965Sjdp} 125433965Sjdp 125533965Sjdpboolean 125633965SjdpNAME(aout,set_section_contents) (abfd, section, location, offset, count) 125733965Sjdp bfd *abfd; 125833965Sjdp sec_ptr section; 125933965Sjdp PTR location; 126033965Sjdp file_ptr offset; 126133965Sjdp bfd_size_type count; 126233965Sjdp{ 126333965Sjdp file_ptr text_end; 126433965Sjdp bfd_size_type text_size; 126533965Sjdp 126633965Sjdp if (! abfd->output_has_begun) 126733965Sjdp { 126833965Sjdp if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) 126933965Sjdp return false; 127033965Sjdp } 127133965Sjdp 127233965Sjdp if (section == obj_bsssec (abfd)) 127333965Sjdp { 127433965Sjdp bfd_set_error (bfd_error_no_contents); 127533965Sjdp return false; 127633965Sjdp } 127733965Sjdp 127833965Sjdp if (section != obj_textsec (abfd) 127933965Sjdp && section != obj_datasec (abfd)) 128033965Sjdp { 128133965Sjdp (*_bfd_error_handler) 128260484Sobrien (_("%s: can not represent section `%s' in a.out object file format"), 128333965Sjdp bfd_get_filename (abfd), bfd_get_section_name (abfd, section)); 128433965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 128533965Sjdp return false; 128633965Sjdp } 128733965Sjdp 128833965Sjdp if (count != 0) 128933965Sjdp { 129033965Sjdp if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 129189857Sobrien || bfd_bwrite (location, count, abfd) != count) 129233965Sjdp return false; 129333965Sjdp } 129433965Sjdp 129533965Sjdp return true; 129633965Sjdp} 129733965Sjdp 129833965Sjdp/* Read the external symbols from an a.out file. */ 129933965Sjdp 130033965Sjdpstatic boolean 130133965Sjdpaout_get_external_symbols (abfd) 130233965Sjdp bfd *abfd; 130333965Sjdp{ 130433965Sjdp if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL) 130533965Sjdp { 130633965Sjdp bfd_size_type count; 130733965Sjdp struct external_nlist *syms; 130889857Sobrien bfd_size_type amt; 130933965Sjdp 131033965Sjdp count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE; 131133965Sjdp 131233965Sjdp#ifdef USE_MMAP 1313104834Sobrien if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd), 1314104834Sobrien exec_hdr (abfd)->a_syms, 1315104834Sobrien &obj_aout_sym_window (abfd), true)) 131633965Sjdp return false; 131733965Sjdp syms = (struct external_nlist *) obj_aout_sym_window (abfd).data; 131833965Sjdp#else 131933965Sjdp /* We allocate using malloc to make the values easy to free 132033965Sjdp later on. If we put them on the objalloc it might not be 132133965Sjdp possible to free them. */ 132233965Sjdp syms = ((struct external_nlist *) 132389857Sobrien bfd_malloc (count * EXTERNAL_NLIST_SIZE)); 132433965Sjdp if (syms == (struct external_nlist *) NULL && count != 0) 132533965Sjdp return false; 132633965Sjdp 132789857Sobrien amt = exec_hdr (abfd)->a_syms; 132833965Sjdp if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 132989857Sobrien || bfd_bread (syms, amt, abfd) != amt) 133033965Sjdp { 133133965Sjdp free (syms); 133233965Sjdp return false; 133333965Sjdp } 133433965Sjdp#endif 133533965Sjdp 133633965Sjdp obj_aout_external_syms (abfd) = syms; 133733965Sjdp obj_aout_external_sym_count (abfd) = count; 133833965Sjdp } 133977298Sobrien 134033965Sjdp if (obj_aout_external_strings (abfd) == NULL 134133965Sjdp && exec_hdr (abfd)->a_syms != 0) 134233965Sjdp { 134333965Sjdp unsigned char string_chars[BYTES_IN_WORD]; 134433965Sjdp bfd_size_type stringsize; 134533965Sjdp char *strings; 134689857Sobrien bfd_size_type amt = BYTES_IN_WORD; 134733965Sjdp 134833965Sjdp /* Get the size of the strings. */ 134933965Sjdp if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 135089857Sobrien || bfd_bread ((PTR) string_chars, amt, abfd) != amt) 135133965Sjdp return false; 135233965Sjdp stringsize = GET_WORD (abfd, string_chars); 135333965Sjdp 135433965Sjdp#ifdef USE_MMAP 1355104834Sobrien if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize, 1356104834Sobrien &obj_aout_string_window (abfd), true)) 135733965Sjdp return false; 135833965Sjdp strings = (char *) obj_aout_string_window (abfd).data; 135933965Sjdp#else 136089857Sobrien strings = (char *) bfd_malloc (stringsize + 1); 136133965Sjdp if (strings == NULL) 136233965Sjdp return false; 136333965Sjdp 136433965Sjdp /* Skip space for the string count in the buffer for convenience 136533965Sjdp when using indexes. */ 136689857Sobrien amt = stringsize - BYTES_IN_WORD; 136789857Sobrien if (bfd_bread (strings + BYTES_IN_WORD, amt, abfd) != amt) 136833965Sjdp { 136933965Sjdp free (strings); 137033965Sjdp return false; 137133965Sjdp } 137233965Sjdp#endif 137333965Sjdp 137433965Sjdp /* Ensure that a zero index yields an empty string. */ 137533965Sjdp strings[0] = '\0'; 137633965Sjdp 137733965Sjdp strings[stringsize - 1] = 0; 137833965Sjdp 137933965Sjdp obj_aout_external_strings (abfd) = strings; 138033965Sjdp obj_aout_external_string_size (abfd) = stringsize; 138133965Sjdp } 138233965Sjdp 138333965Sjdp return true; 138433965Sjdp} 138533965Sjdp 138633965Sjdp/* Translate an a.out symbol into a BFD symbol. The desc, other, type 138733965Sjdp and symbol->value fields of CACHE_PTR will be set from the a.out 138833965Sjdp nlist structure. This function is responsible for setting 138933965Sjdp symbol->flags and symbol->section, and adjusting symbol->value. */ 139033965Sjdp 139133965Sjdpstatic boolean 139233965Sjdptranslate_from_native_sym_flags (abfd, cache_ptr) 139333965Sjdp bfd *abfd; 139433965Sjdp aout_symbol_type *cache_ptr; 139533965Sjdp{ 139633965Sjdp flagword visible; 139733965Sjdp 139833965Sjdp if ((cache_ptr->type & N_STAB) != 0 139933965Sjdp || cache_ptr->type == N_FN) 140033965Sjdp { 140133965Sjdp asection *sec; 140233965Sjdp 140333965Sjdp /* This is a debugging symbol. */ 140433965Sjdp 140533965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING; 140633965Sjdp 140733965Sjdp /* Work out the symbol section. */ 140833965Sjdp switch (cache_ptr->type & N_TYPE) 140933965Sjdp { 141033965Sjdp case N_TEXT: 141133965Sjdp case N_FN: 141233965Sjdp sec = obj_textsec (abfd); 141333965Sjdp break; 141433965Sjdp case N_DATA: 141533965Sjdp sec = obj_datasec (abfd); 141633965Sjdp break; 141733965Sjdp case N_BSS: 141833965Sjdp sec = obj_bsssec (abfd); 141933965Sjdp break; 142033965Sjdp default: 142133965Sjdp case N_ABS: 142233965Sjdp sec = bfd_abs_section_ptr; 142333965Sjdp break; 142433965Sjdp } 142533965Sjdp 142633965Sjdp cache_ptr->symbol.section = sec; 142733965Sjdp cache_ptr->symbol.value -= sec->vma; 142833965Sjdp 142933965Sjdp return true; 143033965Sjdp } 143133965Sjdp 143233965Sjdp /* Get the default visibility. This does not apply to all types, so 143333965Sjdp we just hold it in a local variable to use if wanted. */ 143433965Sjdp if ((cache_ptr->type & N_EXT) == 0) 143533965Sjdp visible = BSF_LOCAL; 143633965Sjdp else 143733965Sjdp visible = BSF_GLOBAL; 143833965Sjdp 143933965Sjdp switch (cache_ptr->type) 144033965Sjdp { 144133965Sjdp default: 144233965Sjdp case N_ABS: case N_ABS | N_EXT: 144333965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 144433965Sjdp cache_ptr->symbol.flags = visible; 144533965Sjdp break; 144633965Sjdp 144733965Sjdp case N_UNDF | N_EXT: 144833965Sjdp if (cache_ptr->symbol.value != 0) 144933965Sjdp { 145033965Sjdp /* This is a common symbol. */ 145133965Sjdp cache_ptr->symbol.flags = BSF_GLOBAL; 145233965Sjdp cache_ptr->symbol.section = bfd_com_section_ptr; 145333965Sjdp } 145433965Sjdp else 145533965Sjdp { 145633965Sjdp cache_ptr->symbol.flags = 0; 145733965Sjdp cache_ptr->symbol.section = bfd_und_section_ptr; 145833965Sjdp } 145933965Sjdp break; 146033965Sjdp 146133965Sjdp case N_TEXT: case N_TEXT | N_EXT: 146233965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 146333965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 146433965Sjdp cache_ptr->symbol.flags = visible; 146533965Sjdp break; 146633965Sjdp 146733965Sjdp /* N_SETV symbols used to represent set vectors placed in the 146833965Sjdp data section. They are no longer generated. Theoretically, 146933965Sjdp it was possible to extract the entries and combine them with 147033965Sjdp new ones, although I don't know if that was ever actually 147133965Sjdp done. Unless that feature is restored, treat them as data 147233965Sjdp symbols. */ 147333965Sjdp case N_SETV: case N_SETV | N_EXT: 147433965Sjdp case N_DATA: case N_DATA | N_EXT: 147533965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 147633965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 147733965Sjdp cache_ptr->symbol.flags = visible; 147833965Sjdp break; 147933965Sjdp 148033965Sjdp case N_BSS: case N_BSS | N_EXT: 148133965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 148233965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 148333965Sjdp cache_ptr->symbol.flags = visible; 148433965Sjdp break; 148533965Sjdp 148633965Sjdp case N_SETA: case N_SETA | N_EXT: 148733965Sjdp case N_SETT: case N_SETT | N_EXT: 148833965Sjdp case N_SETD: case N_SETD | N_EXT: 148933965Sjdp case N_SETB: case N_SETB | N_EXT: 149033965Sjdp { 149133965Sjdp /* This code is no longer needed. It used to be used to make 149233965Sjdp the linker handle set symbols, but they are now handled in 149333965Sjdp the add_symbols routine instead. */ 149433965Sjdp#if 0 149533965Sjdp asection *section; 149633965Sjdp arelent_chain *reloc; 149733965Sjdp asection *into_section; 149889857Sobrien bfd_size_type amt; 149933965Sjdp 150033965Sjdp /* This is a set symbol. The name of the symbol is the name 150133965Sjdp of the set (e.g., __CTOR_LIST__). The value of the symbol 150233965Sjdp is the value to add to the set. We create a section with 150333965Sjdp the same name as the symbol, and add a reloc to insert the 150433965Sjdp appropriate value into the section. 150533965Sjdp 150633965Sjdp This action is actually obsolete; it used to make the 150733965Sjdp linker do the right thing, but the linker no longer uses 150833965Sjdp this function. */ 150933965Sjdp 151033965Sjdp section = bfd_get_section_by_name (abfd, cache_ptr->symbol.name); 151133965Sjdp if (section == NULL) 151233965Sjdp { 151333965Sjdp char *copy; 151433965Sjdp 151589857Sobrien amt = strlen (cache_ptr->symbol.name) + 1; 151689857Sobrien copy = bfd_alloc (abfd, amt); 151733965Sjdp if (copy == NULL) 151833965Sjdp return false; 151933965Sjdp 152033965Sjdp strcpy (copy, cache_ptr->symbol.name); 152133965Sjdp section = bfd_make_section (abfd, copy); 152233965Sjdp if (section == NULL) 152333965Sjdp return false; 152433965Sjdp } 152533965Sjdp 152689857Sobrien amt = sizeof (arelent_chain); 152789857Sobrien reloc = (arelent_chain *) bfd_alloc (abfd, amt); 152833965Sjdp if (reloc == NULL) 152933965Sjdp return false; 153033965Sjdp 153133965Sjdp /* Build a relocation entry for the constructor. */ 153233965Sjdp switch (cache_ptr->type & N_TYPE) 153333965Sjdp { 153433965Sjdp case N_SETA: 153533965Sjdp into_section = bfd_abs_section_ptr; 153633965Sjdp cache_ptr->type = N_ABS; 153733965Sjdp break; 153833965Sjdp case N_SETT: 153933965Sjdp into_section = obj_textsec (abfd); 154033965Sjdp cache_ptr->type = N_TEXT; 154133965Sjdp break; 154233965Sjdp case N_SETD: 154333965Sjdp into_section = obj_datasec (abfd); 154433965Sjdp cache_ptr->type = N_DATA; 154533965Sjdp break; 154633965Sjdp case N_SETB: 154733965Sjdp into_section = obj_bsssec (abfd); 154833965Sjdp cache_ptr->type = N_BSS; 154933965Sjdp break; 155033965Sjdp } 155133965Sjdp 155233965Sjdp /* Build a relocation pointing into the constructor section 155333965Sjdp pointing at the symbol in the set vector specified. */ 155433965Sjdp reloc->relent.addend = cache_ptr->symbol.value; 155533965Sjdp cache_ptr->symbol.section = into_section; 155633965Sjdp reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr; 155733965Sjdp 155833965Sjdp /* We modify the symbol to belong to a section depending upon 155933965Sjdp the name of the symbol, and add to the size of the section 156033965Sjdp to contain a pointer to the symbol. Build a reloc entry to 156133965Sjdp relocate to this symbol attached to this section. */ 156233965Sjdp section->flags = SEC_CONSTRUCTOR | SEC_RELOC; 156333965Sjdp 156433965Sjdp section->reloc_count++; 156533965Sjdp section->alignment_power = 2; 156633965Sjdp 156733965Sjdp reloc->next = section->constructor_chain; 156833965Sjdp section->constructor_chain = reloc; 156933965Sjdp reloc->relent.address = section->_raw_size; 157033965Sjdp section->_raw_size += BYTES_IN_WORD; 157133965Sjdp 157289857Sobrien reloc->relent.howto = CTOR_TABLE_RELOC_HOWTO (abfd); 157333965Sjdp 157433965Sjdp#endif /* 0 */ 157533965Sjdp 157633965Sjdp switch (cache_ptr->type & N_TYPE) 157733965Sjdp { 157833965Sjdp case N_SETA: 157933965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 158033965Sjdp break; 158133965Sjdp case N_SETT: 158233965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 158333965Sjdp break; 158433965Sjdp case N_SETD: 158533965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 158633965Sjdp break; 158733965Sjdp case N_SETB: 158833965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 158933965Sjdp break; 159033965Sjdp } 159133965Sjdp 159233965Sjdp cache_ptr->symbol.flags |= BSF_CONSTRUCTOR; 159333965Sjdp } 159433965Sjdp break; 159533965Sjdp 159633965Sjdp case N_WARNING: 159733965Sjdp /* This symbol is the text of a warning message. The next 159833965Sjdp symbol is the symbol to associate the warning with. If a 159933965Sjdp reference is made to that symbol, a warning is issued. */ 160033965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING; 160133965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 160233965Sjdp break; 160333965Sjdp 160433965Sjdp case N_INDR: case N_INDR | N_EXT: 160533965Sjdp /* An indirect symbol. This consists of two symbols in a row. 160633965Sjdp The first symbol is the name of the indirection. The second 160733965Sjdp symbol is the name of the target. A reference to the first 160833965Sjdp symbol becomes a reference to the second. */ 160933965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible; 161033965Sjdp cache_ptr->symbol.section = bfd_ind_section_ptr; 161133965Sjdp break; 161233965Sjdp 161333965Sjdp case N_WEAKU: 161433965Sjdp cache_ptr->symbol.section = bfd_und_section_ptr; 161533965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 161633965Sjdp break; 161733965Sjdp 161833965Sjdp case N_WEAKA: 161933965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 162033965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 162133965Sjdp break; 162233965Sjdp 162333965Sjdp case N_WEAKT: 162433965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 162533965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 162633965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 162733965Sjdp break; 162833965Sjdp 162933965Sjdp case N_WEAKD: 163033965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 163133965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 163233965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 163333965Sjdp break; 163433965Sjdp 163533965Sjdp case N_WEAKB: 163633965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 163733965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 163833965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 163933965Sjdp break; 164033965Sjdp } 164133965Sjdp 164233965Sjdp return true; 164333965Sjdp} 164433965Sjdp 164533965Sjdp/* Set the fields of SYM_POINTER according to CACHE_PTR. */ 164633965Sjdp 164733965Sjdpstatic boolean 164833965Sjdptranslate_to_native_sym_flags (abfd, cache_ptr, sym_pointer) 164933965Sjdp bfd *abfd; 165033965Sjdp asymbol *cache_ptr; 165133965Sjdp struct external_nlist *sym_pointer; 165233965Sjdp{ 165333965Sjdp bfd_vma value = cache_ptr->value; 165433965Sjdp asection *sec; 165533965Sjdp bfd_vma off; 165633965Sjdp 165733965Sjdp /* Mask out any existing type bits in case copying from one section 165833965Sjdp to another. */ 165933965Sjdp sym_pointer->e_type[0] &= ~N_TYPE; 166033965Sjdp 166133965Sjdp sec = bfd_get_section (cache_ptr); 166233965Sjdp off = 0; 166333965Sjdp 166433965Sjdp if (sec == NULL) 166533965Sjdp { 166633965Sjdp /* This case occurs, e.g., for the *DEBUG* section of a COFF 166733965Sjdp file. */ 166833965Sjdp (*_bfd_error_handler) 166960484Sobrien (_("%s: can not represent section for symbol `%s' in a.out object file format"), 167077298Sobrien bfd_get_filename (abfd), 167160484Sobrien cache_ptr->name != NULL ? cache_ptr->name : _("*unknown*")); 167233965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 167333965Sjdp return false; 167433965Sjdp } 167533965Sjdp 167633965Sjdp if (sec->output_section != NULL) 167733965Sjdp { 167833965Sjdp off = sec->output_offset; 167933965Sjdp sec = sec->output_section; 168033965Sjdp } 168133965Sjdp 168233965Sjdp if (bfd_is_abs_section (sec)) 168333965Sjdp sym_pointer->e_type[0] |= N_ABS; 168433965Sjdp else if (sec == obj_textsec (abfd)) 168533965Sjdp sym_pointer->e_type[0] |= N_TEXT; 168633965Sjdp else if (sec == obj_datasec (abfd)) 168733965Sjdp sym_pointer->e_type[0] |= N_DATA; 168833965Sjdp else if (sec == obj_bsssec (abfd)) 168933965Sjdp sym_pointer->e_type[0] |= N_BSS; 169033965Sjdp else if (bfd_is_und_section (sec)) 169133965Sjdp sym_pointer->e_type[0] = N_UNDF | N_EXT; 169233965Sjdp else if (bfd_is_ind_section (sec)) 169333965Sjdp sym_pointer->e_type[0] = N_INDR; 169433965Sjdp else if (bfd_is_com_section (sec)) 169533965Sjdp sym_pointer->e_type[0] = N_UNDF | N_EXT; 169633965Sjdp else 169733965Sjdp { 169833965Sjdp (*_bfd_error_handler) 169960484Sobrien (_("%s: can not represent section `%s' in a.out object file format"), 170033965Sjdp bfd_get_filename (abfd), bfd_get_section_name (abfd, sec)); 170133965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 170233965Sjdp return false; 170333965Sjdp } 170433965Sjdp 170533965Sjdp /* Turn the symbol from section relative to absolute again */ 170633965Sjdp value += sec->vma + off; 170733965Sjdp 170833965Sjdp if ((cache_ptr->flags & BSF_WARNING) != 0) 170933965Sjdp sym_pointer->e_type[0] = N_WARNING; 171033965Sjdp 171133965Sjdp if ((cache_ptr->flags & BSF_DEBUGGING) != 0) 171233965Sjdp sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type; 171333965Sjdp else if ((cache_ptr->flags & BSF_GLOBAL) != 0) 171433965Sjdp sym_pointer->e_type[0] |= N_EXT; 171577298Sobrien else if ((cache_ptr->flags & BSF_LOCAL) != 0) 171677298Sobrien sym_pointer->e_type[0] &= ~N_EXT; 171733965Sjdp 171833965Sjdp if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0) 171933965Sjdp { 172033965Sjdp int type = ((aout_symbol_type *) cache_ptr)->type; 172133965Sjdp switch (type) 172233965Sjdp { 172333965Sjdp case N_ABS: type = N_SETA; break; 172433965Sjdp case N_TEXT: type = N_SETT; break; 172533965Sjdp case N_DATA: type = N_SETD; break; 172633965Sjdp case N_BSS: type = N_SETB; break; 172733965Sjdp } 172833965Sjdp sym_pointer->e_type[0] = type; 172933965Sjdp } 173033965Sjdp 173133965Sjdp if ((cache_ptr->flags & BSF_WEAK) != 0) 173233965Sjdp { 173333965Sjdp int type; 173433965Sjdp 173533965Sjdp switch (sym_pointer->e_type[0] & N_TYPE) 173633965Sjdp { 173733965Sjdp default: 173833965Sjdp case N_ABS: type = N_WEAKA; break; 173933965Sjdp case N_TEXT: type = N_WEAKT; break; 174033965Sjdp case N_DATA: type = N_WEAKD; break; 174133965Sjdp case N_BSS: type = N_WEAKB; break; 174233965Sjdp case N_UNDF: type = N_WEAKU; break; 174333965Sjdp } 174433965Sjdp sym_pointer->e_type[0] = type; 174533965Sjdp } 174633965Sjdp 174789857Sobrien PUT_WORD (abfd, value, sym_pointer->e_value); 174833965Sjdp 174933965Sjdp return true; 175033965Sjdp} 175133965Sjdp 175277298Sobrien/* Native-level interface to symbols. */ 175333965Sjdp 175433965Sjdpasymbol * 175533965SjdpNAME(aout,make_empty_symbol) (abfd) 175633965Sjdp bfd *abfd; 175733965Sjdp{ 175889857Sobrien bfd_size_type amt = sizeof (aout_symbol_type); 175989857Sobrien aout_symbol_type *new = (aout_symbol_type *) bfd_zalloc (abfd, amt); 176033965Sjdp if (!new) 176133965Sjdp return NULL; 176233965Sjdp new->symbol.the_bfd = abfd; 176333965Sjdp 176433965Sjdp return &new->symbol; 176533965Sjdp} 176633965Sjdp 176733965Sjdp/* Translate a set of internal symbols into external symbols. */ 176833965Sjdp 176933965Sjdpboolean 177033965SjdpNAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic) 177133965Sjdp bfd *abfd; 177233965Sjdp aout_symbol_type *in; 177333965Sjdp struct external_nlist *ext; 177433965Sjdp bfd_size_type count; 177533965Sjdp char *str; 177633965Sjdp bfd_size_type strsize; 177733965Sjdp boolean dynamic; 177833965Sjdp{ 177933965Sjdp struct external_nlist *ext_end; 178033965Sjdp 178133965Sjdp ext_end = ext + count; 178233965Sjdp for (; ext < ext_end; ext++, in++) 178333965Sjdp { 178433965Sjdp bfd_vma x; 178533965Sjdp 178633965Sjdp x = GET_WORD (abfd, ext->e_strx); 178733965Sjdp in->symbol.the_bfd = abfd; 178833965Sjdp 178933965Sjdp /* For the normal symbols, the zero index points at the number 179033965Sjdp of bytes in the string table but is to be interpreted as the 179133965Sjdp null string. For the dynamic symbols, the number of bytes in 179233965Sjdp the string table is stored in the __DYNAMIC structure and the 179333965Sjdp zero index points at an actual string. */ 179433965Sjdp if (x == 0 && ! dynamic) 179533965Sjdp in->symbol.name = ""; 179633965Sjdp else if (x < strsize) 179733965Sjdp in->symbol.name = str + x; 179833965Sjdp else 179933965Sjdp return false; 180033965Sjdp 180133965Sjdp in->symbol.value = GET_SWORD (abfd, ext->e_value); 180289857Sobrien in->desc = H_GET_16 (abfd, ext->e_desc); 180389857Sobrien in->other = H_GET_8 (abfd, ext->e_other); 180489857Sobrien in->type = H_GET_8 (abfd, ext->e_type); 180533965Sjdp in->symbol.udata.p = NULL; 180633965Sjdp 180733965Sjdp if (! translate_from_native_sym_flags (abfd, in)) 180833965Sjdp return false; 180933965Sjdp 181033965Sjdp if (dynamic) 181133965Sjdp in->symbol.flags |= BSF_DYNAMIC; 181233965Sjdp } 181333965Sjdp 181433965Sjdp return true; 181533965Sjdp} 181633965Sjdp 181733965Sjdp/* We read the symbols into a buffer, which is discarded when this 181833965Sjdp function exits. We read the strings into a buffer large enough to 181977298Sobrien hold them all plus all the cached symbol entries. */ 182033965Sjdp 182133965Sjdpboolean 182233965SjdpNAME(aout,slurp_symbol_table) (abfd) 182333965Sjdp bfd *abfd; 182433965Sjdp{ 182533965Sjdp struct external_nlist *old_external_syms; 182633965Sjdp aout_symbol_type *cached; 182789857Sobrien bfd_size_type cached_size; 182833965Sjdp 182933965Sjdp /* If there's no work to be done, don't do any */ 183033965Sjdp if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL) 183133965Sjdp return true; 183233965Sjdp 183333965Sjdp old_external_syms = obj_aout_external_syms (abfd); 183433965Sjdp 183533965Sjdp if (! aout_get_external_symbols (abfd)) 183633965Sjdp return false; 183733965Sjdp 183889857Sobrien cached_size = obj_aout_external_sym_count (abfd); 183989857Sobrien cached_size *= sizeof (aout_symbol_type); 1840104834Sobrien cached = (aout_symbol_type *) bfd_zmalloc (cached_size); 184133965Sjdp if (cached == NULL && cached_size != 0) 184233965Sjdp return false; 184333965Sjdp 184433965Sjdp /* Convert from external symbol information to internal. */ 184533965Sjdp if (! (NAME(aout,translate_symbol_table) 184633965Sjdp (abfd, cached, 184733965Sjdp obj_aout_external_syms (abfd), 184833965Sjdp obj_aout_external_sym_count (abfd), 184933965Sjdp obj_aout_external_strings (abfd), 185033965Sjdp obj_aout_external_string_size (abfd), 185133965Sjdp false))) 185233965Sjdp { 185333965Sjdp free (cached); 185433965Sjdp return false; 185533965Sjdp } 185633965Sjdp 185733965Sjdp bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd); 185833965Sjdp 185933965Sjdp obj_aout_symbols (abfd) = cached; 186033965Sjdp 186133965Sjdp /* It is very likely that anybody who calls this function will not 186233965Sjdp want the external symbol information, so if it was allocated 186333965Sjdp because of our call to aout_get_external_symbols, we free it up 186433965Sjdp right away to save space. */ 186533965Sjdp if (old_external_syms == (struct external_nlist *) NULL 186633965Sjdp && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) 186733965Sjdp { 186833965Sjdp#ifdef USE_MMAP 186933965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 187033965Sjdp#else 187133965Sjdp free (obj_aout_external_syms (abfd)); 187233965Sjdp#endif 187333965Sjdp obj_aout_external_syms (abfd) = NULL; 187433965Sjdp } 187533965Sjdp 187633965Sjdp return true; 187733965Sjdp} 187833965Sjdp 187933965Sjdp/* We use a hash table when writing out symbols so that we only write 188033965Sjdp out a particular string once. This helps particularly when the 188133965Sjdp linker writes out stabs debugging entries, because each different 188233965Sjdp contributing object file tends to have many duplicate stabs 188333965Sjdp strings. 188433965Sjdp 188533965Sjdp This hash table code breaks dbx on SunOS 4.1.3, so we don't do it 188633965Sjdp if BFD_TRADITIONAL_FORMAT is set. */ 188733965Sjdp 188833965Sjdpstatic bfd_size_type add_to_stringtab 188933965Sjdp PARAMS ((bfd *, struct bfd_strtab_hash *, const char *, boolean)); 189033965Sjdpstatic boolean emit_stringtab PARAMS ((bfd *, struct bfd_strtab_hash *)); 189133965Sjdp 189233965Sjdp/* Get the index of a string in a strtab, adding it if it is not 189333965Sjdp already present. */ 189433965Sjdp 189533965Sjdpstatic INLINE bfd_size_type 189633965Sjdpadd_to_stringtab (abfd, tab, str, copy) 189733965Sjdp bfd *abfd; 189833965Sjdp struct bfd_strtab_hash *tab; 189933965Sjdp const char *str; 190033965Sjdp boolean copy; 190133965Sjdp{ 190233965Sjdp boolean hash; 190333965Sjdp bfd_size_type index; 190433965Sjdp 190533965Sjdp /* An index of 0 always means the empty string. */ 190633965Sjdp if (str == 0 || *str == '\0') 190733965Sjdp return 0; 190833965Sjdp 190933965Sjdp /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx 191033965Sjdp doesn't understand a hashed string table. */ 191133965Sjdp hash = true; 191233965Sjdp if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0) 191333965Sjdp hash = false; 191433965Sjdp 191533965Sjdp index = _bfd_stringtab_add (tab, str, hash, copy); 191633965Sjdp 191733965Sjdp if (index != (bfd_size_type) -1) 191833965Sjdp { 191933965Sjdp /* Add BYTES_IN_WORD to the return value to account for the 192033965Sjdp space taken up by the string table size. */ 192133965Sjdp index += BYTES_IN_WORD; 192233965Sjdp } 192333965Sjdp 192433965Sjdp return index; 192533965Sjdp} 192633965Sjdp 192733965Sjdp/* Write out a strtab. ABFD is already at the right location in the 192833965Sjdp file. */ 192933965Sjdp 193033965Sjdpstatic boolean 193133965Sjdpemit_stringtab (abfd, tab) 193233965Sjdp register bfd *abfd; 193333965Sjdp struct bfd_strtab_hash *tab; 193433965Sjdp{ 193533965Sjdp bfd_byte buffer[BYTES_IN_WORD]; 193689857Sobrien bfd_size_type amt = BYTES_IN_WORD; 193733965Sjdp 193833965Sjdp /* The string table starts with the size. */ 193933965Sjdp PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer); 194089857Sobrien if (bfd_bwrite ((PTR) buffer, amt, abfd) != amt) 194133965Sjdp return false; 194233965Sjdp 194333965Sjdp return _bfd_stringtab_emit (abfd, tab); 194433965Sjdp} 194533965Sjdp 194633965Sjdpboolean 194733965SjdpNAME(aout,write_syms) (abfd) 194833965Sjdp bfd *abfd; 194933965Sjdp{ 195033965Sjdp unsigned int count ; 195133965Sjdp asymbol **generic = bfd_get_outsymbols (abfd); 195233965Sjdp struct bfd_strtab_hash *strtab; 195333965Sjdp 195433965Sjdp strtab = _bfd_stringtab_init (); 195533965Sjdp if (strtab == NULL) 195633965Sjdp return false; 195733965Sjdp 195833965Sjdp for (count = 0; count < bfd_get_symcount (abfd); count++) 195933965Sjdp { 196033965Sjdp asymbol *g = generic[count]; 196133965Sjdp bfd_size_type indx; 196233965Sjdp struct external_nlist nsp; 196389857Sobrien bfd_size_type amt; 196433965Sjdp 196533965Sjdp indx = add_to_stringtab (abfd, strtab, g->name, false); 196633965Sjdp if (indx == (bfd_size_type) -1) 196733965Sjdp goto error_return; 196833965Sjdp PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx); 196933965Sjdp 197089857Sobrien if (bfd_asymbol_flavour (g) == abfd->xvec->flavour) 197133965Sjdp { 197289857Sobrien H_PUT_16 (abfd, aout_symbol (g)->desc, nsp.e_desc); 197389857Sobrien H_PUT_8 (abfd, aout_symbol (g)->other, nsp.e_other); 197489857Sobrien H_PUT_8 (abfd, aout_symbol (g)->type, nsp.e_type); 197533965Sjdp } 197633965Sjdp else 197733965Sjdp { 197889857Sobrien H_PUT_16 (abfd, 0, nsp.e_desc); 197989857Sobrien H_PUT_8 (abfd, 0, nsp.e_other); 198089857Sobrien H_PUT_8 (abfd, 0, nsp.e_type); 198133965Sjdp } 198233965Sjdp 198333965Sjdp if (! translate_to_native_sym_flags (abfd, g, &nsp)) 198433965Sjdp goto error_return; 198533965Sjdp 198689857Sobrien amt = EXTERNAL_NLIST_SIZE; 198789857Sobrien if (bfd_bwrite ((PTR) &nsp, amt, abfd) != amt) 198833965Sjdp goto error_return; 198933965Sjdp 199033965Sjdp /* NB: `KEEPIT' currently overlays `udata.p', so set this only 199133965Sjdp here, at the end. */ 199233965Sjdp g->KEEPIT = count; 199333965Sjdp } 199433965Sjdp 199533965Sjdp if (! emit_stringtab (abfd, strtab)) 199633965Sjdp goto error_return; 199733965Sjdp 199833965Sjdp _bfd_stringtab_free (strtab); 199933965Sjdp 200033965Sjdp return true; 200133965Sjdp 200233965Sjdperror_return: 200333965Sjdp _bfd_stringtab_free (strtab); 200433965Sjdp return false; 200533965Sjdp} 200633965Sjdp 200733965Sjdplong 200833965SjdpNAME(aout,get_symtab) (abfd, location) 200933965Sjdp bfd *abfd; 201033965Sjdp asymbol **location; 201133965Sjdp{ 201233965Sjdp unsigned int counter = 0; 201333965Sjdp aout_symbol_type *symbase; 201433965Sjdp 201577298Sobrien if (!NAME(aout,slurp_symbol_table) (abfd)) 201633965Sjdp return -1; 201733965Sjdp 201889857Sobrien for (symbase = obj_aout_symbols (abfd); 201989857Sobrien counter++ < bfd_get_symcount (abfd); 202089857Sobrien ) 202189857Sobrien *(location++) = (asymbol *) (symbase++); 202233965Sjdp *location++ =0; 202333965Sjdp return bfd_get_symcount (abfd); 202433965Sjdp} 202533965Sjdp 202633965Sjdp/* Standard reloc stuff */ 202777298Sobrien/* Output standard relocation information to a file in target byte order. */ 202833965Sjdp 202933965Sjdpextern void NAME(aout,swap_std_reloc_out) 203033965Sjdp PARAMS ((bfd *, arelent *, struct reloc_std_external *)); 203133965Sjdp 203233965Sjdpvoid 203333965SjdpNAME(aout,swap_std_reloc_out) (abfd, g, natptr) 203433965Sjdp bfd *abfd; 203533965Sjdp arelent *g; 203633965Sjdp struct reloc_std_external *natptr; 203733965Sjdp{ 203833965Sjdp int r_index; 203933965Sjdp asymbol *sym = *(g->sym_ptr_ptr); 204033965Sjdp int r_extern; 204133965Sjdp unsigned int r_length; 204233965Sjdp int r_pcrel; 204333965Sjdp int r_baserel, r_jmptable, r_relative; 204433965Sjdp asection *output_section = sym->section->output_section; 204533965Sjdp 204689857Sobrien PUT_WORD (abfd, g->address, natptr->r_address); 204733965Sjdp 204833965Sjdp r_length = g->howto->size ; /* Size as a power of two */ 204933965Sjdp r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ 205033965Sjdp /* XXX This relies on relocs coming from a.out files. */ 205133965Sjdp r_baserel = (g->howto->type & 8) != 0; 205233965Sjdp r_jmptable = (g->howto->type & 16) != 0; 205333965Sjdp r_relative = (g->howto->type & 32) != 0; 205433965Sjdp 205533965Sjdp#if 0 205633965Sjdp /* For a standard reloc, the addend is in the object file. */ 205733965Sjdp r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma; 205833965Sjdp#endif 205933965Sjdp 206033965Sjdp /* name was clobbered by aout_write_syms to be symbol index */ 206133965Sjdp 206233965Sjdp /* If this relocation is relative to a symbol then set the 206333965Sjdp r_index to the symbols index, and the r_extern bit. 206433965Sjdp 206533965Sjdp Absolute symbols can come in in two ways, either as an offset 206633965Sjdp from the abs section, or as a symbol which has an abs value. 206733965Sjdp check for that here 206833965Sjdp */ 206933965Sjdp 207033965Sjdp if (bfd_is_com_section (output_section) 207133965Sjdp || bfd_is_abs_section (output_section) 207233965Sjdp || bfd_is_und_section (output_section)) 207333965Sjdp { 207433965Sjdp if (bfd_abs_section_ptr->symbol == sym) 207533965Sjdp { 207633965Sjdp /* Whoops, looked like an abs symbol, but is really an offset 207733965Sjdp from the abs section */ 207833965Sjdp r_index = N_ABS; 207933965Sjdp r_extern = 0; 208033965Sjdp } 208133965Sjdp else 208233965Sjdp { 208333965Sjdp /* Fill in symbol */ 208433965Sjdp r_extern = 1; 208533965Sjdp r_index = (*(g->sym_ptr_ptr))->KEEPIT; 208633965Sjdp 208733965Sjdp } 208833965Sjdp } 208933965Sjdp else 209033965Sjdp { 209133965Sjdp /* Just an ordinary section */ 209233965Sjdp r_extern = 0; 209333965Sjdp r_index = output_section->target_index; 209433965Sjdp } 209533965Sjdp 209633965Sjdp /* now the fun stuff */ 209789857Sobrien if (bfd_header_big_endian (abfd)) 209889857Sobrien { 209933965Sjdp natptr->r_index[0] = r_index >> 16; 210033965Sjdp natptr->r_index[1] = r_index >> 8; 210133965Sjdp natptr->r_index[2] = r_index; 210289857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) 210389857Sobrien | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) 210489857Sobrien | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) 210589857Sobrien | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) 210689857Sobrien | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) 210789857Sobrien | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); 210889857Sobrien } 210989857Sobrien else 211089857Sobrien { 211189857Sobrien natptr->r_index[2] = r_index >> 16; 211289857Sobrien natptr->r_index[1] = r_index >> 8; 211389857Sobrien natptr->r_index[0] = r_index; 211489857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) 211589857Sobrien | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) 211689857Sobrien | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) 211789857Sobrien | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) 211889857Sobrien | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) 211989857Sobrien | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 212089857Sobrien } 212133965Sjdp} 212233965Sjdp 212333965Sjdp/* Extended stuff */ 212477298Sobrien/* Output extended relocation information to a file in target byte order. */ 212533965Sjdp 212633965Sjdpextern void NAME(aout,swap_ext_reloc_out) 212733965Sjdp PARAMS ((bfd *, arelent *, struct reloc_ext_external *)); 212833965Sjdp 212933965Sjdpvoid 213033965SjdpNAME(aout,swap_ext_reloc_out) (abfd, g, natptr) 213133965Sjdp bfd *abfd; 213233965Sjdp arelent *g; 213333965Sjdp register struct reloc_ext_external *natptr; 213433965Sjdp{ 213533965Sjdp int r_index; 213633965Sjdp int r_extern; 213733965Sjdp unsigned int r_type; 213889857Sobrien bfd_vma r_addend; 213933965Sjdp asymbol *sym = *(g->sym_ptr_ptr); 214033965Sjdp asection *output_section = sym->section->output_section; 214133965Sjdp 214233965Sjdp PUT_WORD (abfd, g->address, natptr->r_address); 214333965Sjdp 214433965Sjdp r_type = (unsigned int) g->howto->type; 214533965Sjdp 214633965Sjdp r_addend = g->addend; 214733965Sjdp if ((sym->flags & BSF_SECTION_SYM) != 0) 214833965Sjdp r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma; 214933965Sjdp 215033965Sjdp /* If this relocation is relative to a symbol then set the 215133965Sjdp r_index to the symbols index, and the r_extern bit. 215233965Sjdp 215333965Sjdp Absolute symbols can come in in two ways, either as an offset 215433965Sjdp from the abs section, or as a symbol which has an abs value. 215533965Sjdp check for that here. */ 215633965Sjdp 215733965Sjdp if (bfd_is_abs_section (bfd_get_section (sym))) 215833965Sjdp { 215933965Sjdp r_extern = 0; 216033965Sjdp r_index = N_ABS; 216133965Sjdp } 216233965Sjdp else if ((sym->flags & BSF_SECTION_SYM) == 0) 216333965Sjdp { 216433965Sjdp if (bfd_is_und_section (bfd_get_section (sym)) 216533965Sjdp || (sym->flags & BSF_GLOBAL) != 0) 216633965Sjdp r_extern = 1; 216733965Sjdp else 216833965Sjdp r_extern = 0; 216933965Sjdp r_index = (*(g->sym_ptr_ptr))->KEEPIT; 217033965Sjdp } 217133965Sjdp else 217233965Sjdp { 217333965Sjdp /* Just an ordinary section */ 217433965Sjdp r_extern = 0; 217533965Sjdp r_index = output_section->target_index; 217633965Sjdp } 217733965Sjdp 217833965Sjdp /* now the fun stuff */ 217989857Sobrien if (bfd_header_big_endian (abfd)) 218089857Sobrien { 218189857Sobrien natptr->r_index[0] = r_index >> 16; 218289857Sobrien natptr->r_index[1] = r_index >> 8; 218389857Sobrien natptr->r_index[2] = r_index; 218489857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) 218589857Sobrien | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG)); 218689857Sobrien } 218789857Sobrien else 218889857Sobrien { 218989857Sobrien natptr->r_index[2] = r_index >> 16; 219089857Sobrien natptr->r_index[1] = r_index >> 8; 219189857Sobrien natptr->r_index[0] = r_index; 219289857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) 219389857Sobrien | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE)); 219489857Sobrien } 219533965Sjdp 219633965Sjdp PUT_WORD (abfd, r_addend, natptr->r_addend); 219733965Sjdp} 219833965Sjdp 219933965Sjdp/* BFD deals internally with all things based from the section they're 220033965Sjdp in. so, something in 10 bytes into a text section with a base of 220133965Sjdp 50 would have a symbol (.text+10) and know .text vma was 50. 220233965Sjdp 220333965Sjdp Aout keeps all it's symbols based from zero, so the symbol would 220433965Sjdp contain 60. This macro subs the base of each section from the value 220589857Sobrien to give the true offset from the section. */ 220633965Sjdp 220789857Sobrien#define MOVE_ADDRESS(ad) \ 220889857Sobrien if (r_extern) \ 220989857Sobrien { \ 221089857Sobrien /* Undefined symbol. */ \ 221189857Sobrien cache_ptr->sym_ptr_ptr = symbols + r_index; \ 221233965Sjdp cache_ptr->addend = ad; \ 221333965Sjdp } \ 221489857Sobrien else \ 221589857Sobrien { \ 221689857Sobrien /* Defined, section relative. Replace symbol with pointer to \ 221789857Sobrien symbol which points to section. */ \ 221889857Sobrien switch (r_index) \ 221989857Sobrien { \ 222089857Sobrien case N_TEXT: \ 222189857Sobrien case N_TEXT | N_EXT: \ 222289857Sobrien cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr; \ 222389857Sobrien cache_ptr->addend = ad - su->textsec->vma; \ 222489857Sobrien break; \ 222589857Sobrien case N_DATA: \ 222689857Sobrien case N_DATA | N_EXT: \ 222789857Sobrien cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr; \ 222889857Sobrien cache_ptr->addend = ad - su->datasec->vma; \ 222989857Sobrien break; \ 223089857Sobrien case N_BSS: \ 223189857Sobrien case N_BSS | N_EXT: \ 223289857Sobrien cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr; \ 223389857Sobrien cache_ptr->addend = ad - su->bsssec->vma; \ 223489857Sobrien break; \ 223589857Sobrien default: \ 223689857Sobrien case N_ABS: \ 223789857Sobrien case N_ABS | N_EXT: \ 223889857Sobrien cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \ 223989857Sobrien cache_ptr->addend = ad; \ 224089857Sobrien break; \ 224189857Sobrien } \ 224289857Sobrien } 224333965Sjdp 224433965Sjdpvoid 224533965SjdpNAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) 224633965Sjdp bfd *abfd; 224733965Sjdp struct reloc_ext_external *bytes; 224833965Sjdp arelent *cache_ptr; 224933965Sjdp asymbol **symbols; 225033965Sjdp bfd_size_type symcount; 225133965Sjdp{ 225233965Sjdp unsigned int r_index; 225333965Sjdp int r_extern; 225433965Sjdp unsigned int r_type; 225533965Sjdp struct aoutdata *su = &(abfd->tdata.aout_data->a); 225633965Sjdp 225733965Sjdp cache_ptr->address = (GET_SWORD (abfd, bytes->r_address)); 225833965Sjdp 225933965Sjdp /* now the fun stuff */ 226089857Sobrien if (bfd_header_big_endian (abfd)) 226189857Sobrien { 226289857Sobrien r_index = ((bytes->r_index[0] << 16) 226389857Sobrien | (bytes->r_index[1] << 8) 226489857Sobrien | bytes->r_index[2]); 226589857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 226689857Sobrien r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 226789857Sobrien >> RELOC_EXT_BITS_TYPE_SH_BIG); 226889857Sobrien } 226989857Sobrien else 227089857Sobrien { 227189857Sobrien r_index = ((bytes->r_index[2] << 16) 227289857Sobrien | (bytes->r_index[1] << 8) 227389857Sobrien | bytes->r_index[0]); 227489857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 227589857Sobrien r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 227689857Sobrien >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 227789857Sobrien } 227833965Sjdp 227933965Sjdp cache_ptr->howto = howto_table_ext + r_type; 228033965Sjdp 228133965Sjdp /* Base relative relocs are always against the symbol table, 228233965Sjdp regardless of the setting of r_extern. r_extern just reflects 228333965Sjdp whether the symbol the reloc is against is local or global. */ 228433965Sjdp if (r_type == RELOC_BASE10 228533965Sjdp || r_type == RELOC_BASE13 228633965Sjdp || r_type == RELOC_BASE22) 228733965Sjdp r_extern = 1; 228833965Sjdp 228933965Sjdp if (r_extern && r_index > symcount) 229033965Sjdp { 229133965Sjdp /* We could arrange to return an error, but it might be useful 229233965Sjdp to see the file even if it is bad. */ 229333965Sjdp r_extern = 0; 229433965Sjdp r_index = N_ABS; 229533965Sjdp } 229633965Sjdp 229789857Sobrien MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend)); 229833965Sjdp} 229933965Sjdp 230033965Sjdpvoid 230133965SjdpNAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) 230233965Sjdp bfd *abfd; 230333965Sjdp struct reloc_std_external *bytes; 230433965Sjdp arelent *cache_ptr; 230533965Sjdp asymbol **symbols; 230633965Sjdp bfd_size_type symcount; 230733965Sjdp{ 230833965Sjdp unsigned int r_index; 230933965Sjdp int r_extern; 231033965Sjdp unsigned int r_length; 231133965Sjdp int r_pcrel; 231233965Sjdp int r_baserel, r_jmptable, r_relative; 231333965Sjdp struct aoutdata *su = &(abfd->tdata.aout_data->a); 231433965Sjdp unsigned int howto_idx; 231533965Sjdp 231689857Sobrien cache_ptr->address = H_GET_32 (abfd, bytes->r_address); 231733965Sjdp 231833965Sjdp /* now the fun stuff */ 231989857Sobrien if (bfd_header_big_endian (abfd)) 232089857Sobrien { 232189857Sobrien r_index = ((bytes->r_index[0] << 16) 232289857Sobrien | (bytes->r_index[1] << 8) 232389857Sobrien | bytes->r_index[2]); 232489857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); 232589857Sobrien r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 232689857Sobrien r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 232789857Sobrien r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 232889857Sobrien r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); 232989857Sobrien r_length = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) 233089857Sobrien >> RELOC_STD_BITS_LENGTH_SH_BIG); 233189857Sobrien } 233289857Sobrien else 233389857Sobrien { 233489857Sobrien r_index = ((bytes->r_index[2] << 16) 233589857Sobrien | (bytes->r_index[1] << 8) 233689857Sobrien | bytes->r_index[0]); 233789857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); 233889857Sobrien r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 233989857Sobrien r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); 234089857Sobrien r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); 234189857Sobrien r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE)); 234289857Sobrien r_length = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) 234389857Sobrien >> RELOC_STD_BITS_LENGTH_SH_LITTLE); 234489857Sobrien } 234533965Sjdp 234689857Sobrien howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel 234789857Sobrien + 16 * r_jmptable + 32 * r_relative); 234833965Sjdp BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); 234933965Sjdp cache_ptr->howto = howto_table_std + howto_idx; 235033965Sjdp BFD_ASSERT (cache_ptr->howto->type != (unsigned int) -1); 235133965Sjdp 235233965Sjdp /* Base relative relocs are always against the symbol table, 235333965Sjdp regardless of the setting of r_extern. r_extern just reflects 235433965Sjdp whether the symbol the reloc is against is local or global. */ 235533965Sjdp if (r_baserel) 235633965Sjdp r_extern = 1; 235733965Sjdp 235833965Sjdp if (r_extern && r_index > symcount) 235933965Sjdp { 236033965Sjdp /* We could arrange to return an error, but it might be useful 236133965Sjdp to see the file even if it is bad. */ 236233965Sjdp r_extern = 0; 236333965Sjdp r_index = N_ABS; 236433965Sjdp } 236533965Sjdp 236689857Sobrien MOVE_ADDRESS (0); 236733965Sjdp} 236833965Sjdp 236933965Sjdp/* Read and swap the relocs for a section. */ 237033965Sjdp 237133965Sjdpboolean 237233965SjdpNAME(aout,slurp_reloc_table) (abfd, asect, symbols) 237333965Sjdp bfd *abfd; 237433965Sjdp sec_ptr asect; 237533965Sjdp asymbol **symbols; 237633965Sjdp{ 237789857Sobrien bfd_size_type count; 237833965Sjdp bfd_size_type reloc_size; 237933965Sjdp PTR relocs; 238033965Sjdp arelent *reloc_cache; 238133965Sjdp size_t each_size; 238233965Sjdp unsigned int counter = 0; 238333965Sjdp arelent *cache_ptr; 238489857Sobrien bfd_size_type amt; 238533965Sjdp 238633965Sjdp if (asect->relocation) 238733965Sjdp return true; 238833965Sjdp 238933965Sjdp if (asect->flags & SEC_CONSTRUCTOR) 239033965Sjdp return true; 239133965Sjdp 239233965Sjdp if (asect == obj_datasec (abfd)) 239389857Sobrien reloc_size = exec_hdr (abfd)->a_drsize; 239433965Sjdp else if (asect == obj_textsec (abfd)) 239589857Sobrien reloc_size = exec_hdr (abfd)->a_trsize; 239633965Sjdp else if (asect == obj_bsssec (abfd)) 239733965Sjdp reloc_size = 0; 239833965Sjdp else 239933965Sjdp { 240033965Sjdp bfd_set_error (bfd_error_invalid_operation); 240133965Sjdp return false; 240233965Sjdp } 240333965Sjdp 240433965Sjdp if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) 240533965Sjdp return false; 240633965Sjdp 240733965Sjdp each_size = obj_reloc_entry_size (abfd); 240833965Sjdp 240933965Sjdp count = reloc_size / each_size; 241033965Sjdp 241189857Sobrien amt = count * sizeof (arelent); 2412104834Sobrien reloc_cache = (arelent *) bfd_zmalloc (amt); 241333965Sjdp if (reloc_cache == NULL && count != 0) 241433965Sjdp return false; 241533965Sjdp 241689857Sobrien relocs = bfd_malloc (reloc_size); 241733965Sjdp if (relocs == NULL && reloc_size != 0) 241833965Sjdp { 241933965Sjdp free (reloc_cache); 242033965Sjdp return false; 242133965Sjdp } 242233965Sjdp 242389857Sobrien if (bfd_bread (relocs, reloc_size, abfd) != reloc_size) 242433965Sjdp { 242533965Sjdp free (relocs); 242633965Sjdp free (reloc_cache); 242733965Sjdp return false; 242833965Sjdp } 242933965Sjdp 243033965Sjdp cache_ptr = reloc_cache; 243133965Sjdp if (each_size == RELOC_EXT_SIZE) 243233965Sjdp { 243389857Sobrien struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs; 243433965Sjdp 243533965Sjdp for (; counter < count; counter++, rptr++, cache_ptr++) 243677298Sobrien MY_swap_ext_reloc_in (abfd, rptr, cache_ptr, symbols, 243789857Sobrien (bfd_size_type) bfd_get_symcount (abfd)); 243833965Sjdp } 243933965Sjdp else 244033965Sjdp { 244189857Sobrien struct reloc_std_external *rptr = (struct reloc_std_external *) relocs; 244233965Sjdp 244333965Sjdp for (; counter < count; counter++, rptr++, cache_ptr++) 244433965Sjdp MY_swap_std_reloc_in (abfd, rptr, cache_ptr, symbols, 244589857Sobrien (bfd_size_type) bfd_get_symcount (abfd)); 244633965Sjdp } 244733965Sjdp 244833965Sjdp free (relocs); 244933965Sjdp 245033965Sjdp asect->relocation = reloc_cache; 245133965Sjdp asect->reloc_count = cache_ptr - reloc_cache; 245233965Sjdp 245333965Sjdp return true; 245433965Sjdp} 245533965Sjdp 245633965Sjdp/* Write out a relocation section into an object file. */ 245733965Sjdp 245833965Sjdpboolean 245933965SjdpNAME(aout,squirt_out_relocs) (abfd, section) 246033965Sjdp bfd *abfd; 246133965Sjdp asection *section; 246233965Sjdp{ 246333965Sjdp arelent **generic; 246433965Sjdp unsigned char *native, *natptr; 246533965Sjdp size_t each_size; 246633965Sjdp 246733965Sjdp unsigned int count = section->reloc_count; 246889857Sobrien bfd_size_type natsize; 246933965Sjdp 247033965Sjdp if (count == 0 || section->orelocation == NULL) 247133965Sjdp return true; 247233965Sjdp 247333965Sjdp each_size = obj_reloc_entry_size (abfd); 247489857Sobrien natsize = (bfd_size_type) each_size * count; 247533965Sjdp native = (unsigned char *) bfd_zalloc (abfd, natsize); 247633965Sjdp if (!native) 247733965Sjdp return false; 247833965Sjdp 247933965Sjdp generic = section->orelocation; 248033965Sjdp 248133965Sjdp if (each_size == RELOC_EXT_SIZE) 248233965Sjdp { 248333965Sjdp for (natptr = native; 248433965Sjdp count != 0; 248533965Sjdp --count, natptr += each_size, ++generic) 248677298Sobrien MY_swap_ext_reloc_out (abfd, *generic, 248777298Sobrien (struct reloc_ext_external *) natptr); 248833965Sjdp } 248933965Sjdp else 249033965Sjdp { 249133965Sjdp for (natptr = native; 249233965Sjdp count != 0; 249333965Sjdp --count, natptr += each_size, ++generic) 249489857Sobrien MY_swap_std_reloc_out (abfd, *generic, 249589857Sobrien (struct reloc_std_external *) natptr); 249633965Sjdp } 249733965Sjdp 249889857Sobrien if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize) 249989857Sobrien { 250089857Sobrien bfd_release (abfd, native); 250189857Sobrien return false; 250289857Sobrien } 250333965Sjdp bfd_release (abfd, native); 250433965Sjdp 250533965Sjdp return true; 250633965Sjdp} 250733965Sjdp 250833965Sjdp/* This is stupid. This function should be a boolean predicate */ 250933965Sjdplong 251033965SjdpNAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols) 251133965Sjdp bfd *abfd; 251233965Sjdp sec_ptr section; 251333965Sjdp arelent **relptr; 251433965Sjdp asymbol **symbols; 251533965Sjdp{ 251633965Sjdp arelent *tblptr = section->relocation; 251733965Sjdp unsigned int count; 251833965Sjdp 251933965Sjdp if (section == obj_bsssec (abfd)) 252033965Sjdp { 252133965Sjdp *relptr = NULL; 252233965Sjdp return 0; 252333965Sjdp } 252433965Sjdp 252577298Sobrien if (!(tblptr || NAME(aout,slurp_reloc_table) (abfd, section, symbols))) 252633965Sjdp return -1; 252733965Sjdp 252889857Sobrien if (section->flags & SEC_CONSTRUCTOR) 252989857Sobrien { 253089857Sobrien arelent_chain *chain = section->constructor_chain; 253189857Sobrien for (count = 0; count < section->reloc_count; count ++) 253289857Sobrien { 253389857Sobrien *relptr ++ = &chain->relent; 253489857Sobrien chain = chain->next; 253589857Sobrien } 253633965Sjdp } 253789857Sobrien else 253889857Sobrien { 253989857Sobrien tblptr = section->relocation; 254033965Sjdp 254189857Sobrien for (count = 0; count++ < section->reloc_count; ) 254289857Sobrien { 254389857Sobrien *relptr++ = tblptr++; 254489857Sobrien } 254589857Sobrien } 254633965Sjdp *relptr = 0; 254733965Sjdp 254833965Sjdp return section->reloc_count; 254933965Sjdp} 255033965Sjdp 255133965Sjdplong 255233965SjdpNAME(aout,get_reloc_upper_bound) (abfd, asect) 255333965Sjdp bfd *abfd; 255433965Sjdp sec_ptr asect; 255533965Sjdp{ 255689857Sobrien if (bfd_get_format (abfd) != bfd_object) 255789857Sobrien { 255889857Sobrien bfd_set_error (bfd_error_invalid_operation); 255989857Sobrien return -1; 256089857Sobrien } 256189857Sobrien if (asect->flags & SEC_CONSTRUCTOR) 256289857Sobrien { 256389857Sobrien return (sizeof (arelent *) * (asect->reloc_count+1)); 256489857Sobrien } 256533965Sjdp 256633965Sjdp if (asect == obj_datasec (abfd)) 256733965Sjdp return (sizeof (arelent *) 256889857Sobrien * ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd)) 256933965Sjdp + 1)); 257033965Sjdp 257133965Sjdp if (asect == obj_textsec (abfd)) 257233965Sjdp return (sizeof (arelent *) 257389857Sobrien * ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd)) 257433965Sjdp + 1)); 257533965Sjdp 257633965Sjdp if (asect == obj_bsssec (abfd)) 257733965Sjdp return sizeof (arelent *); 257833965Sjdp 257933965Sjdp if (asect == obj_bsssec (abfd)) 258033965Sjdp return 0; 258133965Sjdp 258233965Sjdp bfd_set_error (bfd_error_invalid_operation); 258333965Sjdp return -1; 258433965Sjdp} 258533965Sjdp 258633965Sjdplong 258733965SjdpNAME(aout,get_symtab_upper_bound) (abfd) 258833965Sjdp bfd *abfd; 258933965Sjdp{ 259077298Sobrien if (!NAME(aout,slurp_symbol_table) (abfd)) 259133965Sjdp return -1; 259233965Sjdp 259333965Sjdp return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *)); 259433965Sjdp} 259533965Sjdp 259689857Sobrienalent * 259733965SjdpNAME(aout,get_lineno) (ignore_abfd, ignore_symbol) 259860484Sobrien bfd *ignore_abfd ATTRIBUTE_UNUSED; 259960484Sobrien asymbol *ignore_symbol ATTRIBUTE_UNUSED; 260033965Sjdp{ 260160484Sobrien return (alent *)NULL; 260233965Sjdp} 260333965Sjdp 260433965Sjdpvoid 260533965SjdpNAME(aout,get_symbol_info) (ignore_abfd, symbol, ret) 260660484Sobrien bfd *ignore_abfd ATTRIBUTE_UNUSED; 260733965Sjdp asymbol *symbol; 260833965Sjdp symbol_info *ret; 260933965Sjdp{ 261033965Sjdp bfd_symbol_info (symbol, ret); 261133965Sjdp 261233965Sjdp if (ret->type == '?') 261333965Sjdp { 261489857Sobrien int type_code = aout_symbol (symbol)->type & 0xff; 261533965Sjdp const char *stab_name = bfd_get_stab_name (type_code); 261633965Sjdp static char buf[10]; 261733965Sjdp 261833965Sjdp if (stab_name == NULL) 261933965Sjdp { 262077298Sobrien sprintf (buf, "(%d)", type_code); 262133965Sjdp stab_name = buf; 262233965Sjdp } 262333965Sjdp ret->type = '-'; 262433965Sjdp ret->stab_type = type_code; 262589857Sobrien ret->stab_other = (unsigned) (aout_symbol (symbol)->other & 0xff); 262689857Sobrien ret->stab_desc = (unsigned) (aout_symbol (symbol)->desc & 0xffff); 262733965Sjdp ret->stab_name = stab_name; 262833965Sjdp } 262933965Sjdp} 263033965Sjdp 263133965Sjdpvoid 263289857SobrienNAME(aout,print_symbol) (abfd, afile, symbol, how) 263389857Sobrien bfd *abfd; 263433965Sjdp PTR afile; 263533965Sjdp asymbol *symbol; 263633965Sjdp bfd_print_symbol_type how; 263733965Sjdp{ 263833965Sjdp FILE *file = (FILE *)afile; 263933965Sjdp 264089857Sobrien switch (how) 264133965Sjdp { 264289857Sobrien case bfd_print_symbol_name: 264389857Sobrien if (symbol->name) 264489857Sobrien fprintf (file,"%s", symbol->name); 264589857Sobrien break; 264689857Sobrien case bfd_print_symbol_more: 264789857Sobrien fprintf (file,"%4x %2x %2x", 264889857Sobrien (unsigned) (aout_symbol (symbol)->desc & 0xffff), 264989857Sobrien (unsigned) (aout_symbol (symbol)->other & 0xff), 265089857Sobrien (unsigned) (aout_symbol (symbol)->type)); 265189857Sobrien break; 265289857Sobrien case bfd_print_symbol_all: 265389857Sobrien { 265489857Sobrien const char *section_name = symbol->section->name; 265533965Sjdp 265689857Sobrien bfd_print_symbol_vandf (abfd, (PTR)file, symbol); 265733965Sjdp 265889857Sobrien fprintf (file," %-5s %04x %02x %02x", 265989857Sobrien section_name, 266089857Sobrien (unsigned) (aout_symbol (symbol)->desc & 0xffff), 266189857Sobrien (unsigned) (aout_symbol (symbol)->other & 0xff), 266289857Sobrien (unsigned) (aout_symbol (symbol)->type & 0xff)); 266389857Sobrien if (symbol->name) 266489857Sobrien fprintf (file," %s", symbol->name); 266589857Sobrien } 266689857Sobrien break; 266733965Sjdp } 266833965Sjdp} 266933965Sjdp 267033965Sjdp/* If we don't have to allocate more than 1MB to hold the generic 267133965Sjdp symbols, we use the generic minisymbol methord: it's faster, since 267233965Sjdp it only translates the symbols once, not multiple times. */ 267333965Sjdp#define MINISYM_THRESHOLD (1000000 / sizeof (asymbol)) 267433965Sjdp 267533965Sjdp/* Read minisymbols. For minisymbols, we use the unmodified a.out 267633965Sjdp symbols. The minisymbol_to_symbol function translates these into 267733965Sjdp BFD asymbol structures. */ 267833965Sjdp 267933965Sjdplong 268033965SjdpNAME(aout,read_minisymbols) (abfd, dynamic, minisymsp, sizep) 268133965Sjdp bfd *abfd; 268233965Sjdp boolean dynamic; 268333965Sjdp PTR *minisymsp; 268433965Sjdp unsigned int *sizep; 268533965Sjdp{ 268633965Sjdp if (dynamic) 268733965Sjdp { 268833965Sjdp /* We could handle the dynamic symbols here as well, but it's 268933965Sjdp easier to hand them off. */ 269033965Sjdp return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); 269133965Sjdp } 269233965Sjdp 269333965Sjdp if (! aout_get_external_symbols (abfd)) 269433965Sjdp return -1; 269533965Sjdp 269633965Sjdp if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD) 269733965Sjdp return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); 269833965Sjdp 269933965Sjdp *minisymsp = (PTR) obj_aout_external_syms (abfd); 270033965Sjdp 270133965Sjdp /* By passing the external symbols back from this routine, we are 270233965Sjdp giving up control over the memory block. Clear 270333965Sjdp obj_aout_external_syms, so that we do not try to free it 270433965Sjdp ourselves. */ 270533965Sjdp obj_aout_external_syms (abfd) = NULL; 270633965Sjdp 270733965Sjdp *sizep = EXTERNAL_NLIST_SIZE; 270833965Sjdp return obj_aout_external_sym_count (abfd); 270933965Sjdp} 271033965Sjdp 271133965Sjdp/* Convert a minisymbol to a BFD asymbol. A minisymbol is just an 271233965Sjdp unmodified a.out symbol. The SYM argument is a structure returned 271333965Sjdp by bfd_make_empty_symbol, which we fill in here. */ 271433965Sjdp 271533965Sjdpasymbol * 271633965SjdpNAME(aout,minisymbol_to_symbol) (abfd, dynamic, minisym, sym) 271733965Sjdp bfd *abfd; 271833965Sjdp boolean dynamic; 271933965Sjdp const PTR minisym; 272033965Sjdp asymbol *sym; 272133965Sjdp{ 272233965Sjdp if (dynamic 272333965Sjdp || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD) 272433965Sjdp return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym); 272533965Sjdp 272633965Sjdp memset (sym, 0, sizeof (aout_symbol_type)); 272733965Sjdp 272833965Sjdp /* We call translate_symbol_table to translate a single symbol. */ 272933965Sjdp if (! (NAME(aout,translate_symbol_table) 273033965Sjdp (abfd, 273133965Sjdp (aout_symbol_type *) sym, 273233965Sjdp (struct external_nlist *) minisym, 273333965Sjdp (bfd_size_type) 1, 273433965Sjdp obj_aout_external_strings (abfd), 273533965Sjdp obj_aout_external_string_size (abfd), 273633965Sjdp false))) 273733965Sjdp return NULL; 273833965Sjdp 273933965Sjdp return sym; 274033965Sjdp} 274133965Sjdp 274233965Sjdp/* 274333965Sjdp provided a BFD, a section and an offset into the section, calculate 274433965Sjdp and return the name of the source file and the line nearest to the 274533965Sjdp wanted location. 274633965Sjdp*/ 274733965Sjdp 274833965Sjdpboolean 274933965SjdpNAME(aout,find_nearest_line) 275033965Sjdp (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr) 275133965Sjdp bfd *abfd; 275233965Sjdp asection *section; 275333965Sjdp asymbol **symbols; 275433965Sjdp bfd_vma offset; 275589857Sobrien const char **filename_ptr; 275689857Sobrien const char **functionname_ptr; 275733965Sjdp unsigned int *line_ptr; 275833965Sjdp{ 275933965Sjdp /* Run down the file looking for the filename, function and linenumber */ 276033965Sjdp asymbol **p; 276189857Sobrien const char *directory_name = NULL; 276289857Sobrien const char *main_file_name = NULL; 276389857Sobrien const char *current_file_name = NULL; 276489857Sobrien const char *line_file_name = NULL; /* Value of current_file_name at line number. */ 276589857Sobrien const char *line_directory_name = NULL; /* Value of directory_name at line number. */ 276633965Sjdp bfd_vma low_line_vma = 0; 276733965Sjdp bfd_vma low_func_vma = 0; 276833965Sjdp asymbol *func = 0; 276989857Sobrien bfd_size_type filelen, funclen; 277033965Sjdp char *buf; 277133965Sjdp 277233965Sjdp *filename_ptr = abfd->filename; 277333965Sjdp *functionname_ptr = 0; 277433965Sjdp *line_ptr = 0; 277589857Sobrien if (symbols != (asymbol **)NULL) 277689857Sobrien { 277789857Sobrien for (p = symbols; *p; p++) 277889857Sobrien { 277989857Sobrien aout_symbol_type *q = (aout_symbol_type *) (*p); 278089857Sobrien next: 278189857Sobrien switch (q->type) 278289857Sobrien { 278389857Sobrien case N_TEXT: 278489857Sobrien /* If this looks like a file name symbol, and it comes after 278589857Sobrien the line number we have found so far, but before the 278689857Sobrien offset, then we have probably not found the right line 278789857Sobrien number. */ 278889857Sobrien if (q->symbol.value <= offset 278989857Sobrien && ((q->symbol.value > low_line_vma 279089857Sobrien && (line_file_name != NULL 279189857Sobrien || *line_ptr != 0)) 279289857Sobrien || (q->symbol.value > low_func_vma 279389857Sobrien && func != NULL))) 279489857Sobrien { 279589857Sobrien const char *symname; 279633965Sjdp 279789857Sobrien symname = q->symbol.name; 279889857Sobrien if (strcmp (symname + strlen (symname) - 2, ".o") == 0) 279989857Sobrien { 280089857Sobrien if (q->symbol.value > low_line_vma) 280189857Sobrien { 280289857Sobrien *line_ptr = 0; 280389857Sobrien line_file_name = NULL; 280489857Sobrien } 280589857Sobrien if (q->symbol.value > low_func_vma) 280689857Sobrien func = NULL; 280789857Sobrien } 280889857Sobrien } 280989857Sobrien break; 281033965Sjdp 281189857Sobrien case N_SO: 281289857Sobrien /* If this symbol is less than the offset, but greater than 281389857Sobrien the line number we have found so far, then we have not 281489857Sobrien found the right line number. */ 281589857Sobrien if (q->symbol.value <= offset) 281689857Sobrien { 281789857Sobrien if (q->symbol.value > low_line_vma) 281889857Sobrien { 281989857Sobrien *line_ptr = 0; 282089857Sobrien line_file_name = NULL; 282189857Sobrien } 282289857Sobrien if (q->symbol.value > low_func_vma) 282389857Sobrien func = NULL; 282489857Sobrien } 282533965Sjdp 282689857Sobrien main_file_name = current_file_name = q->symbol.name; 282789857Sobrien /* Look ahead to next symbol to check if that too is an N_SO. */ 282889857Sobrien p++; 282989857Sobrien if (*p == NULL) 283089857Sobrien break; 283189857Sobrien q = (aout_symbol_type *) (*p); 283289857Sobrien if (q->type != (int)N_SO) 283389857Sobrien goto next; 283433965Sjdp 283589857Sobrien /* Found a second N_SO First is directory; second is filename. */ 283689857Sobrien directory_name = current_file_name; 283789857Sobrien main_file_name = current_file_name = q->symbol.name; 283889857Sobrien if (obj_textsec (abfd) != section) 283989857Sobrien goto done; 284089857Sobrien break; 284189857Sobrien case N_SOL: 284289857Sobrien current_file_name = q->symbol.name; 284389857Sobrien break; 284433965Sjdp 284589857Sobrien case N_SLINE: 284633965Sjdp 284789857Sobrien case N_DSLINE: 284889857Sobrien case N_BSLINE: 284989857Sobrien /* We'll keep this if it resolves nearer than the one we have 285089857Sobrien already. */ 285189857Sobrien if (q->symbol.value >= low_line_vma 285289857Sobrien && q->symbol.value <= offset) 285389857Sobrien { 285489857Sobrien *line_ptr = q->desc; 285589857Sobrien low_line_vma = q->symbol.value; 285689857Sobrien line_file_name = current_file_name; 285789857Sobrien line_directory_name = directory_name; 285889857Sobrien } 285989857Sobrien break; 286089857Sobrien case N_FUN: 286189857Sobrien { 286289857Sobrien /* We'll keep this if it is nearer than the one we have already */ 286389857Sobrien if (q->symbol.value >= low_func_vma && 286489857Sobrien q->symbol.value <= offset) { 286589857Sobrien low_func_vma = q->symbol.value; 286689857Sobrien func = (asymbol *)q; 286789857Sobrien } 286889857Sobrien else if (q->symbol.value > offset) 286989857Sobrien goto done; 287089857Sobrien } 287189857Sobrien break; 287289857Sobrien } 287333965Sjdp } 287433965Sjdp } 287533965Sjdp 287633965Sjdp done: 287733965Sjdp if (*line_ptr != 0) 287860484Sobrien { 287960484Sobrien main_file_name = line_file_name; 288060484Sobrien directory_name = line_directory_name; 288160484Sobrien } 288233965Sjdp 288333965Sjdp if (main_file_name == NULL 288461843Sobrien || IS_ABSOLUTE_PATH (main_file_name) 288533965Sjdp || directory_name == NULL) 288633965Sjdp filelen = 0; 288733965Sjdp else 288833965Sjdp filelen = strlen (directory_name) + strlen (main_file_name); 288933965Sjdp if (func == NULL) 289033965Sjdp funclen = 0; 289133965Sjdp else 289233965Sjdp funclen = strlen (bfd_asymbol_name (func)); 289333965Sjdp 289433965Sjdp if (adata (abfd).line_buf != NULL) 289533965Sjdp free (adata (abfd).line_buf); 289633965Sjdp if (filelen + funclen == 0) 289733965Sjdp adata (abfd).line_buf = buf = NULL; 289833965Sjdp else 289933965Sjdp { 290033965Sjdp buf = (char *) bfd_malloc (filelen + funclen + 3); 290133965Sjdp adata (abfd).line_buf = buf; 290233965Sjdp if (buf == NULL) 290333965Sjdp return false; 290433965Sjdp } 290533965Sjdp 290633965Sjdp if (main_file_name != NULL) 290733965Sjdp { 290861843Sobrien if (IS_ABSOLUTE_PATH (main_file_name) || directory_name == NULL) 290933965Sjdp *filename_ptr = main_file_name; 291033965Sjdp else 291133965Sjdp { 291233965Sjdp sprintf (buf, "%s%s", directory_name, main_file_name); 291333965Sjdp *filename_ptr = buf; 291433965Sjdp buf += filelen + 1; 291533965Sjdp } 291633965Sjdp } 291733965Sjdp 291833965Sjdp if (func) 291933965Sjdp { 292033965Sjdp const char *function = func->name; 292189857Sobrien char *colon; 292233965Sjdp 292333965Sjdp /* The caller expects a symbol name. We actually have a 292433965Sjdp function name, without the leading underscore. Put the 292533965Sjdp underscore back in, so that the caller gets a symbol name. */ 292633965Sjdp if (bfd_get_symbol_leading_char (abfd) == '\0') 292733965Sjdp strcpy (buf, function); 292833965Sjdp else 292933965Sjdp { 293033965Sjdp buf[0] = bfd_get_symbol_leading_char (abfd); 293133965Sjdp strcpy (buf + 1, function); 293233965Sjdp } 293333965Sjdp /* Have to remove : stuff */ 293489857Sobrien colon = strchr (buf, ':'); 293589857Sobrien if (colon != NULL) 293689857Sobrien *colon = '\0'; 293733965Sjdp *functionname_ptr = buf; 293833965Sjdp } 293933965Sjdp 294033965Sjdp return true; 294133965Sjdp} 294233965Sjdp 294333965Sjdpint 294433965SjdpNAME(aout,sizeof_headers) (abfd, execable) 294533965Sjdp bfd *abfd; 294660484Sobrien boolean execable ATTRIBUTE_UNUSED; 294733965Sjdp{ 294889857Sobrien return adata (abfd).exec_bytes_size; 294933965Sjdp} 295033965Sjdp 295133965Sjdp/* Free all information we have cached for this BFD. We can always 295233965Sjdp read it again later if we need it. */ 295333965Sjdp 295433965Sjdpboolean 295533965SjdpNAME(aout,bfd_free_cached_info) (abfd) 295633965Sjdp bfd *abfd; 295733965Sjdp{ 295833965Sjdp asection *o; 295933965Sjdp 296078828Sobrien if (bfd_get_format (abfd) != bfd_object 296178828Sobrien || abfd->tdata.aout_data == NULL) 296233965Sjdp return true; 296333965Sjdp 296433965Sjdp#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; } 296533965Sjdp BFCI_FREE (obj_aout_symbols (abfd)); 296633965Sjdp#ifdef USE_MMAP 296733965Sjdp obj_aout_external_syms (abfd) = 0; 296833965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 296933965Sjdp bfd_free_window (&obj_aout_string_window (abfd)); 297033965Sjdp obj_aout_external_strings (abfd) = 0; 297133965Sjdp#else 297233965Sjdp BFCI_FREE (obj_aout_external_syms (abfd)); 297333965Sjdp BFCI_FREE (obj_aout_external_strings (abfd)); 297433965Sjdp#endif 297533965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 297633965Sjdp BFCI_FREE (o->relocation); 297733965Sjdp#undef BFCI_FREE 297833965Sjdp 297933965Sjdp return true; 298033965Sjdp} 298133965Sjdp 298233965Sjdp/* a.out link code. */ 298333965Sjdp 298433965Sjdpstatic boolean aout_link_add_object_symbols 298533965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 298633965Sjdpstatic boolean aout_link_check_archive_element 298733965Sjdp PARAMS ((bfd *, struct bfd_link_info *, boolean *)); 298833965Sjdpstatic boolean aout_link_free_symbols PARAMS ((bfd *)); 298933965Sjdpstatic boolean aout_link_check_ar_symbols 299033965Sjdp PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded)); 299133965Sjdpstatic boolean aout_link_add_symbols 299233965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 299333965Sjdp 299433965Sjdp/* Routine to create an entry in an a.out link hash table. */ 299533965Sjdp 299633965Sjdpstruct bfd_hash_entry * 299733965SjdpNAME(aout,link_hash_newfunc) (entry, table, string) 299833965Sjdp struct bfd_hash_entry *entry; 299933965Sjdp struct bfd_hash_table *table; 300033965Sjdp const char *string; 300133965Sjdp{ 300233965Sjdp struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry; 300333965Sjdp 300433965Sjdp /* Allocate the structure if it has not already been allocated by a 300533965Sjdp subclass. */ 300633965Sjdp if (ret == (struct aout_link_hash_entry *) NULL) 300733965Sjdp ret = ((struct aout_link_hash_entry *) 300833965Sjdp bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry))); 300933965Sjdp if (ret == (struct aout_link_hash_entry *) NULL) 301033965Sjdp return (struct bfd_hash_entry *) ret; 301133965Sjdp 301233965Sjdp /* Call the allocation method of the superclass. */ 301333965Sjdp ret = ((struct aout_link_hash_entry *) 301433965Sjdp _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, 301533965Sjdp table, string)); 301633965Sjdp if (ret) 301733965Sjdp { 301833965Sjdp /* Set local fields. */ 301933965Sjdp ret->written = false; 302033965Sjdp ret->indx = -1; 302133965Sjdp } 302233965Sjdp 302333965Sjdp return (struct bfd_hash_entry *) ret; 302433965Sjdp} 302533965Sjdp 302633965Sjdp/* Initialize an a.out link hash table. */ 302733965Sjdp 302833965Sjdpboolean 302933965SjdpNAME(aout,link_hash_table_init) (table, abfd, newfunc) 303033965Sjdp struct aout_link_hash_table *table; 303133965Sjdp bfd *abfd; 303233965Sjdp struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, 303333965Sjdp struct bfd_hash_table *, 303433965Sjdp const char *)); 303533965Sjdp{ 303633965Sjdp return _bfd_link_hash_table_init (&table->root, abfd, newfunc); 303733965Sjdp} 303833965Sjdp 303933965Sjdp/* Create an a.out link hash table. */ 304033965Sjdp 304133965Sjdpstruct bfd_link_hash_table * 304233965SjdpNAME(aout,link_hash_table_create) (abfd) 304333965Sjdp bfd *abfd; 304433965Sjdp{ 304533965Sjdp struct aout_link_hash_table *ret; 304689857Sobrien bfd_size_type amt = sizeof (struct aout_link_hash_table); 304733965Sjdp 304889857Sobrien ret = (struct aout_link_hash_table *) bfd_alloc (abfd, amt); 304933965Sjdp if (ret == NULL) 305033965Sjdp return (struct bfd_link_hash_table *) NULL; 305133965Sjdp if (! NAME(aout,link_hash_table_init) (ret, abfd, 305233965Sjdp NAME(aout,link_hash_newfunc))) 305333965Sjdp { 305433965Sjdp free (ret); 305533965Sjdp return (struct bfd_link_hash_table *) NULL; 305633965Sjdp } 305733965Sjdp return &ret->root; 305833965Sjdp} 305933965Sjdp 306033965Sjdp/* Given an a.out BFD, add symbols to the global hash table as 306133965Sjdp appropriate. */ 306233965Sjdp 306333965Sjdpboolean 306433965SjdpNAME(aout,link_add_symbols) (abfd, info) 306533965Sjdp bfd *abfd; 306633965Sjdp struct bfd_link_info *info; 306733965Sjdp{ 306833965Sjdp switch (bfd_get_format (abfd)) 306933965Sjdp { 307033965Sjdp case bfd_object: 307133965Sjdp return aout_link_add_object_symbols (abfd, info); 307233965Sjdp case bfd_archive: 307333965Sjdp return _bfd_generic_link_add_archive_symbols 307433965Sjdp (abfd, info, aout_link_check_archive_element); 307533965Sjdp default: 307633965Sjdp bfd_set_error (bfd_error_wrong_format); 307733965Sjdp return false; 307833965Sjdp } 307933965Sjdp} 308033965Sjdp 308133965Sjdp/* Add symbols from an a.out object file. */ 308233965Sjdp 308333965Sjdpstatic boolean 308433965Sjdpaout_link_add_object_symbols (abfd, info) 308533965Sjdp bfd *abfd; 308633965Sjdp struct bfd_link_info *info; 308733965Sjdp{ 308833965Sjdp if (! aout_get_external_symbols (abfd)) 308933965Sjdp return false; 309033965Sjdp if (! aout_link_add_symbols (abfd, info)) 309133965Sjdp return false; 309233965Sjdp if (! info->keep_memory) 309333965Sjdp { 309433965Sjdp if (! aout_link_free_symbols (abfd)) 309533965Sjdp return false; 309633965Sjdp } 309733965Sjdp return true; 309833965Sjdp} 309933965Sjdp 310033965Sjdp/* Check a single archive element to see if we need to include it in 310133965Sjdp the link. *PNEEDED is set according to whether this element is 310233965Sjdp needed in the link or not. This is called from 310333965Sjdp _bfd_generic_link_add_archive_symbols. */ 310433965Sjdp 310533965Sjdpstatic boolean 310633965Sjdpaout_link_check_archive_element (abfd, info, pneeded) 310733965Sjdp bfd *abfd; 310833965Sjdp struct bfd_link_info *info; 310933965Sjdp boolean *pneeded; 311033965Sjdp{ 311133965Sjdp if (! aout_get_external_symbols (abfd)) 311233965Sjdp return false; 311333965Sjdp 311433965Sjdp if (! aout_link_check_ar_symbols (abfd, info, pneeded)) 311533965Sjdp return false; 311633965Sjdp 311733965Sjdp if (*pneeded) 311833965Sjdp { 311933965Sjdp if (! aout_link_add_symbols (abfd, info)) 312033965Sjdp return false; 312133965Sjdp } 312233965Sjdp 312333965Sjdp if (! info->keep_memory || ! *pneeded) 312433965Sjdp { 312533965Sjdp if (! aout_link_free_symbols (abfd)) 312633965Sjdp return false; 312733965Sjdp } 312833965Sjdp 312933965Sjdp return true; 313033965Sjdp} 313133965Sjdp 313233965Sjdp/* Free up the internal symbols read from an a.out file. */ 313333965Sjdp 313433965Sjdpstatic boolean 313533965Sjdpaout_link_free_symbols (abfd) 313633965Sjdp bfd *abfd; 313733965Sjdp{ 313833965Sjdp if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) 313933965Sjdp { 314033965Sjdp#ifdef USE_MMAP 314133965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 314233965Sjdp#else 314333965Sjdp free ((PTR) obj_aout_external_syms (abfd)); 314433965Sjdp#endif 314533965Sjdp obj_aout_external_syms (abfd) = (struct external_nlist *) NULL; 314633965Sjdp } 314733965Sjdp if (obj_aout_external_strings (abfd) != (char *) NULL) 314833965Sjdp { 314933965Sjdp#ifdef USE_MMAP 315033965Sjdp bfd_free_window (&obj_aout_string_window (abfd)); 315133965Sjdp#else 315233965Sjdp free ((PTR) obj_aout_external_strings (abfd)); 315333965Sjdp#endif 315433965Sjdp obj_aout_external_strings (abfd) = (char *) NULL; 315533965Sjdp } 315633965Sjdp return true; 315733965Sjdp} 315833965Sjdp 315933965Sjdp/* Look through the internal symbols to see if this object file should 316033965Sjdp be included in the link. We should include this object file if it 316133965Sjdp defines any symbols which are currently undefined. If this object 316233965Sjdp file defines a common symbol, then we may adjust the size of the 316333965Sjdp known symbol but we do not include the object file in the link 316433965Sjdp (unless there is some other reason to include it). */ 316533965Sjdp 316633965Sjdpstatic boolean 316733965Sjdpaout_link_check_ar_symbols (abfd, info, pneeded) 316833965Sjdp bfd *abfd; 316933965Sjdp struct bfd_link_info *info; 317033965Sjdp boolean *pneeded; 317133965Sjdp{ 317233965Sjdp register struct external_nlist *p; 317333965Sjdp struct external_nlist *pend; 317433965Sjdp char *strings; 317533965Sjdp 317633965Sjdp *pneeded = false; 317733965Sjdp 317833965Sjdp /* Look through all the symbols. */ 317933965Sjdp p = obj_aout_external_syms (abfd); 318033965Sjdp pend = p + obj_aout_external_sym_count (abfd); 318133965Sjdp strings = obj_aout_external_strings (abfd); 318233965Sjdp for (; p < pend; p++) 318333965Sjdp { 318489857Sobrien int type = H_GET_8 (abfd, p->e_type); 318533965Sjdp const char *name; 318633965Sjdp struct bfd_link_hash_entry *h; 318733965Sjdp 318833965Sjdp /* Ignore symbols that are not externally visible. This is an 318933965Sjdp optimization only, as we check the type more thoroughly 319033965Sjdp below. */ 319133965Sjdp if (((type & N_EXT) == 0 319233965Sjdp || (type & N_STAB) != 0 319333965Sjdp || type == N_FN) 319433965Sjdp && type != N_WEAKA 319533965Sjdp && type != N_WEAKT 319633965Sjdp && type != N_WEAKD 319733965Sjdp && type != N_WEAKB) 319833965Sjdp { 319933965Sjdp if (type == N_WARNING 320033965Sjdp || type == N_INDR) 320133965Sjdp ++p; 320233965Sjdp continue; 320333965Sjdp } 320433965Sjdp 320533965Sjdp name = strings + GET_WORD (abfd, p->e_strx); 320633965Sjdp h = bfd_link_hash_lookup (info->hash, name, false, false, true); 320733965Sjdp 320833965Sjdp /* We are only interested in symbols that are currently 320933965Sjdp undefined or common. */ 321033965Sjdp if (h == (struct bfd_link_hash_entry *) NULL 321133965Sjdp || (h->type != bfd_link_hash_undefined 321233965Sjdp && h->type != bfd_link_hash_common)) 321333965Sjdp { 321433965Sjdp if (type == (N_INDR | N_EXT)) 321533965Sjdp ++p; 321633965Sjdp continue; 321733965Sjdp } 321833965Sjdp 321933965Sjdp if (type == (N_TEXT | N_EXT) 322033965Sjdp || type == (N_DATA | N_EXT) 322133965Sjdp || type == (N_BSS | N_EXT) 322233965Sjdp || type == (N_ABS | N_EXT) 322333965Sjdp || type == (N_INDR | N_EXT)) 322433965Sjdp { 322533965Sjdp /* This object file defines this symbol. We must link it 322633965Sjdp in. This is true regardless of whether the current 322733965Sjdp definition of the symbol is undefined or common. If the 322833965Sjdp current definition is common, we have a case in which we 322933965Sjdp have already seen an object file including 323033965Sjdp int a; 323133965Sjdp and this object file from the archive includes 323233965Sjdp int a = 5; 323333965Sjdp In such a case we must include this object file. 323433965Sjdp 323533965Sjdp FIXME: The SunOS 4.1.3 linker will pull in the archive 323633965Sjdp element if the symbol is defined in the .data section, 323733965Sjdp but not if it is defined in the .text section. That 323833965Sjdp seems a bit crazy to me, and I haven't implemented it. 323933965Sjdp However, it might be correct. */ 324033965Sjdp if (! (*info->callbacks->add_archive_element) (info, abfd, name)) 324133965Sjdp return false; 324233965Sjdp *pneeded = true; 324333965Sjdp return true; 324433965Sjdp } 324533965Sjdp 324633965Sjdp if (type == (N_UNDF | N_EXT)) 324733965Sjdp { 324833965Sjdp bfd_vma value; 324933965Sjdp 325033965Sjdp value = GET_WORD (abfd, p->e_value); 325133965Sjdp if (value != 0) 325233965Sjdp { 325333965Sjdp /* This symbol is common in the object from the archive 325433965Sjdp file. */ 325533965Sjdp if (h->type == bfd_link_hash_undefined) 325633965Sjdp { 325733965Sjdp bfd *symbfd; 325833965Sjdp unsigned int power; 325933965Sjdp 326033965Sjdp symbfd = h->u.undef.abfd; 326133965Sjdp if (symbfd == (bfd *) NULL) 326233965Sjdp { 326333965Sjdp /* This symbol was created as undefined from 326433965Sjdp outside BFD. We assume that we should link 326533965Sjdp in the object file. This is done for the -u 326633965Sjdp option in the linker. */ 326733965Sjdp if (! (*info->callbacks->add_archive_element) (info, 326833965Sjdp abfd, 326933965Sjdp name)) 327033965Sjdp return false; 327133965Sjdp *pneeded = true; 327233965Sjdp return true; 327333965Sjdp } 327433965Sjdp /* Turn the current link symbol into a common 327533965Sjdp symbol. It is already on the undefs list. */ 327633965Sjdp h->type = bfd_link_hash_common; 327733965Sjdp h->u.c.p = ((struct bfd_link_hash_common_entry *) 327833965Sjdp bfd_hash_allocate (&info->hash->table, 327933965Sjdp sizeof (struct bfd_link_hash_common_entry))); 328033965Sjdp if (h->u.c.p == NULL) 328133965Sjdp return false; 328233965Sjdp 328333965Sjdp h->u.c.size = value; 328433965Sjdp 328533965Sjdp /* FIXME: This isn't quite right. The maximum 328633965Sjdp alignment of a common symbol should be set by the 328733965Sjdp architecture of the output file, not of the input 328833965Sjdp file. */ 328933965Sjdp power = bfd_log2 (value); 329033965Sjdp if (power > bfd_get_arch_info (abfd)->section_align_power) 329133965Sjdp power = bfd_get_arch_info (abfd)->section_align_power; 329233965Sjdp h->u.c.p->alignment_power = power; 329333965Sjdp 329433965Sjdp h->u.c.p->section = bfd_make_section_old_way (symbfd, 329533965Sjdp "COMMON"); 329633965Sjdp } 329733965Sjdp else 329833965Sjdp { 329933965Sjdp /* Adjust the size of the common symbol if 330033965Sjdp necessary. */ 330133965Sjdp if (value > h->u.c.size) 330233965Sjdp h->u.c.size = value; 330333965Sjdp } 330433965Sjdp } 330533965Sjdp } 330633965Sjdp 330733965Sjdp if (type == N_WEAKA 330833965Sjdp || type == N_WEAKT 330933965Sjdp || type == N_WEAKD 331033965Sjdp || type == N_WEAKB) 331133965Sjdp { 331233965Sjdp /* This symbol is weak but defined. We must pull it in if 331333965Sjdp the current link symbol is undefined, but we don't want 331433965Sjdp it if the current link symbol is common. */ 331533965Sjdp if (h->type == bfd_link_hash_undefined) 331633965Sjdp { 331733965Sjdp if (! (*info->callbacks->add_archive_element) (info, abfd, name)) 331833965Sjdp return false; 331933965Sjdp *pneeded = true; 332033965Sjdp return true; 332133965Sjdp } 332233965Sjdp } 332333965Sjdp } 332433965Sjdp 332533965Sjdp /* We do not need this object file. */ 332633965Sjdp return true; 332733965Sjdp} 332833965Sjdp 332933965Sjdp/* Add all symbols from an object file to the hash table. */ 333033965Sjdp 333133965Sjdpstatic boolean 333233965Sjdpaout_link_add_symbols (abfd, info) 333333965Sjdp bfd *abfd; 333433965Sjdp struct bfd_link_info *info; 333533965Sjdp{ 333633965Sjdp boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *, 333733965Sjdp const char *, flagword, asection *, 333833965Sjdp bfd_vma, const char *, boolean, 333933965Sjdp boolean, 334033965Sjdp struct bfd_link_hash_entry **)); 334133965Sjdp struct external_nlist *syms; 334233965Sjdp bfd_size_type sym_count; 334333965Sjdp char *strings; 334433965Sjdp boolean copy; 334533965Sjdp struct aout_link_hash_entry **sym_hash; 334633965Sjdp register struct external_nlist *p; 334733965Sjdp struct external_nlist *pend; 334889857Sobrien bfd_size_type amt; 334933965Sjdp 335033965Sjdp syms = obj_aout_external_syms (abfd); 335133965Sjdp sym_count = obj_aout_external_sym_count (abfd); 335233965Sjdp strings = obj_aout_external_strings (abfd); 335333965Sjdp if (info->keep_memory) 335433965Sjdp copy = false; 335533965Sjdp else 335633965Sjdp copy = true; 335733965Sjdp 335833965Sjdp if (aout_backend_info (abfd)->add_dynamic_symbols != NULL) 335933965Sjdp { 336033965Sjdp if (! ((*aout_backend_info (abfd)->add_dynamic_symbols) 336133965Sjdp (abfd, info, &syms, &sym_count, &strings))) 336233965Sjdp return false; 336333965Sjdp } 336433965Sjdp 336533965Sjdp /* We keep a list of the linker hash table entries that correspond 336633965Sjdp to particular symbols. We could just look them up in the hash 336733965Sjdp table, but keeping the list is more efficient. Perhaps this 336833965Sjdp should be conditional on info->keep_memory. */ 336989857Sobrien amt = sym_count * sizeof (struct aout_link_hash_entry *); 337089857Sobrien sym_hash = (struct aout_link_hash_entry **) bfd_alloc (abfd, amt); 337133965Sjdp if (sym_hash == NULL && sym_count != 0) 337233965Sjdp return false; 337333965Sjdp obj_aout_sym_hashes (abfd) = sym_hash; 337433965Sjdp 337533965Sjdp add_one_symbol = aout_backend_info (abfd)->add_one_symbol; 337633965Sjdp if (add_one_symbol == NULL) 337733965Sjdp add_one_symbol = _bfd_generic_link_add_one_symbol; 337833965Sjdp 337933965Sjdp p = syms; 338033965Sjdp pend = p + sym_count; 338133965Sjdp for (; p < pend; p++, sym_hash++) 338233965Sjdp { 338333965Sjdp int type; 338433965Sjdp const char *name; 338533965Sjdp bfd_vma value; 338633965Sjdp asection *section; 338733965Sjdp flagword flags; 338833965Sjdp const char *string; 338933965Sjdp 339033965Sjdp *sym_hash = NULL; 339133965Sjdp 339289857Sobrien type = H_GET_8 (abfd, p->e_type); 339333965Sjdp 339433965Sjdp /* Ignore debugging symbols. */ 339533965Sjdp if ((type & N_STAB) != 0) 339633965Sjdp continue; 339733965Sjdp 339833965Sjdp name = strings + GET_WORD (abfd, p->e_strx); 339933965Sjdp value = GET_WORD (abfd, p->e_value); 340033965Sjdp flags = BSF_GLOBAL; 340133965Sjdp string = NULL; 340233965Sjdp switch (type) 340333965Sjdp { 340433965Sjdp default: 340533965Sjdp abort (); 340633965Sjdp 340733965Sjdp case N_UNDF: 340833965Sjdp case N_ABS: 340933965Sjdp case N_TEXT: 341033965Sjdp case N_DATA: 341133965Sjdp case N_BSS: 341233965Sjdp case N_FN_SEQ: 341333965Sjdp case N_COMM: 341433965Sjdp case N_SETV: 341533965Sjdp case N_FN: 341633965Sjdp /* Ignore symbols that are not externally visible. */ 341733965Sjdp continue; 341833965Sjdp case N_INDR: 341933965Sjdp /* Ignore local indirect symbol. */ 342033965Sjdp ++p; 342133965Sjdp ++sym_hash; 342233965Sjdp continue; 342333965Sjdp 342433965Sjdp case N_UNDF | N_EXT: 342533965Sjdp if (value == 0) 342633965Sjdp { 342733965Sjdp section = bfd_und_section_ptr; 342833965Sjdp flags = 0; 342933965Sjdp } 343033965Sjdp else 343133965Sjdp section = bfd_com_section_ptr; 343233965Sjdp break; 343333965Sjdp case N_ABS | N_EXT: 343433965Sjdp section = bfd_abs_section_ptr; 343533965Sjdp break; 343633965Sjdp case N_TEXT | N_EXT: 343733965Sjdp section = obj_textsec (abfd); 343833965Sjdp value -= bfd_get_section_vma (abfd, section); 343933965Sjdp break; 344033965Sjdp case N_DATA | N_EXT: 344133965Sjdp case N_SETV | N_EXT: 344233965Sjdp /* Treat N_SETV symbols as N_DATA symbol; see comment in 344333965Sjdp translate_from_native_sym_flags. */ 344433965Sjdp section = obj_datasec (abfd); 344533965Sjdp value -= bfd_get_section_vma (abfd, section); 344633965Sjdp break; 344733965Sjdp case N_BSS | N_EXT: 344833965Sjdp section = obj_bsssec (abfd); 344933965Sjdp value -= bfd_get_section_vma (abfd, section); 345033965Sjdp break; 345133965Sjdp case N_INDR | N_EXT: 345233965Sjdp /* An indirect symbol. The next symbol is the symbol 345333965Sjdp which this one really is. */ 345433965Sjdp BFD_ASSERT (p + 1 < pend); 345533965Sjdp ++p; 345633965Sjdp string = strings + GET_WORD (abfd, p->e_strx); 345733965Sjdp section = bfd_ind_section_ptr; 345833965Sjdp flags |= BSF_INDIRECT; 345933965Sjdp break; 346033965Sjdp case N_COMM | N_EXT: 346133965Sjdp section = bfd_com_section_ptr; 346233965Sjdp break; 346333965Sjdp case N_SETA: case N_SETA | N_EXT: 346433965Sjdp section = bfd_abs_section_ptr; 346533965Sjdp flags |= BSF_CONSTRUCTOR; 346633965Sjdp break; 346733965Sjdp case N_SETT: case N_SETT | N_EXT: 346833965Sjdp section = obj_textsec (abfd); 346933965Sjdp flags |= BSF_CONSTRUCTOR; 347033965Sjdp value -= bfd_get_section_vma (abfd, section); 347133965Sjdp break; 347233965Sjdp case N_SETD: case N_SETD | N_EXT: 347333965Sjdp section = obj_datasec (abfd); 347433965Sjdp flags |= BSF_CONSTRUCTOR; 347533965Sjdp value -= bfd_get_section_vma (abfd, section); 347633965Sjdp break; 347733965Sjdp case N_SETB: case N_SETB | N_EXT: 347833965Sjdp section = obj_bsssec (abfd); 347933965Sjdp flags |= BSF_CONSTRUCTOR; 348033965Sjdp value -= bfd_get_section_vma (abfd, section); 348133965Sjdp break; 348233965Sjdp case N_WARNING: 348333965Sjdp /* A warning symbol. The next symbol is the one to warn 348433965Sjdp about. */ 348533965Sjdp BFD_ASSERT (p + 1 < pend); 348633965Sjdp ++p; 348733965Sjdp string = name; 348833965Sjdp name = strings + GET_WORD (abfd, p->e_strx); 348933965Sjdp section = bfd_und_section_ptr; 349033965Sjdp flags |= BSF_WARNING; 349133965Sjdp break; 349233965Sjdp case N_WEAKU: 349333965Sjdp section = bfd_und_section_ptr; 349433965Sjdp flags = BSF_WEAK; 349533965Sjdp break; 349633965Sjdp case N_WEAKA: 349733965Sjdp section = bfd_abs_section_ptr; 349833965Sjdp flags = BSF_WEAK; 349933965Sjdp break; 350033965Sjdp case N_WEAKT: 350133965Sjdp section = obj_textsec (abfd); 350233965Sjdp value -= bfd_get_section_vma (abfd, section); 350333965Sjdp flags = BSF_WEAK; 350433965Sjdp break; 350533965Sjdp case N_WEAKD: 350633965Sjdp section = obj_datasec (abfd); 350733965Sjdp value -= bfd_get_section_vma (abfd, section); 350833965Sjdp flags = BSF_WEAK; 350933965Sjdp break; 351033965Sjdp case N_WEAKB: 351133965Sjdp section = obj_bsssec (abfd); 351233965Sjdp value -= bfd_get_section_vma (abfd, section); 351333965Sjdp flags = BSF_WEAK; 351433965Sjdp break; 351533965Sjdp } 351633965Sjdp 351733965Sjdp if (! ((*add_one_symbol) 351833965Sjdp (info, abfd, name, flags, section, value, string, copy, false, 351933965Sjdp (struct bfd_link_hash_entry **) sym_hash))) 352033965Sjdp return false; 352133965Sjdp 352233965Sjdp /* Restrict the maximum alignment of a common symbol based on 352333965Sjdp the architecture, since a.out has no way to represent 352433965Sjdp alignment requirements of a section in a .o file. FIXME: 352533965Sjdp This isn't quite right: it should use the architecture of the 352633965Sjdp output file, not the input files. */ 352733965Sjdp if ((*sym_hash)->root.type == bfd_link_hash_common 352833965Sjdp && ((*sym_hash)->root.u.c.p->alignment_power > 352933965Sjdp bfd_get_arch_info (abfd)->section_align_power)) 353033965Sjdp (*sym_hash)->root.u.c.p->alignment_power = 353133965Sjdp bfd_get_arch_info (abfd)->section_align_power; 353233965Sjdp 353333965Sjdp /* If this is a set symbol, and we are not building sets, then 353433965Sjdp it is possible for the hash entry to not have been set. In 353533965Sjdp such a case, treat the symbol as not globally defined. */ 353633965Sjdp if ((*sym_hash)->root.type == bfd_link_hash_new) 353733965Sjdp { 353833965Sjdp BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0); 353933965Sjdp *sym_hash = NULL; 354033965Sjdp } 354133965Sjdp 354233965Sjdp if (type == (N_INDR | N_EXT) || type == N_WARNING) 354333965Sjdp ++sym_hash; 354433965Sjdp } 354533965Sjdp 354633965Sjdp return true; 354733965Sjdp} 354833965Sjdp 354933965Sjdp/* A hash table used for header files with N_BINCL entries. */ 355033965Sjdp 355133965Sjdpstruct aout_link_includes_table 355233965Sjdp{ 355333965Sjdp struct bfd_hash_table root; 355433965Sjdp}; 355533965Sjdp 355633965Sjdp/* A linked list of totals that we have found for a particular header 355733965Sjdp file. */ 355833965Sjdp 355933965Sjdpstruct aout_link_includes_totals 356033965Sjdp{ 356133965Sjdp struct aout_link_includes_totals *next; 356233965Sjdp bfd_vma total; 356333965Sjdp}; 356433965Sjdp 356533965Sjdp/* An entry in the header file hash table. */ 356633965Sjdp 356733965Sjdpstruct aout_link_includes_entry 356833965Sjdp{ 356933965Sjdp struct bfd_hash_entry root; 357033965Sjdp /* List of totals we have found for this file. */ 357133965Sjdp struct aout_link_includes_totals *totals; 357233965Sjdp}; 357333965Sjdp 357433965Sjdp/* Look up an entry in an the header file hash table. */ 357533965Sjdp 357689857Sobrien#define aout_link_includes_lookup(table, string, create, copy) \ 357789857Sobrien ((struct aout_link_includes_entry *) \ 357833965Sjdp bfd_hash_lookup (&(table)->root, (string), (create), (copy))) 357933965Sjdp 358033965Sjdp/* During the final link step we need to pass around a bunch of 358133965Sjdp information, so we do it in an instance of this structure. */ 358233965Sjdp 358333965Sjdpstruct aout_final_link_info 358433965Sjdp{ 358533965Sjdp /* General link information. */ 358633965Sjdp struct bfd_link_info *info; 358733965Sjdp /* Output bfd. */ 358833965Sjdp bfd *output_bfd; 358933965Sjdp /* Reloc file positions. */ 359033965Sjdp file_ptr treloff, dreloff; 359133965Sjdp /* File position of symbols. */ 359233965Sjdp file_ptr symoff; 359333965Sjdp /* String table. */ 359433965Sjdp struct bfd_strtab_hash *strtab; 359533965Sjdp /* Header file hash table. */ 359633965Sjdp struct aout_link_includes_table includes; 359733965Sjdp /* A buffer large enough to hold the contents of any section. */ 359833965Sjdp bfd_byte *contents; 359933965Sjdp /* A buffer large enough to hold the relocs of any section. */ 360033965Sjdp PTR relocs; 360133965Sjdp /* A buffer large enough to hold the symbol map of any input BFD. */ 360233965Sjdp int *symbol_map; 360333965Sjdp /* A buffer large enough to hold output symbols of any input BFD. */ 360433965Sjdp struct external_nlist *output_syms; 360533965Sjdp}; 360633965Sjdp 360733965Sjdpstatic struct bfd_hash_entry *aout_link_includes_newfunc 360833965Sjdp PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 360933965Sjdpstatic boolean aout_link_input_bfd 361033965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd)); 361133965Sjdpstatic boolean aout_link_write_symbols 361233965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd)); 361333965Sjdpstatic boolean aout_link_write_other_symbol 361433965Sjdp PARAMS ((struct aout_link_hash_entry *, PTR)); 361533965Sjdpstatic boolean aout_link_input_section 361633965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd, 361733965Sjdp asection *input_section, file_ptr *reloff_ptr, 361833965Sjdp bfd_size_type rel_size)); 361933965Sjdpstatic boolean aout_link_input_section_std 362033965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd, 362133965Sjdp asection *input_section, struct reloc_std_external *, 362233965Sjdp bfd_size_type rel_size, bfd_byte *contents)); 362333965Sjdpstatic boolean aout_link_input_section_ext 362433965Sjdp PARAMS ((struct aout_final_link_info *, bfd *input_bfd, 362533965Sjdp asection *input_section, struct reloc_ext_external *, 362633965Sjdp bfd_size_type rel_size, bfd_byte *contents)); 362733965Sjdpstatic INLINE asection *aout_reloc_index_to_section 362833965Sjdp PARAMS ((bfd *, int)); 362933965Sjdpstatic boolean aout_link_reloc_link_order 363033965Sjdp PARAMS ((struct aout_final_link_info *, asection *, 363133965Sjdp struct bfd_link_order *)); 363233965Sjdp 363333965Sjdp/* The function to create a new entry in the header file hash table. */ 363433965Sjdp 363533965Sjdpstatic struct bfd_hash_entry * 363633965Sjdpaout_link_includes_newfunc (entry, table, string) 363733965Sjdp struct bfd_hash_entry *entry; 363833965Sjdp struct bfd_hash_table *table; 363933965Sjdp const char *string; 364033965Sjdp{ 364133965Sjdp struct aout_link_includes_entry *ret = 364233965Sjdp (struct aout_link_includes_entry *) entry; 364333965Sjdp 364433965Sjdp /* Allocate the structure if it has not already been allocated by a 364533965Sjdp subclass. */ 364633965Sjdp if (ret == (struct aout_link_includes_entry *) NULL) 364733965Sjdp ret = ((struct aout_link_includes_entry *) 364833965Sjdp bfd_hash_allocate (table, 364933965Sjdp sizeof (struct aout_link_includes_entry))); 365033965Sjdp if (ret == (struct aout_link_includes_entry *) NULL) 365133965Sjdp return (struct bfd_hash_entry *) ret; 365233965Sjdp 365333965Sjdp /* Call the allocation method of the superclass. */ 365433965Sjdp ret = ((struct aout_link_includes_entry *) 365533965Sjdp bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); 365633965Sjdp if (ret) 365733965Sjdp { 365833965Sjdp /* Set local fields. */ 365933965Sjdp ret->totals = NULL; 366033965Sjdp } 366133965Sjdp 366233965Sjdp return (struct bfd_hash_entry *) ret; 366333965Sjdp} 366433965Sjdp 366533965Sjdp/* Do the final link step. This is called on the output BFD. The 366633965Sjdp INFO structure should point to a list of BFDs linked through the 366733965Sjdp link_next field which can be used to find each BFD which takes part 366833965Sjdp in the output. Also, each section in ABFD should point to a list 366933965Sjdp of bfd_link_order structures which list all the input sections for 367033965Sjdp the output section. */ 367133965Sjdp 367233965Sjdpboolean 367333965SjdpNAME(aout,final_link) (abfd, info, callback) 367433965Sjdp bfd *abfd; 367533965Sjdp struct bfd_link_info *info; 367633965Sjdp void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); 367733965Sjdp{ 367833965Sjdp struct aout_final_link_info aout_info; 367933965Sjdp boolean includes_hash_initialized = false; 368033965Sjdp register bfd *sub; 368133965Sjdp bfd_size_type trsize, drsize; 368289857Sobrien bfd_size_type max_contents_size; 368389857Sobrien bfd_size_type max_relocs_size; 368489857Sobrien bfd_size_type max_sym_count; 368533965Sjdp bfd_size_type text_size; 368633965Sjdp file_ptr text_end; 368733965Sjdp register struct bfd_link_order *p; 368833965Sjdp asection *o; 368933965Sjdp boolean have_link_order_relocs; 369033965Sjdp 369133965Sjdp if (info->shared) 369233965Sjdp abfd->flags |= DYNAMIC; 369333965Sjdp 369433965Sjdp aout_info.info = info; 369533965Sjdp aout_info.output_bfd = abfd; 369633965Sjdp aout_info.contents = NULL; 369733965Sjdp aout_info.relocs = NULL; 369833965Sjdp aout_info.symbol_map = NULL; 369933965Sjdp aout_info.output_syms = NULL; 370033965Sjdp 370133965Sjdp if (! bfd_hash_table_init_n (&aout_info.includes.root, 370233965Sjdp aout_link_includes_newfunc, 370333965Sjdp 251)) 370433965Sjdp goto error_return; 370533965Sjdp includes_hash_initialized = true; 370633965Sjdp 370733965Sjdp /* Figure out the largest section size. Also, if generating 370833965Sjdp relocateable output, count the relocs. */ 370933965Sjdp trsize = 0; 371033965Sjdp drsize = 0; 371133965Sjdp max_contents_size = 0; 371233965Sjdp max_relocs_size = 0; 371333965Sjdp max_sym_count = 0; 371433965Sjdp for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) 371533965Sjdp { 371689857Sobrien bfd_size_type sz; 371733965Sjdp 371833965Sjdp if (info->relocateable) 371933965Sjdp { 372033965Sjdp if (bfd_get_flavour (sub) == bfd_target_aout_flavour) 372133965Sjdp { 372233965Sjdp trsize += exec_hdr (sub)->a_trsize; 372333965Sjdp drsize += exec_hdr (sub)->a_drsize; 372433965Sjdp } 372533965Sjdp else 372633965Sjdp { 372733965Sjdp /* FIXME: We need to identify the .text and .data sections 372833965Sjdp and call get_reloc_upper_bound and canonicalize_reloc to 372933965Sjdp work out the number of relocs needed, and then multiply 373033965Sjdp by the reloc size. */ 373133965Sjdp (*_bfd_error_handler) 373260484Sobrien (_("%s: relocateable link from %s to %s not supported"), 373333965Sjdp bfd_get_filename (abfd), 373433965Sjdp sub->xvec->name, abfd->xvec->name); 373533965Sjdp bfd_set_error (bfd_error_invalid_operation); 373633965Sjdp goto error_return; 373733965Sjdp } 373833965Sjdp } 373933965Sjdp 374033965Sjdp if (bfd_get_flavour (sub) == bfd_target_aout_flavour) 374133965Sjdp { 374233965Sjdp sz = bfd_section_size (sub, obj_textsec (sub)); 374333965Sjdp if (sz > max_contents_size) 374433965Sjdp max_contents_size = sz; 374533965Sjdp sz = bfd_section_size (sub, obj_datasec (sub)); 374633965Sjdp if (sz > max_contents_size) 374733965Sjdp max_contents_size = sz; 374833965Sjdp 374933965Sjdp sz = exec_hdr (sub)->a_trsize; 375033965Sjdp if (sz > max_relocs_size) 375133965Sjdp max_relocs_size = sz; 375233965Sjdp sz = exec_hdr (sub)->a_drsize; 375333965Sjdp if (sz > max_relocs_size) 375433965Sjdp max_relocs_size = sz; 375533965Sjdp 375633965Sjdp sz = obj_aout_external_sym_count (sub); 375733965Sjdp if (sz > max_sym_count) 375833965Sjdp max_sym_count = sz; 375933965Sjdp } 376033965Sjdp } 376133965Sjdp 376233965Sjdp if (info->relocateable) 376333965Sjdp { 376433965Sjdp if (obj_textsec (abfd) != (asection *) NULL) 376533965Sjdp trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd) 376633965Sjdp ->link_order_head) 376733965Sjdp * obj_reloc_entry_size (abfd)); 376833965Sjdp if (obj_datasec (abfd) != (asection *) NULL) 376933965Sjdp drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd) 377033965Sjdp ->link_order_head) 377133965Sjdp * obj_reloc_entry_size (abfd)); 377233965Sjdp } 377333965Sjdp 377433965Sjdp exec_hdr (abfd)->a_trsize = trsize; 377533965Sjdp exec_hdr (abfd)->a_drsize = drsize; 377633965Sjdp 377733965Sjdp exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd); 377833965Sjdp 377933965Sjdp /* Adjust the section sizes and vmas according to the magic number. 378033965Sjdp This sets a_text, a_data and a_bss in the exec_hdr and sets the 378133965Sjdp filepos for each section. */ 378233965Sjdp if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) 378333965Sjdp goto error_return; 378433965Sjdp 378533965Sjdp /* The relocation and symbol file positions differ among a.out 378633965Sjdp targets. We are passed a callback routine from the backend 378733965Sjdp specific code to handle this. 378833965Sjdp FIXME: At this point we do not know how much space the symbol 378933965Sjdp table will require. This will not work for any (nonstandard) 379033965Sjdp a.out target that needs to know the symbol table size before it 379133965Sjdp can compute the relocation file positions. This may or may not 379233965Sjdp be the case for the hp300hpux target, for example. */ 379333965Sjdp (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff, 379433965Sjdp &aout_info.symoff); 379533965Sjdp obj_textsec (abfd)->rel_filepos = aout_info.treloff; 379633965Sjdp obj_datasec (abfd)->rel_filepos = aout_info.dreloff; 379733965Sjdp obj_sym_filepos (abfd) = aout_info.symoff; 379833965Sjdp 379933965Sjdp /* We keep a count of the symbols as we output them. */ 380033965Sjdp obj_aout_external_sym_count (abfd) = 0; 380133965Sjdp 380233965Sjdp /* We accumulate the string table as we write out the symbols. */ 380333965Sjdp aout_info.strtab = _bfd_stringtab_init (); 380433965Sjdp if (aout_info.strtab == NULL) 380533965Sjdp goto error_return; 380633965Sjdp 380733965Sjdp /* Allocate buffers to hold section contents and relocs. */ 380833965Sjdp aout_info.contents = (bfd_byte *) bfd_malloc (max_contents_size); 380933965Sjdp aout_info.relocs = (PTR) bfd_malloc (max_relocs_size); 381033965Sjdp aout_info.symbol_map = (int *) bfd_malloc (max_sym_count * sizeof (int *)); 381133965Sjdp aout_info.output_syms = ((struct external_nlist *) 381233965Sjdp bfd_malloc ((max_sym_count + 1) 381333965Sjdp * sizeof (struct external_nlist))); 381433965Sjdp if ((aout_info.contents == NULL && max_contents_size != 0) 381533965Sjdp || (aout_info.relocs == NULL && max_relocs_size != 0) 381633965Sjdp || (aout_info.symbol_map == NULL && max_sym_count != 0) 381733965Sjdp || aout_info.output_syms == NULL) 381833965Sjdp goto error_return; 381933965Sjdp 382033965Sjdp /* If we have a symbol named __DYNAMIC, force it out now. This is 382133965Sjdp required by SunOS. Doing this here rather than in sunos.c is a 382233965Sjdp hack, but it's easier than exporting everything which would be 382333965Sjdp needed. */ 382433965Sjdp { 382533965Sjdp struct aout_link_hash_entry *h; 382633965Sjdp 382733965Sjdp h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC", 382833965Sjdp false, false, false); 382933965Sjdp if (h != NULL) 383033965Sjdp aout_link_write_other_symbol (h, &aout_info); 383133965Sjdp } 383233965Sjdp 383333965Sjdp /* The most time efficient way to do the link would be to read all 383433965Sjdp the input object files into memory and then sort out the 383533965Sjdp information into the output file. Unfortunately, that will 383633965Sjdp probably use too much memory. Another method would be to step 383733965Sjdp through everything that composes the text section and write it 383833965Sjdp out, and then everything that composes the data section and write 383933965Sjdp it out, and then write out the relocs, and then write out the 384033965Sjdp symbols. Unfortunately, that requires reading stuff from each 384133965Sjdp input file several times, and we will not be able to keep all the 384233965Sjdp input files open simultaneously, and reopening them will be slow. 384333965Sjdp 384433965Sjdp What we do is basically process one input file at a time. We do 384533965Sjdp everything we need to do with an input file once--copy over the 384633965Sjdp section contents, handle the relocation information, and write 384733965Sjdp out the symbols--and then we throw away the information we read 384833965Sjdp from it. This approach requires a lot of lseeks of the output 384933965Sjdp file, which is unfortunate but still faster than reopening a lot 385033965Sjdp of files. 385133965Sjdp 385233965Sjdp We use the output_has_begun field of the input BFDs to see 385333965Sjdp whether we have already handled it. */ 385433965Sjdp for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) 385533965Sjdp sub->output_has_begun = false; 385633965Sjdp 385733965Sjdp /* Mark all sections which are to be included in the link. This 385833965Sjdp will normally be every section. We need to do this so that we 385933965Sjdp can identify any sections which the linker has decided to not 386033965Sjdp include. */ 386133965Sjdp for (o = abfd->sections; o != NULL; o = o->next) 386233965Sjdp { 386333965Sjdp for (p = o->link_order_head; p != NULL; p = p->next) 386433965Sjdp { 386533965Sjdp if (p->type == bfd_indirect_link_order) 386633965Sjdp p->u.indirect.section->linker_mark = true; 386733965Sjdp } 386833965Sjdp } 386933965Sjdp 387033965Sjdp have_link_order_relocs = false; 387133965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 387233965Sjdp { 387333965Sjdp for (p = o->link_order_head; 387433965Sjdp p != (struct bfd_link_order *) NULL; 387533965Sjdp p = p->next) 387633965Sjdp { 387733965Sjdp if (p->type == bfd_indirect_link_order 387833965Sjdp && (bfd_get_flavour (p->u.indirect.section->owner) 387933965Sjdp == bfd_target_aout_flavour)) 388033965Sjdp { 388133965Sjdp bfd *input_bfd; 388233965Sjdp 388333965Sjdp input_bfd = p->u.indirect.section->owner; 388433965Sjdp if (! input_bfd->output_has_begun) 388533965Sjdp { 388633965Sjdp if (! aout_link_input_bfd (&aout_info, input_bfd)) 388733965Sjdp goto error_return; 388833965Sjdp input_bfd->output_has_begun = true; 388933965Sjdp } 389033965Sjdp } 389133965Sjdp else if (p->type == bfd_section_reloc_link_order 389233965Sjdp || p->type == bfd_symbol_reloc_link_order) 389333965Sjdp { 389433965Sjdp /* These are handled below. */ 389533965Sjdp have_link_order_relocs = true; 389633965Sjdp } 389733965Sjdp else 389833965Sjdp { 389933965Sjdp if (! _bfd_default_link_order (abfd, info, o, p)) 390033965Sjdp goto error_return; 390133965Sjdp } 390233965Sjdp } 390333965Sjdp } 390433965Sjdp 390533965Sjdp /* Write out any symbols that we have not already written out. */ 390633965Sjdp aout_link_hash_traverse (aout_hash_table (info), 390733965Sjdp aout_link_write_other_symbol, 390833965Sjdp (PTR) &aout_info); 390933965Sjdp 391033965Sjdp /* Now handle any relocs we were asked to create by the linker. 391133965Sjdp These did not come from any input file. We must do these after 391233965Sjdp we have written out all the symbols, so that we know the symbol 391333965Sjdp indices to use. */ 391433965Sjdp if (have_link_order_relocs) 391533965Sjdp { 391633965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 391733965Sjdp { 391833965Sjdp for (p = o->link_order_head; 391933965Sjdp p != (struct bfd_link_order *) NULL; 392033965Sjdp p = p->next) 392133965Sjdp { 392233965Sjdp if (p->type == bfd_section_reloc_link_order 392333965Sjdp || p->type == bfd_symbol_reloc_link_order) 392433965Sjdp { 392533965Sjdp if (! aout_link_reloc_link_order (&aout_info, o, p)) 392633965Sjdp goto error_return; 392733965Sjdp } 392833965Sjdp } 392933965Sjdp } 393033965Sjdp } 393133965Sjdp 393233965Sjdp if (aout_info.contents != NULL) 393333965Sjdp { 393433965Sjdp free (aout_info.contents); 393533965Sjdp aout_info.contents = NULL; 393633965Sjdp } 393733965Sjdp if (aout_info.relocs != NULL) 393833965Sjdp { 393933965Sjdp free (aout_info.relocs); 394033965Sjdp aout_info.relocs = NULL; 394133965Sjdp } 394233965Sjdp if (aout_info.symbol_map != NULL) 394333965Sjdp { 394433965Sjdp free (aout_info.symbol_map); 394533965Sjdp aout_info.symbol_map = NULL; 394633965Sjdp } 394733965Sjdp if (aout_info.output_syms != NULL) 394833965Sjdp { 394933965Sjdp free (aout_info.output_syms); 395033965Sjdp aout_info.output_syms = NULL; 395133965Sjdp } 395233965Sjdp if (includes_hash_initialized) 395333965Sjdp { 395433965Sjdp bfd_hash_table_free (&aout_info.includes.root); 395533965Sjdp includes_hash_initialized = false; 395633965Sjdp } 395733965Sjdp 395833965Sjdp /* Finish up any dynamic linking we may be doing. */ 395933965Sjdp if (aout_backend_info (abfd)->finish_dynamic_link != NULL) 396033965Sjdp { 396133965Sjdp if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info)) 396233965Sjdp goto error_return; 396333965Sjdp } 396433965Sjdp 396533965Sjdp /* Update the header information. */ 396633965Sjdp abfd->symcount = obj_aout_external_sym_count (abfd); 396733965Sjdp exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE; 396833965Sjdp obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms; 396933965Sjdp obj_textsec (abfd)->reloc_count = 397033965Sjdp exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); 397133965Sjdp obj_datasec (abfd)->reloc_count = 397233965Sjdp exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); 397333965Sjdp 397438889Sjdp /* Write out the string table, unless there are no symbols. */ 397538889Sjdp if (abfd->symcount > 0) 397638889Sjdp { 397738889Sjdp if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 397838889Sjdp || ! emit_stringtab (abfd, aout_info.strtab)) 397938889Sjdp goto error_return; 398038889Sjdp } 398138889Sjdp else if (obj_textsec (abfd)->reloc_count == 0 398238889Sjdp && obj_datasec (abfd)->reloc_count == 0) 398338889Sjdp { 398438889Sjdp bfd_byte b; 398589857Sobrien file_ptr pos; 398633965Sjdp 398738889Sjdp b = 0; 398889857Sobrien pos = obj_datasec (abfd)->filepos + exec_hdr (abfd)->a_data - 1; 398989857Sobrien if (bfd_seek (abfd, pos, SEEK_SET) != 0 399089857Sobrien || bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1) 399138889Sjdp goto error_return; 399238889Sjdp } 399338889Sjdp 399438889Sjdp return true; 399538889Sjdp 399633965Sjdp error_return: 399733965Sjdp if (aout_info.contents != NULL) 399833965Sjdp free (aout_info.contents); 399933965Sjdp if (aout_info.relocs != NULL) 400033965Sjdp free (aout_info.relocs); 400133965Sjdp if (aout_info.symbol_map != NULL) 400233965Sjdp free (aout_info.symbol_map); 400333965Sjdp if (aout_info.output_syms != NULL) 400433965Sjdp free (aout_info.output_syms); 400533965Sjdp if (includes_hash_initialized) 400633965Sjdp bfd_hash_table_free (&aout_info.includes.root); 400733965Sjdp return false; 400833965Sjdp} 400933965Sjdp 401033965Sjdp/* Link an a.out input BFD into the output file. */ 401133965Sjdp 401233965Sjdpstatic boolean 401333965Sjdpaout_link_input_bfd (finfo, input_bfd) 401433965Sjdp struct aout_final_link_info *finfo; 401533965Sjdp bfd *input_bfd; 401633965Sjdp{ 401733965Sjdp bfd_size_type sym_count; 401833965Sjdp 401933965Sjdp BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object); 402033965Sjdp 402133965Sjdp /* If this is a dynamic object, it may need special handling. */ 402233965Sjdp if ((input_bfd->flags & DYNAMIC) != 0 402333965Sjdp && aout_backend_info (input_bfd)->link_dynamic_object != NULL) 402433965Sjdp { 402533965Sjdp return ((*aout_backend_info (input_bfd)->link_dynamic_object) 402633965Sjdp (finfo->info, input_bfd)); 402733965Sjdp } 402833965Sjdp 402933965Sjdp /* Get the symbols. We probably have them already, unless 403033965Sjdp finfo->info->keep_memory is false. */ 403133965Sjdp if (! aout_get_external_symbols (input_bfd)) 403233965Sjdp return false; 403333965Sjdp 403433965Sjdp sym_count = obj_aout_external_sym_count (input_bfd); 403533965Sjdp 403633965Sjdp /* Write out the symbols and get a map of the new indices. The map 403733965Sjdp is placed into finfo->symbol_map. */ 403833965Sjdp if (! aout_link_write_symbols (finfo, input_bfd)) 403933965Sjdp return false; 404033965Sjdp 404133965Sjdp /* Relocate and write out the sections. These functions use the 404233965Sjdp symbol map created by aout_link_write_symbols. The linker_mark 404333965Sjdp field will be set if these sections are to be included in the 404433965Sjdp link, which will normally be the case. */ 404533965Sjdp if (obj_textsec (input_bfd)->linker_mark) 404633965Sjdp { 404733965Sjdp if (! aout_link_input_section (finfo, input_bfd, 404833965Sjdp obj_textsec (input_bfd), 404933965Sjdp &finfo->treloff, 405033965Sjdp exec_hdr (input_bfd)->a_trsize)) 405133965Sjdp return false; 405233965Sjdp } 405333965Sjdp if (obj_datasec (input_bfd)->linker_mark) 405433965Sjdp { 405533965Sjdp if (! aout_link_input_section (finfo, input_bfd, 405633965Sjdp obj_datasec (input_bfd), 405733965Sjdp &finfo->dreloff, 405833965Sjdp exec_hdr (input_bfd)->a_drsize)) 405933965Sjdp return false; 406033965Sjdp } 406133965Sjdp 406233965Sjdp /* If we are not keeping memory, we don't need the symbols any 406333965Sjdp longer. We still need them if we are keeping memory, because the 406433965Sjdp strings in the hash table point into them. */ 406533965Sjdp if (! finfo->info->keep_memory) 406633965Sjdp { 406733965Sjdp if (! aout_link_free_symbols (input_bfd)) 406833965Sjdp return false; 406933965Sjdp } 407033965Sjdp 407133965Sjdp return true; 407233965Sjdp} 407333965Sjdp 407433965Sjdp/* Adjust and write out the symbols for an a.out file. Set the new 407533965Sjdp symbol indices into a symbol_map. */ 407633965Sjdp 407733965Sjdpstatic boolean 407833965Sjdpaout_link_write_symbols (finfo, input_bfd) 407933965Sjdp struct aout_final_link_info *finfo; 408033965Sjdp bfd *input_bfd; 408133965Sjdp{ 408233965Sjdp bfd *output_bfd; 408333965Sjdp bfd_size_type sym_count; 408433965Sjdp char *strings; 408533965Sjdp enum bfd_link_strip strip; 408633965Sjdp enum bfd_link_discard discard; 408733965Sjdp struct external_nlist *outsym; 408833965Sjdp bfd_size_type strtab_index; 408933965Sjdp register struct external_nlist *sym; 409033965Sjdp struct external_nlist *sym_end; 409133965Sjdp struct aout_link_hash_entry **sym_hash; 409233965Sjdp int *symbol_map; 409333965Sjdp boolean pass; 409433965Sjdp boolean skip_next; 409533965Sjdp 409633965Sjdp output_bfd = finfo->output_bfd; 409733965Sjdp sym_count = obj_aout_external_sym_count (input_bfd); 409833965Sjdp strings = obj_aout_external_strings (input_bfd); 409933965Sjdp strip = finfo->info->strip; 410033965Sjdp discard = finfo->info->discard; 410133965Sjdp outsym = finfo->output_syms; 410233965Sjdp 410333965Sjdp /* First write out a symbol for this object file, unless we are 410433965Sjdp discarding such symbols. */ 410533965Sjdp if (strip != strip_all 410633965Sjdp && (strip != strip_some 410733965Sjdp || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename, 410833965Sjdp false, false) != NULL) 410933965Sjdp && discard != discard_all) 411033965Sjdp { 411189857Sobrien H_PUT_8 (output_bfd, N_TEXT, outsym->e_type); 411289857Sobrien H_PUT_8 (output_bfd, 0, outsym->e_other); 411389857Sobrien H_PUT_16 (output_bfd, 0, outsym->e_desc); 411433965Sjdp strtab_index = add_to_stringtab (output_bfd, finfo->strtab, 411533965Sjdp input_bfd->filename, false); 411633965Sjdp if (strtab_index == (bfd_size_type) -1) 411733965Sjdp return false; 411833965Sjdp PUT_WORD (output_bfd, strtab_index, outsym->e_strx); 411933965Sjdp PUT_WORD (output_bfd, 412033965Sjdp (bfd_get_section_vma (output_bfd, 412133965Sjdp obj_textsec (input_bfd)->output_section) 412233965Sjdp + obj_textsec (input_bfd)->output_offset), 412333965Sjdp outsym->e_value); 412433965Sjdp ++obj_aout_external_sym_count (output_bfd); 412533965Sjdp ++outsym; 412633965Sjdp } 412733965Sjdp 412833965Sjdp pass = false; 412933965Sjdp skip_next = false; 413033965Sjdp sym = obj_aout_external_syms (input_bfd); 413133965Sjdp sym_end = sym + sym_count; 413233965Sjdp sym_hash = obj_aout_sym_hashes (input_bfd); 413333965Sjdp symbol_map = finfo->symbol_map; 413489857Sobrien memset (symbol_map, 0, (size_t) sym_count * sizeof *symbol_map); 413533965Sjdp for (; sym < sym_end; sym++, sym_hash++, symbol_map++) 413633965Sjdp { 413733965Sjdp const char *name; 413833965Sjdp int type; 413933965Sjdp struct aout_link_hash_entry *h; 414033965Sjdp boolean skip; 414133965Sjdp asection *symsec; 414233965Sjdp bfd_vma val = 0; 414333965Sjdp boolean copy; 414433965Sjdp 414533965Sjdp /* We set *symbol_map to 0 above for all symbols. If it has 414633965Sjdp already been set to -1 for this symbol, it means that we are 414733965Sjdp discarding it because it appears in a duplicate header file. 414833965Sjdp See the N_BINCL code below. */ 414933965Sjdp if (*symbol_map == -1) 415033965Sjdp continue; 415133965Sjdp 415233965Sjdp /* Initialize *symbol_map to -1, which means that the symbol was 415333965Sjdp not copied into the output file. We will change it later if 415433965Sjdp we do copy the symbol over. */ 415533965Sjdp *symbol_map = -1; 415633965Sjdp 415789857Sobrien type = H_GET_8 (input_bfd, sym->e_type); 415833965Sjdp name = strings + GET_WORD (input_bfd, sym->e_strx); 415933965Sjdp 416033965Sjdp h = NULL; 416133965Sjdp 416233965Sjdp if (pass) 416333965Sjdp { 416433965Sjdp /* Pass this symbol through. It is the target of an 416533965Sjdp indirect or warning symbol. */ 416633965Sjdp val = GET_WORD (input_bfd, sym->e_value); 416733965Sjdp pass = false; 416833965Sjdp } 416933965Sjdp else if (skip_next) 417033965Sjdp { 417133965Sjdp /* Skip this symbol, which is the target of an indirect 417233965Sjdp symbol that we have changed to no longer be an indirect 417333965Sjdp symbol. */ 417433965Sjdp skip_next = false; 417533965Sjdp continue; 417633965Sjdp } 417733965Sjdp else 417833965Sjdp { 417933965Sjdp struct aout_link_hash_entry *hresolve; 418033965Sjdp 418133965Sjdp /* We have saved the hash table entry for this symbol, if 418233965Sjdp there is one. Note that we could just look it up again 418333965Sjdp in the hash table, provided we first check that it is an 418477298Sobrien external symbol. */ 418533965Sjdp h = *sym_hash; 418633965Sjdp 418733965Sjdp /* Use the name from the hash table, in case the symbol was 418833965Sjdp wrapped. */ 4189104834Sobrien if (h != NULL 4190104834Sobrien && h->root.type != bfd_link_hash_warning) 419133965Sjdp name = h->root.root.string; 419233965Sjdp 419333965Sjdp /* If this is an indirect or warning symbol, then change 419433965Sjdp hresolve to the base symbol. We also change *sym_hash so 419533965Sjdp that the relocation routines relocate against the real 419633965Sjdp symbol. */ 419733965Sjdp hresolve = h; 419833965Sjdp if (h != (struct aout_link_hash_entry *) NULL 419933965Sjdp && (h->root.type == bfd_link_hash_indirect 420033965Sjdp || h->root.type == bfd_link_hash_warning)) 420133965Sjdp { 420233965Sjdp hresolve = (struct aout_link_hash_entry *) h->root.u.i.link; 420333965Sjdp while (hresolve->root.type == bfd_link_hash_indirect 420433965Sjdp || hresolve->root.type == bfd_link_hash_warning) 420533965Sjdp hresolve = ((struct aout_link_hash_entry *) 420633965Sjdp hresolve->root.u.i.link); 420733965Sjdp *sym_hash = hresolve; 420833965Sjdp } 420933965Sjdp 421033965Sjdp /* If the symbol has already been written out, skip it. */ 421133965Sjdp if (h != (struct aout_link_hash_entry *) NULL 421233965Sjdp && h->written) 421333965Sjdp { 421433965Sjdp if ((type & N_TYPE) == N_INDR 421533965Sjdp || type == N_WARNING) 421633965Sjdp skip_next = true; 421733965Sjdp *symbol_map = h->indx; 421833965Sjdp continue; 421933965Sjdp } 422033965Sjdp 422133965Sjdp /* See if we are stripping this symbol. */ 422233965Sjdp skip = false; 422333965Sjdp switch (strip) 422433965Sjdp { 422533965Sjdp case strip_none: 422633965Sjdp break; 422733965Sjdp case strip_debugger: 422833965Sjdp if ((type & N_STAB) != 0) 422933965Sjdp skip = true; 423033965Sjdp break; 423133965Sjdp case strip_some: 423233965Sjdp if (bfd_hash_lookup (finfo->info->keep_hash, name, false, false) 423333965Sjdp == NULL) 423433965Sjdp skip = true; 423533965Sjdp break; 423633965Sjdp case strip_all: 423733965Sjdp skip = true; 423833965Sjdp break; 423933965Sjdp } 424033965Sjdp if (skip) 424133965Sjdp { 424233965Sjdp if (h != (struct aout_link_hash_entry *) NULL) 424333965Sjdp h->written = true; 424433965Sjdp continue; 424533965Sjdp } 424633965Sjdp 424733965Sjdp /* Get the value of the symbol. */ 424833965Sjdp if ((type & N_TYPE) == N_TEXT 424933965Sjdp || type == N_WEAKT) 425033965Sjdp symsec = obj_textsec (input_bfd); 425133965Sjdp else if ((type & N_TYPE) == N_DATA 425233965Sjdp || type == N_WEAKD) 425333965Sjdp symsec = obj_datasec (input_bfd); 425433965Sjdp else if ((type & N_TYPE) == N_BSS 425533965Sjdp || type == N_WEAKB) 425633965Sjdp symsec = obj_bsssec (input_bfd); 425733965Sjdp else if ((type & N_TYPE) == N_ABS 425833965Sjdp || type == N_WEAKA) 425933965Sjdp symsec = bfd_abs_section_ptr; 426033965Sjdp else if (((type & N_TYPE) == N_INDR 426133965Sjdp && (hresolve == (struct aout_link_hash_entry *) NULL 426233965Sjdp || (hresolve->root.type != bfd_link_hash_defined 426333965Sjdp && hresolve->root.type != bfd_link_hash_defweak 426433965Sjdp && hresolve->root.type != bfd_link_hash_common))) 426533965Sjdp || type == N_WARNING) 426633965Sjdp { 426733965Sjdp /* Pass the next symbol through unchanged. The 426833965Sjdp condition above for indirect symbols is so that if 426933965Sjdp the indirect symbol was defined, we output it with 427033965Sjdp the correct definition so the debugger will 427133965Sjdp understand it. */ 427233965Sjdp pass = true; 427333965Sjdp val = GET_WORD (input_bfd, sym->e_value); 427433965Sjdp symsec = NULL; 427533965Sjdp } 427633965Sjdp else if ((type & N_STAB) != 0) 427733965Sjdp { 427833965Sjdp val = GET_WORD (input_bfd, sym->e_value); 427933965Sjdp symsec = NULL; 428033965Sjdp } 428133965Sjdp else 428233965Sjdp { 428333965Sjdp /* If we get here with an indirect symbol, it means that 428433965Sjdp we are outputting it with a real definition. In such 428533965Sjdp a case we do not want to output the next symbol, 428633965Sjdp which is the target of the indirection. */ 428733965Sjdp if ((type & N_TYPE) == N_INDR) 428833965Sjdp skip_next = true; 428933965Sjdp 429033965Sjdp symsec = NULL; 429133965Sjdp 429233965Sjdp /* We need to get the value from the hash table. We use 429333965Sjdp hresolve so that if we have defined an indirect 429433965Sjdp symbol we output the final definition. */ 429533965Sjdp if (h == (struct aout_link_hash_entry *) NULL) 429633965Sjdp { 429733965Sjdp switch (type & N_TYPE) 429833965Sjdp { 429933965Sjdp case N_SETT: 430033965Sjdp symsec = obj_textsec (input_bfd); 430133965Sjdp break; 430233965Sjdp case N_SETD: 430333965Sjdp symsec = obj_datasec (input_bfd); 430433965Sjdp break; 430533965Sjdp case N_SETB: 430633965Sjdp symsec = obj_bsssec (input_bfd); 430733965Sjdp break; 430833965Sjdp case N_SETA: 430933965Sjdp symsec = bfd_abs_section_ptr; 431033965Sjdp break; 431133965Sjdp default: 431233965Sjdp val = 0; 431333965Sjdp break; 431433965Sjdp } 431533965Sjdp } 431633965Sjdp else if (hresolve->root.type == bfd_link_hash_defined 431733965Sjdp || hresolve->root.type == bfd_link_hash_defweak) 431833965Sjdp { 431933965Sjdp asection *input_section; 432033965Sjdp asection *output_section; 432133965Sjdp 432233965Sjdp /* This case usually means a common symbol which was 432333965Sjdp turned into a defined symbol. */ 432433965Sjdp input_section = hresolve->root.u.def.section; 432533965Sjdp output_section = input_section->output_section; 432633965Sjdp BFD_ASSERT (bfd_is_abs_section (output_section) 432733965Sjdp || output_section->owner == output_bfd); 432833965Sjdp val = (hresolve->root.u.def.value 432933965Sjdp + bfd_get_section_vma (output_bfd, output_section) 433033965Sjdp + input_section->output_offset); 433133965Sjdp 433233965Sjdp /* Get the correct type based on the section. If 433333965Sjdp this is a constructed set, force it to be 433433965Sjdp globally visible. */ 433533965Sjdp if (type == N_SETT 433633965Sjdp || type == N_SETD 433733965Sjdp || type == N_SETB 433833965Sjdp || type == N_SETA) 433933965Sjdp type |= N_EXT; 434033965Sjdp 434133965Sjdp type &=~ N_TYPE; 434233965Sjdp 434333965Sjdp if (output_section == obj_textsec (output_bfd)) 434433965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 434533965Sjdp ? N_TEXT 434633965Sjdp : N_WEAKT); 434733965Sjdp else if (output_section == obj_datasec (output_bfd)) 434833965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 434933965Sjdp ? N_DATA 435033965Sjdp : N_WEAKD); 435133965Sjdp else if (output_section == obj_bsssec (output_bfd)) 435233965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 435333965Sjdp ? N_BSS 435433965Sjdp : N_WEAKB); 435533965Sjdp else 435633965Sjdp type |= (hresolve->root.type == bfd_link_hash_defined 435733965Sjdp ? N_ABS 435833965Sjdp : N_WEAKA); 435933965Sjdp } 436033965Sjdp else if (hresolve->root.type == bfd_link_hash_common) 436133965Sjdp val = hresolve->root.u.c.size; 436233965Sjdp else if (hresolve->root.type == bfd_link_hash_undefweak) 436333965Sjdp { 436433965Sjdp val = 0; 436533965Sjdp type = N_WEAKU; 436633965Sjdp } 436733965Sjdp else 436833965Sjdp val = 0; 436933965Sjdp } 437033965Sjdp if (symsec != (asection *) NULL) 437133965Sjdp val = (symsec->output_section->vma 437233965Sjdp + symsec->output_offset 437333965Sjdp + (GET_WORD (input_bfd, sym->e_value) 437433965Sjdp - symsec->vma)); 437533965Sjdp 437633965Sjdp /* If this is a global symbol set the written flag, and if 437733965Sjdp it is a local symbol see if we should discard it. */ 437833965Sjdp if (h != (struct aout_link_hash_entry *) NULL) 437933965Sjdp { 438033965Sjdp h->written = true; 438133965Sjdp h->indx = obj_aout_external_sym_count (output_bfd); 438233965Sjdp } 438333965Sjdp else if ((type & N_TYPE) != N_SETT 438433965Sjdp && (type & N_TYPE) != N_SETD 438533965Sjdp && (type & N_TYPE) != N_SETB 438633965Sjdp && (type & N_TYPE) != N_SETA) 438733965Sjdp { 438833965Sjdp switch (discard) 438933965Sjdp { 439033965Sjdp case discard_none: 439189857Sobrien case discard_sec_merge: 439233965Sjdp break; 439333965Sjdp case discard_l: 439433965Sjdp if ((type & N_STAB) == 0 439533965Sjdp && bfd_is_local_label_name (input_bfd, name)) 439633965Sjdp skip = true; 439733965Sjdp break; 439833965Sjdp case discard_all: 439933965Sjdp skip = true; 440033965Sjdp break; 440133965Sjdp } 440233965Sjdp if (skip) 440333965Sjdp { 440433965Sjdp pass = false; 440533965Sjdp continue; 440633965Sjdp } 440733965Sjdp } 440833965Sjdp 440933965Sjdp /* An N_BINCL symbol indicates the start of the stabs 441033965Sjdp entries for a header file. We need to scan ahead to the 441133965Sjdp next N_EINCL symbol, ignoring nesting, adding up all the 441233965Sjdp characters in the symbol names, not including the file 441333965Sjdp numbers in types (the first number after an open 441433965Sjdp parenthesis). */ 441533965Sjdp if (type == N_BINCL) 441633965Sjdp { 441733965Sjdp struct external_nlist *incl_sym; 441833965Sjdp int nest; 441933965Sjdp struct aout_link_includes_entry *incl_entry; 442033965Sjdp struct aout_link_includes_totals *t; 442133965Sjdp 442233965Sjdp val = 0; 442333965Sjdp nest = 0; 442433965Sjdp for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++) 442533965Sjdp { 442633965Sjdp int incl_type; 442733965Sjdp 442889857Sobrien incl_type = H_GET_8 (input_bfd, incl_sym->e_type); 442933965Sjdp if (incl_type == N_EINCL) 443033965Sjdp { 443133965Sjdp if (nest == 0) 443233965Sjdp break; 443333965Sjdp --nest; 443433965Sjdp } 443533965Sjdp else if (incl_type == N_BINCL) 443633965Sjdp ++nest; 443733965Sjdp else if (nest == 0) 443833965Sjdp { 443933965Sjdp const char *s; 444033965Sjdp 444133965Sjdp s = strings + GET_WORD (input_bfd, incl_sym->e_strx); 444233965Sjdp for (; *s != '\0'; s++) 444333965Sjdp { 444433965Sjdp val += *s; 444533965Sjdp if (*s == '(') 444633965Sjdp { 444733965Sjdp /* Skip the file number. */ 444833965Sjdp ++s; 444989857Sobrien while (ISDIGIT (*s)) 445033965Sjdp ++s; 445133965Sjdp --s; 445233965Sjdp } 445333965Sjdp } 445433965Sjdp } 445533965Sjdp } 445633965Sjdp 445733965Sjdp /* If we have already included a header file with the 445833965Sjdp same value, then replace this one with an N_EXCL 445933965Sjdp symbol. */ 446033965Sjdp copy = ! finfo->info->keep_memory; 446133965Sjdp incl_entry = aout_link_includes_lookup (&finfo->includes, 446233965Sjdp name, true, copy); 446333965Sjdp if (incl_entry == NULL) 446433965Sjdp return false; 446533965Sjdp for (t = incl_entry->totals; t != NULL; t = t->next) 446633965Sjdp if (t->total == val) 446733965Sjdp break; 446833965Sjdp if (t == NULL) 446933965Sjdp { 447033965Sjdp /* This is the first time we have seen this header 447133965Sjdp file with this set of stabs strings. */ 447233965Sjdp t = ((struct aout_link_includes_totals *) 447333965Sjdp bfd_hash_allocate (&finfo->includes.root, 447433965Sjdp sizeof *t)); 447533965Sjdp if (t == NULL) 447633965Sjdp return false; 447733965Sjdp t->total = val; 447833965Sjdp t->next = incl_entry->totals; 447933965Sjdp incl_entry->totals = t; 448033965Sjdp } 448133965Sjdp else 448233965Sjdp { 448333965Sjdp int *incl_map; 448433965Sjdp 448533965Sjdp /* This is a duplicate header file. We must change 448633965Sjdp it to be an N_EXCL entry, and mark all the 448733965Sjdp included symbols to prevent outputting them. */ 448833965Sjdp type = N_EXCL; 448933965Sjdp 449033965Sjdp nest = 0; 449133965Sjdp for (incl_sym = sym + 1, incl_map = symbol_map + 1; 449233965Sjdp incl_sym < sym_end; 449333965Sjdp incl_sym++, incl_map++) 449433965Sjdp { 449533965Sjdp int incl_type; 449633965Sjdp 449789857Sobrien incl_type = H_GET_8 (input_bfd, incl_sym->e_type); 449833965Sjdp if (incl_type == N_EINCL) 449933965Sjdp { 450033965Sjdp if (nest == 0) 450133965Sjdp { 450233965Sjdp *incl_map = -1; 450333965Sjdp break; 450433965Sjdp } 450533965Sjdp --nest; 450633965Sjdp } 450733965Sjdp else if (incl_type == N_BINCL) 450833965Sjdp ++nest; 450933965Sjdp else if (nest == 0) 451033965Sjdp *incl_map = -1; 451133965Sjdp } 451233965Sjdp } 451333965Sjdp } 451433965Sjdp } 451533965Sjdp 451633965Sjdp /* Copy this symbol into the list of symbols we are going to 451733965Sjdp write out. */ 451889857Sobrien H_PUT_8 (output_bfd, type, outsym->e_type); 451989857Sobrien H_PUT_8 (output_bfd, H_GET_8 (input_bfd, sym->e_other), outsym->e_other); 452089857Sobrien H_PUT_16 (output_bfd, H_GET_16 (input_bfd, sym->e_desc), outsym->e_desc); 452133965Sjdp copy = false; 452233965Sjdp if (! finfo->info->keep_memory) 452333965Sjdp { 452433965Sjdp /* name points into a string table which we are going to 452533965Sjdp free. If there is a hash table entry, use that string. 452633965Sjdp Otherwise, copy name into memory. */ 452733965Sjdp if (h != (struct aout_link_hash_entry *) NULL) 452833965Sjdp name = h->root.root.string; 452933965Sjdp else 453033965Sjdp copy = true; 453133965Sjdp } 453233965Sjdp strtab_index = add_to_stringtab (output_bfd, finfo->strtab, 453333965Sjdp name, copy); 453433965Sjdp if (strtab_index == (bfd_size_type) -1) 453533965Sjdp return false; 453633965Sjdp PUT_WORD (output_bfd, strtab_index, outsym->e_strx); 453733965Sjdp PUT_WORD (output_bfd, val, outsym->e_value); 453833965Sjdp *symbol_map = obj_aout_external_sym_count (output_bfd); 453933965Sjdp ++obj_aout_external_sym_count (output_bfd); 454033965Sjdp ++outsym; 454133965Sjdp } 454233965Sjdp 454333965Sjdp /* Write out the output symbols we have just constructed. */ 454433965Sjdp if (outsym > finfo->output_syms) 454533965Sjdp { 454689857Sobrien bfd_size_type outsym_size; 454733965Sjdp 454833965Sjdp if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0) 454933965Sjdp return false; 455089857Sobrien outsym_size = outsym - finfo->output_syms; 455189857Sobrien outsym_size *= EXTERNAL_NLIST_SIZE; 455289857Sobrien if (bfd_bwrite ((PTR) finfo->output_syms, outsym_size, output_bfd) 455389857Sobrien != outsym_size) 455433965Sjdp return false; 455589857Sobrien finfo->symoff += outsym_size; 455633965Sjdp } 455733965Sjdp 455833965Sjdp return true; 455933965Sjdp} 456033965Sjdp 456133965Sjdp/* Write out a symbol that was not associated with an a.out input 456233965Sjdp object. */ 456333965Sjdp 456433965Sjdpstatic boolean 456533965Sjdpaout_link_write_other_symbol (h, data) 456633965Sjdp struct aout_link_hash_entry *h; 456733965Sjdp PTR data; 456833965Sjdp{ 456933965Sjdp struct aout_final_link_info *finfo = (struct aout_final_link_info *) data; 457033965Sjdp bfd *output_bfd; 457133965Sjdp int type; 457233965Sjdp bfd_vma val; 457333965Sjdp struct external_nlist outsym; 457433965Sjdp bfd_size_type indx; 457589857Sobrien bfd_size_type amt; 457633965Sjdp 457794536Sobrien if (h->root.type == bfd_link_hash_warning) 457894536Sobrien { 457994536Sobrien h = (struct aout_link_hash_entry *) h->root.u.i.link; 458094536Sobrien if (h->root.type == bfd_link_hash_new) 458194536Sobrien return true; 458294536Sobrien } 458394536Sobrien 458433965Sjdp output_bfd = finfo->output_bfd; 458533965Sjdp 458633965Sjdp if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL) 458733965Sjdp { 458833965Sjdp if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol) 458933965Sjdp (output_bfd, finfo->info, h))) 459033965Sjdp { 459133965Sjdp /* FIXME: No way to handle errors. */ 459233965Sjdp abort (); 459333965Sjdp } 459433965Sjdp } 459533965Sjdp 459633965Sjdp if (h->written) 459733965Sjdp return true; 459833965Sjdp 459933965Sjdp h->written = true; 460033965Sjdp 460133965Sjdp /* An indx of -2 means the symbol must be written. */ 460233965Sjdp if (h->indx != -2 460333965Sjdp && (finfo->info->strip == strip_all 460433965Sjdp || (finfo->info->strip == strip_some 460533965Sjdp && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string, 460633965Sjdp false, false) == NULL))) 460733965Sjdp return true; 460833965Sjdp 460933965Sjdp switch (h->root.type) 461033965Sjdp { 461133965Sjdp default: 461294536Sobrien case bfd_link_hash_warning: 461333965Sjdp abort (); 461433965Sjdp /* Avoid variable not initialized warnings. */ 461533965Sjdp return true; 461633965Sjdp case bfd_link_hash_new: 461733965Sjdp /* This can happen for set symbols when sets are not being 461833965Sjdp built. */ 461933965Sjdp return true; 462033965Sjdp case bfd_link_hash_undefined: 462133965Sjdp type = N_UNDF | N_EXT; 462233965Sjdp val = 0; 462333965Sjdp break; 462433965Sjdp case bfd_link_hash_defined: 462533965Sjdp case bfd_link_hash_defweak: 462633965Sjdp { 462733965Sjdp asection *sec; 462833965Sjdp 462933965Sjdp sec = h->root.u.def.section->output_section; 463033965Sjdp BFD_ASSERT (bfd_is_abs_section (sec) 463133965Sjdp || sec->owner == output_bfd); 463233965Sjdp if (sec == obj_textsec (output_bfd)) 463333965Sjdp type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT; 463433965Sjdp else if (sec == obj_datasec (output_bfd)) 463533965Sjdp type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD; 463633965Sjdp else if (sec == obj_bsssec (output_bfd)) 463733965Sjdp type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB; 463833965Sjdp else 463933965Sjdp type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA; 464033965Sjdp type |= N_EXT; 464133965Sjdp val = (h->root.u.def.value 464233965Sjdp + sec->vma 464333965Sjdp + h->root.u.def.section->output_offset); 464433965Sjdp } 464533965Sjdp break; 464633965Sjdp case bfd_link_hash_common: 464733965Sjdp type = N_UNDF | N_EXT; 464833965Sjdp val = h->root.u.c.size; 464933965Sjdp break; 465033965Sjdp case bfd_link_hash_undefweak: 465133965Sjdp type = N_WEAKU; 465233965Sjdp val = 0; 465333965Sjdp case bfd_link_hash_indirect: 465494536Sobrien /* We ignore these symbols, since the indirected symbol is 465594536Sobrien already in the hash table. */ 465633965Sjdp return true; 465733965Sjdp } 465833965Sjdp 465989857Sobrien H_PUT_8 (output_bfd, type, outsym.e_type); 466089857Sobrien H_PUT_8 (output_bfd, 0, outsym.e_other); 466189857Sobrien H_PUT_16 (output_bfd, 0, outsym.e_desc); 466233965Sjdp indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string, 466333965Sjdp false); 466489857Sobrien if (indx == - (bfd_size_type) 1) 466533965Sjdp { 466633965Sjdp /* FIXME: No way to handle errors. */ 466733965Sjdp abort (); 466833965Sjdp } 466933965Sjdp PUT_WORD (output_bfd, indx, outsym.e_strx); 467033965Sjdp PUT_WORD (output_bfd, val, outsym.e_value); 467133965Sjdp 467289857Sobrien amt = EXTERNAL_NLIST_SIZE; 467333965Sjdp if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0 467489857Sobrien || bfd_bwrite ((PTR) &outsym, amt, output_bfd) != amt) 467533965Sjdp { 467633965Sjdp /* FIXME: No way to handle errors. */ 467733965Sjdp abort (); 467833965Sjdp } 467933965Sjdp 468033965Sjdp finfo->symoff += EXTERNAL_NLIST_SIZE; 468133965Sjdp h->indx = obj_aout_external_sym_count (output_bfd); 468233965Sjdp ++obj_aout_external_sym_count (output_bfd); 468333965Sjdp 468433965Sjdp return true; 468533965Sjdp} 468633965Sjdp 468733965Sjdp/* Link an a.out section into the output file. */ 468833965Sjdp 468933965Sjdpstatic boolean 469033965Sjdpaout_link_input_section (finfo, input_bfd, input_section, reloff_ptr, 469133965Sjdp rel_size) 469233965Sjdp struct aout_final_link_info *finfo; 469333965Sjdp bfd *input_bfd; 469433965Sjdp asection *input_section; 469533965Sjdp file_ptr *reloff_ptr; 469633965Sjdp bfd_size_type rel_size; 469733965Sjdp{ 469833965Sjdp bfd_size_type input_size; 469933965Sjdp PTR relocs; 470033965Sjdp 470133965Sjdp /* Get the section contents. */ 470233965Sjdp input_size = bfd_section_size (input_bfd, input_section); 470333965Sjdp if (! bfd_get_section_contents (input_bfd, input_section, 470433965Sjdp (PTR) finfo->contents, 470533965Sjdp (file_ptr) 0, input_size)) 470633965Sjdp return false; 470733965Sjdp 470833965Sjdp /* Read in the relocs if we haven't already done it. */ 470933965Sjdp if (aout_section_data (input_section) != NULL 471033965Sjdp && aout_section_data (input_section)->relocs != NULL) 471133965Sjdp relocs = aout_section_data (input_section)->relocs; 471233965Sjdp else 471333965Sjdp { 471433965Sjdp relocs = finfo->relocs; 471533965Sjdp if (rel_size > 0) 471633965Sjdp { 471733965Sjdp if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 471889857Sobrien || bfd_bread (relocs, rel_size, input_bfd) != rel_size) 471933965Sjdp return false; 472033965Sjdp } 472133965Sjdp } 472233965Sjdp 472333965Sjdp /* Relocate the section contents. */ 472433965Sjdp if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) 472533965Sjdp { 472633965Sjdp if (! aout_link_input_section_std (finfo, input_bfd, input_section, 472733965Sjdp (struct reloc_std_external *) relocs, 472833965Sjdp rel_size, finfo->contents)) 472933965Sjdp return false; 473033965Sjdp } 473133965Sjdp else 473233965Sjdp { 473333965Sjdp if (! aout_link_input_section_ext (finfo, input_bfd, input_section, 473433965Sjdp (struct reloc_ext_external *) relocs, 473533965Sjdp rel_size, finfo->contents)) 473633965Sjdp return false; 473733965Sjdp } 473833965Sjdp 473933965Sjdp /* Write out the section contents. */ 474033965Sjdp if (! bfd_set_section_contents (finfo->output_bfd, 474133965Sjdp input_section->output_section, 474233965Sjdp (PTR) finfo->contents, 474389857Sobrien (file_ptr) input_section->output_offset, 474433965Sjdp input_size)) 474533965Sjdp return false; 474633965Sjdp 474733965Sjdp /* If we are producing relocateable output, the relocs were 474833965Sjdp modified, and we now write them out. */ 474933965Sjdp if (finfo->info->relocateable && rel_size > 0) 475033965Sjdp { 475133965Sjdp if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0) 475233965Sjdp return false; 475389857Sobrien if (bfd_bwrite (relocs, rel_size, finfo->output_bfd) != rel_size) 475433965Sjdp return false; 475533965Sjdp *reloff_ptr += rel_size; 475633965Sjdp 475733965Sjdp /* Assert that the relocs have not run into the symbols, and 475833965Sjdp that if these are the text relocs they have not run into the 475933965Sjdp data relocs. */ 476033965Sjdp BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) 476133965Sjdp && (reloff_ptr != &finfo->treloff 476233965Sjdp || (*reloff_ptr 476333965Sjdp <= obj_datasec (finfo->output_bfd)->rel_filepos))); 476433965Sjdp } 476533965Sjdp 476633965Sjdp return true; 476733965Sjdp} 476833965Sjdp 476933965Sjdp/* Get the section corresponding to a reloc index. */ 477033965Sjdp 477133965Sjdpstatic INLINE asection * 477233965Sjdpaout_reloc_index_to_section (abfd, indx) 477333965Sjdp bfd *abfd; 477433965Sjdp int indx; 477533965Sjdp{ 477633965Sjdp switch (indx & N_TYPE) 477733965Sjdp { 477833965Sjdp case N_TEXT: 477933965Sjdp return obj_textsec (abfd); 478033965Sjdp case N_DATA: 478133965Sjdp return obj_datasec (abfd); 478233965Sjdp case N_BSS: 478333965Sjdp return obj_bsssec (abfd); 478433965Sjdp case N_ABS: 478533965Sjdp case N_UNDF: 478633965Sjdp return bfd_abs_section_ptr; 478733965Sjdp default: 478833965Sjdp abort (); 478933965Sjdp } 479060484Sobrien /*NOTREACHED*/ 479160484Sobrien return NULL; 479233965Sjdp} 479333965Sjdp 479433965Sjdp/* Relocate an a.out section using standard a.out relocs. */ 479533965Sjdp 479633965Sjdpstatic boolean 479733965Sjdpaout_link_input_section_std (finfo, input_bfd, input_section, relocs, 479833965Sjdp rel_size, contents) 479933965Sjdp struct aout_final_link_info *finfo; 480033965Sjdp bfd *input_bfd; 480133965Sjdp asection *input_section; 480233965Sjdp struct reloc_std_external *relocs; 480333965Sjdp bfd_size_type rel_size; 480433965Sjdp bfd_byte *contents; 480533965Sjdp{ 480633965Sjdp boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, 480733965Sjdp bfd *, asection *, 480833965Sjdp struct aout_link_hash_entry *, 480933965Sjdp PTR, bfd_byte *, boolean *, 481033965Sjdp bfd_vma *)); 481133965Sjdp bfd *output_bfd; 481233965Sjdp boolean relocateable; 481333965Sjdp struct external_nlist *syms; 481433965Sjdp char *strings; 481533965Sjdp struct aout_link_hash_entry **sym_hashes; 481633965Sjdp int *symbol_map; 481733965Sjdp bfd_size_type reloc_count; 481833965Sjdp register struct reloc_std_external *rel; 481933965Sjdp struct reloc_std_external *rel_end; 482033965Sjdp 482133965Sjdp output_bfd = finfo->output_bfd; 482233965Sjdp check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; 482333965Sjdp 482433965Sjdp BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE); 482533965Sjdp BFD_ASSERT (input_bfd->xvec->header_byteorder 482633965Sjdp == output_bfd->xvec->header_byteorder); 482733965Sjdp 482833965Sjdp relocateable = finfo->info->relocateable; 482933965Sjdp syms = obj_aout_external_syms (input_bfd); 483033965Sjdp strings = obj_aout_external_strings (input_bfd); 483133965Sjdp sym_hashes = obj_aout_sym_hashes (input_bfd); 483233965Sjdp symbol_map = finfo->symbol_map; 483333965Sjdp 483433965Sjdp reloc_count = rel_size / RELOC_STD_SIZE; 483533965Sjdp rel = relocs; 483633965Sjdp rel_end = rel + reloc_count; 483733965Sjdp for (; rel < rel_end; rel++) 483833965Sjdp { 483933965Sjdp bfd_vma r_addr; 484033965Sjdp int r_index; 484133965Sjdp int r_extern; 484233965Sjdp int r_pcrel; 484333965Sjdp int r_baserel = 0; 484433965Sjdp reloc_howto_type *howto; 484533965Sjdp struct aout_link_hash_entry *h = NULL; 484633965Sjdp bfd_vma relocation; 484733965Sjdp bfd_reloc_status_type r; 484833965Sjdp 484933965Sjdp r_addr = GET_SWORD (input_bfd, rel->r_address); 485033965Sjdp 485133965Sjdp#ifdef MY_reloc_howto 485289857Sobrien howto = MY_reloc_howto (input_bfd, rel, r_index, r_extern, r_pcrel); 485377298Sobrien#else 485433965Sjdp { 485533965Sjdp int r_jmptable; 485633965Sjdp int r_relative; 485733965Sjdp int r_length; 485833965Sjdp unsigned int howto_idx; 485933965Sjdp 486033965Sjdp if (bfd_header_big_endian (input_bfd)) 486133965Sjdp { 486233965Sjdp r_index = ((rel->r_index[0] << 16) 486333965Sjdp | (rel->r_index[1] << 8) 486433965Sjdp | rel->r_index[2]); 486533965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); 486633965Sjdp r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 486733965Sjdp r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 486833965Sjdp r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 486933965Sjdp r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); 487033965Sjdp r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) 487133965Sjdp >> RELOC_STD_BITS_LENGTH_SH_BIG); 487233965Sjdp } 487333965Sjdp else 487433965Sjdp { 487533965Sjdp r_index = ((rel->r_index[2] << 16) 487633965Sjdp | (rel->r_index[1] << 8) 487733965Sjdp | rel->r_index[0]); 487833965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); 487933965Sjdp r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 488033965Sjdp r_baserel = (0 != (rel->r_type[0] 488133965Sjdp & RELOC_STD_BITS_BASEREL_LITTLE)); 488233965Sjdp r_jmptable= (0 != (rel->r_type[0] 488333965Sjdp & RELOC_STD_BITS_JMPTABLE_LITTLE)); 488433965Sjdp r_relative= (0 != (rel->r_type[0] 488533965Sjdp & RELOC_STD_BITS_RELATIVE_LITTLE)); 488633965Sjdp r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) 488733965Sjdp >> RELOC_STD_BITS_LENGTH_SH_LITTLE); 488833965Sjdp } 488933965Sjdp 489033965Sjdp howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel 489133965Sjdp + 16 * r_jmptable + 32 * r_relative); 489233965Sjdp BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); 489333965Sjdp howto = howto_table_std + howto_idx; 489433965Sjdp } 489533965Sjdp#endif 489633965Sjdp 489733965Sjdp if (relocateable) 489833965Sjdp { 489933965Sjdp /* We are generating a relocateable output file, and must 490033965Sjdp modify the reloc accordingly. */ 490133965Sjdp if (r_extern) 490233965Sjdp { 490333965Sjdp /* If we know the symbol this relocation is against, 490433965Sjdp convert it into a relocation against a section. This 490533965Sjdp is what the native linker does. */ 490633965Sjdp h = sym_hashes[r_index]; 490733965Sjdp if (h != (struct aout_link_hash_entry *) NULL 490833965Sjdp && (h->root.type == bfd_link_hash_defined 490933965Sjdp || h->root.type == bfd_link_hash_defweak)) 491033965Sjdp { 491133965Sjdp asection *output_section; 491233965Sjdp 491333965Sjdp /* Change the r_extern value. */ 491433965Sjdp if (bfd_header_big_endian (output_bfd)) 491533965Sjdp rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; 491633965Sjdp else 491733965Sjdp rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; 491833965Sjdp 491933965Sjdp /* Compute a new r_index. */ 492033965Sjdp output_section = h->root.u.def.section->output_section; 492133965Sjdp if (output_section == obj_textsec (output_bfd)) 492233965Sjdp r_index = N_TEXT; 492333965Sjdp else if (output_section == obj_datasec (output_bfd)) 492433965Sjdp r_index = N_DATA; 492533965Sjdp else if (output_section == obj_bsssec (output_bfd)) 492633965Sjdp r_index = N_BSS; 492733965Sjdp else 492833965Sjdp r_index = N_ABS; 492933965Sjdp 493033965Sjdp /* Add the symbol value and the section VMA to the 493133965Sjdp addend stored in the contents. */ 493233965Sjdp relocation = (h->root.u.def.value 493333965Sjdp + output_section->vma 493433965Sjdp + h->root.u.def.section->output_offset); 493533965Sjdp } 493633965Sjdp else 493733965Sjdp { 493833965Sjdp /* We must change r_index according to the symbol 493933965Sjdp map. */ 494033965Sjdp r_index = symbol_map[r_index]; 494133965Sjdp 494233965Sjdp if (r_index == -1) 494333965Sjdp { 494433965Sjdp if (h != NULL) 494533965Sjdp { 494633965Sjdp /* We decided to strip this symbol, but it 494733965Sjdp turns out that we can't. Note that we 494833965Sjdp lose the other and desc information here. 494933965Sjdp I don't think that will ever matter for a 495033965Sjdp global symbol. */ 495133965Sjdp if (h->indx < 0) 495233965Sjdp { 495333965Sjdp h->indx = -2; 495433965Sjdp h->written = false; 495533965Sjdp if (! aout_link_write_other_symbol (h, 495633965Sjdp (PTR) finfo)) 495733965Sjdp return false; 495833965Sjdp } 495933965Sjdp r_index = h->indx; 496033965Sjdp } 496133965Sjdp else 496233965Sjdp { 496333965Sjdp const char *name; 496433965Sjdp 496533965Sjdp name = strings + GET_WORD (input_bfd, 496633965Sjdp syms[r_index].e_strx); 496733965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 496833965Sjdp (finfo->info, name, input_bfd, input_section, 496933965Sjdp r_addr))) 497033965Sjdp return false; 497133965Sjdp r_index = 0; 497233965Sjdp } 497333965Sjdp } 497433965Sjdp 497533965Sjdp relocation = 0; 497633965Sjdp } 497733965Sjdp 497833965Sjdp /* Write out the new r_index value. */ 497933965Sjdp if (bfd_header_big_endian (output_bfd)) 498033965Sjdp { 498133965Sjdp rel->r_index[0] = r_index >> 16; 498233965Sjdp rel->r_index[1] = r_index >> 8; 498333965Sjdp rel->r_index[2] = r_index; 498433965Sjdp } 498533965Sjdp else 498633965Sjdp { 498733965Sjdp rel->r_index[2] = r_index >> 16; 498833965Sjdp rel->r_index[1] = r_index >> 8; 498933965Sjdp rel->r_index[0] = r_index; 499033965Sjdp } 499133965Sjdp } 499233965Sjdp else 499333965Sjdp { 499433965Sjdp asection *section; 499533965Sjdp 499633965Sjdp /* This is a relocation against a section. We must 499733965Sjdp adjust by the amount that the section moved. */ 499833965Sjdp section = aout_reloc_index_to_section (input_bfd, r_index); 499933965Sjdp relocation = (section->output_section->vma 500033965Sjdp + section->output_offset 500133965Sjdp - section->vma); 500233965Sjdp } 500333965Sjdp 500433965Sjdp /* Change the address of the relocation. */ 500533965Sjdp PUT_WORD (output_bfd, 500633965Sjdp r_addr + input_section->output_offset, 500733965Sjdp rel->r_address); 500833965Sjdp 500933965Sjdp /* Adjust a PC relative relocation by removing the reference 501033965Sjdp to the original address in the section and including the 501133965Sjdp reference to the new address. */ 501233965Sjdp if (r_pcrel) 501333965Sjdp relocation -= (input_section->output_section->vma 501433965Sjdp + input_section->output_offset 501533965Sjdp - input_section->vma); 501633965Sjdp 501733965Sjdp#ifdef MY_relocatable_reloc 501833965Sjdp MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr); 501933965Sjdp#endif 502033965Sjdp 502133965Sjdp if (relocation == 0) 502233965Sjdp r = bfd_reloc_ok; 502333965Sjdp else 502433965Sjdp r = MY_relocate_contents (howto, 502533965Sjdp input_bfd, relocation, 502633965Sjdp contents + r_addr); 502733965Sjdp } 502833965Sjdp else 502933965Sjdp { 503033965Sjdp boolean hundef; 503133965Sjdp 503233965Sjdp /* We are generating an executable, and must do a full 503333965Sjdp relocation. */ 503433965Sjdp hundef = false; 503560484Sobrien 503633965Sjdp if (r_extern) 503733965Sjdp { 503833965Sjdp h = sym_hashes[r_index]; 503933965Sjdp 504033965Sjdp if (h != (struct aout_link_hash_entry *) NULL 504133965Sjdp && (h->root.type == bfd_link_hash_defined 504233965Sjdp || h->root.type == bfd_link_hash_defweak)) 504333965Sjdp { 504433965Sjdp relocation = (h->root.u.def.value 504533965Sjdp + h->root.u.def.section->output_section->vma 504633965Sjdp + h->root.u.def.section->output_offset); 504733965Sjdp } 504833965Sjdp else if (h != (struct aout_link_hash_entry *) NULL 504933965Sjdp && h->root.type == bfd_link_hash_undefweak) 505033965Sjdp relocation = 0; 505133965Sjdp else 505233965Sjdp { 505333965Sjdp hundef = true; 505433965Sjdp relocation = 0; 505533965Sjdp } 505633965Sjdp } 505733965Sjdp else 505833965Sjdp { 505933965Sjdp asection *section; 506033965Sjdp 506133965Sjdp section = aout_reloc_index_to_section (input_bfd, r_index); 506233965Sjdp relocation = (section->output_section->vma 506333965Sjdp + section->output_offset 506433965Sjdp - section->vma); 506533965Sjdp if (r_pcrel) 506633965Sjdp relocation += input_section->vma; 506733965Sjdp } 506833965Sjdp 506933965Sjdp if (check_dynamic_reloc != NULL) 507033965Sjdp { 507133965Sjdp boolean skip; 507233965Sjdp 507333965Sjdp if (! ((*check_dynamic_reloc) 507433965Sjdp (finfo->info, input_bfd, input_section, h, 507533965Sjdp (PTR) rel, contents, &skip, &relocation))) 507633965Sjdp return false; 507733965Sjdp if (skip) 507833965Sjdp continue; 507933965Sjdp } 508033965Sjdp 508133965Sjdp /* Now warn if a global symbol is undefined. We could not 508233965Sjdp do this earlier, because check_dynamic_reloc might want 508333965Sjdp to skip this reloc. */ 508433965Sjdp if (hundef && ! finfo->info->shared && ! r_baserel) 508533965Sjdp { 508633965Sjdp const char *name; 508733965Sjdp 508833965Sjdp if (h != NULL) 508933965Sjdp name = h->root.root.string; 509033965Sjdp else 509133965Sjdp name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); 509233965Sjdp if (! ((*finfo->info->callbacks->undefined_symbol) 509360484Sobrien (finfo->info, name, input_bfd, input_section, 509460484Sobrien r_addr, true))) 509533965Sjdp return false; 509633965Sjdp } 509733965Sjdp 509833965Sjdp r = MY_final_link_relocate (howto, 509933965Sjdp input_bfd, input_section, 510033965Sjdp contents, r_addr, relocation, 510133965Sjdp (bfd_vma) 0); 510233965Sjdp } 510333965Sjdp 510433965Sjdp if (r != bfd_reloc_ok) 510533965Sjdp { 510633965Sjdp switch (r) 510733965Sjdp { 510833965Sjdp default: 510933965Sjdp case bfd_reloc_outofrange: 511033965Sjdp abort (); 511133965Sjdp case bfd_reloc_overflow: 511233965Sjdp { 511333965Sjdp const char *name; 511433965Sjdp 511533965Sjdp if (h != NULL) 511633965Sjdp name = h->root.root.string; 511733965Sjdp else if (r_extern) 511833965Sjdp name = strings + GET_WORD (input_bfd, 511933965Sjdp syms[r_index].e_strx); 512033965Sjdp else 512133965Sjdp { 512233965Sjdp asection *s; 512333965Sjdp 512433965Sjdp s = aout_reloc_index_to_section (input_bfd, r_index); 512533965Sjdp name = bfd_section_name (input_bfd, s); 512633965Sjdp } 512733965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 512833965Sjdp (finfo->info, name, howto->name, 512933965Sjdp (bfd_vma) 0, input_bfd, input_section, r_addr))) 513033965Sjdp return false; 513133965Sjdp } 513233965Sjdp break; 513333965Sjdp } 513433965Sjdp } 513533965Sjdp } 513633965Sjdp 513733965Sjdp return true; 513833965Sjdp} 513933965Sjdp 514033965Sjdp/* Relocate an a.out section using extended a.out relocs. */ 514133965Sjdp 514233965Sjdpstatic boolean 514333965Sjdpaout_link_input_section_ext (finfo, input_bfd, input_section, relocs, 514433965Sjdp rel_size, contents) 514533965Sjdp struct aout_final_link_info *finfo; 514633965Sjdp bfd *input_bfd; 514733965Sjdp asection *input_section; 514833965Sjdp struct reloc_ext_external *relocs; 514933965Sjdp bfd_size_type rel_size; 515033965Sjdp bfd_byte *contents; 515133965Sjdp{ 515233965Sjdp boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, 515333965Sjdp bfd *, asection *, 515433965Sjdp struct aout_link_hash_entry *, 515533965Sjdp PTR, bfd_byte *, boolean *, 515633965Sjdp bfd_vma *)); 515733965Sjdp bfd *output_bfd; 515833965Sjdp boolean relocateable; 515933965Sjdp struct external_nlist *syms; 516033965Sjdp char *strings; 516133965Sjdp struct aout_link_hash_entry **sym_hashes; 516233965Sjdp int *symbol_map; 516333965Sjdp bfd_size_type reloc_count; 516433965Sjdp register struct reloc_ext_external *rel; 516533965Sjdp struct reloc_ext_external *rel_end; 516633965Sjdp 516733965Sjdp output_bfd = finfo->output_bfd; 516833965Sjdp check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; 516933965Sjdp 517033965Sjdp BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE); 517133965Sjdp BFD_ASSERT (input_bfd->xvec->header_byteorder 517233965Sjdp == output_bfd->xvec->header_byteorder); 517333965Sjdp 517433965Sjdp relocateable = finfo->info->relocateable; 517533965Sjdp syms = obj_aout_external_syms (input_bfd); 517633965Sjdp strings = obj_aout_external_strings (input_bfd); 517733965Sjdp sym_hashes = obj_aout_sym_hashes (input_bfd); 517833965Sjdp symbol_map = finfo->symbol_map; 517933965Sjdp 518033965Sjdp reloc_count = rel_size / RELOC_EXT_SIZE; 518133965Sjdp rel = relocs; 518233965Sjdp rel_end = rel + reloc_count; 518333965Sjdp for (; rel < rel_end; rel++) 518433965Sjdp { 518533965Sjdp bfd_vma r_addr; 518633965Sjdp int r_index; 518733965Sjdp int r_extern; 518833965Sjdp unsigned int r_type; 518933965Sjdp bfd_vma r_addend; 519033965Sjdp struct aout_link_hash_entry *h = NULL; 519133965Sjdp asection *r_section = NULL; 519233965Sjdp bfd_vma relocation; 519333965Sjdp 519433965Sjdp r_addr = GET_SWORD (input_bfd, rel->r_address); 519533965Sjdp 519633965Sjdp if (bfd_header_big_endian (input_bfd)) 519733965Sjdp { 519833965Sjdp r_index = ((rel->r_index[0] << 16) 519933965Sjdp | (rel->r_index[1] << 8) 520033965Sjdp | rel->r_index[2]); 520133965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 520233965Sjdp r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 520333965Sjdp >> RELOC_EXT_BITS_TYPE_SH_BIG); 520433965Sjdp } 520533965Sjdp else 520633965Sjdp { 520733965Sjdp r_index = ((rel->r_index[2] << 16) 520833965Sjdp | (rel->r_index[1] << 8) 520933965Sjdp | rel->r_index[0]); 521033965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 521133965Sjdp r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 521233965Sjdp >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 521333965Sjdp } 521433965Sjdp 521533965Sjdp r_addend = GET_SWORD (input_bfd, rel->r_addend); 521633965Sjdp 521733965Sjdp BFD_ASSERT (r_type < TABLE_SIZE (howto_table_ext)); 521833965Sjdp 521933965Sjdp if (relocateable) 522033965Sjdp { 522133965Sjdp /* We are generating a relocateable output file, and must 522233965Sjdp modify the reloc accordingly. */ 522333965Sjdp if (r_extern 522433965Sjdp || r_type == RELOC_BASE10 522533965Sjdp || r_type == RELOC_BASE13 522633965Sjdp || r_type == RELOC_BASE22) 522733965Sjdp { 522833965Sjdp /* If we know the symbol this relocation is against, 522933965Sjdp convert it into a relocation against a section. This 523033965Sjdp is what the native linker does. */ 523133965Sjdp if (r_type == RELOC_BASE10 523233965Sjdp || r_type == RELOC_BASE13 523333965Sjdp || r_type == RELOC_BASE22) 523433965Sjdp h = NULL; 523533965Sjdp else 523633965Sjdp h = sym_hashes[r_index]; 523733965Sjdp if (h != (struct aout_link_hash_entry *) NULL 523833965Sjdp && (h->root.type == bfd_link_hash_defined 523933965Sjdp || h->root.type == bfd_link_hash_defweak)) 524033965Sjdp { 524133965Sjdp asection *output_section; 524233965Sjdp 524333965Sjdp /* Change the r_extern value. */ 524433965Sjdp if (bfd_header_big_endian (output_bfd)) 524533965Sjdp rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; 524633965Sjdp else 524733965Sjdp rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; 524833965Sjdp 524933965Sjdp /* Compute a new r_index. */ 525033965Sjdp output_section = h->root.u.def.section->output_section; 525133965Sjdp if (output_section == obj_textsec (output_bfd)) 525233965Sjdp r_index = N_TEXT; 525333965Sjdp else if (output_section == obj_datasec (output_bfd)) 525433965Sjdp r_index = N_DATA; 525533965Sjdp else if (output_section == obj_bsssec (output_bfd)) 525633965Sjdp r_index = N_BSS; 525733965Sjdp else 525833965Sjdp r_index = N_ABS; 525933965Sjdp 526033965Sjdp /* Add the symbol value and the section VMA to the 526133965Sjdp addend. */ 526233965Sjdp relocation = (h->root.u.def.value 526333965Sjdp + output_section->vma 526433965Sjdp + h->root.u.def.section->output_offset); 526533965Sjdp 526633965Sjdp /* Now RELOCATION is the VMA of the final 526733965Sjdp destination. If this is a PC relative reloc, 526833965Sjdp then ADDEND is the negative of the source VMA. 526933965Sjdp We want to set ADDEND to the difference between 527033965Sjdp the destination VMA and the source VMA, which 527133965Sjdp means we must adjust RELOCATION by the change in 527233965Sjdp the source VMA. This is done below. */ 527333965Sjdp } 527433965Sjdp else 527533965Sjdp { 527633965Sjdp /* We must change r_index according to the symbol 527733965Sjdp map. */ 527833965Sjdp r_index = symbol_map[r_index]; 527933965Sjdp 528033965Sjdp if (r_index == -1) 528133965Sjdp { 528233965Sjdp if (h != NULL) 528333965Sjdp { 528433965Sjdp /* We decided to strip this symbol, but it 528533965Sjdp turns out that we can't. Note that we 528633965Sjdp lose the other and desc information here. 528733965Sjdp I don't think that will ever matter for a 528833965Sjdp global symbol. */ 528933965Sjdp if (h->indx < 0) 529033965Sjdp { 529133965Sjdp h->indx = -2; 529233965Sjdp h->written = false; 529333965Sjdp if (! aout_link_write_other_symbol (h, 529433965Sjdp (PTR) finfo)) 529533965Sjdp return false; 529633965Sjdp } 529733965Sjdp r_index = h->indx; 529833965Sjdp } 529933965Sjdp else 530033965Sjdp { 530133965Sjdp const char *name; 530233965Sjdp 530333965Sjdp name = strings + GET_WORD (input_bfd, 530433965Sjdp syms[r_index].e_strx); 530533965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 530633965Sjdp (finfo->info, name, input_bfd, input_section, 530733965Sjdp r_addr))) 530833965Sjdp return false; 530933965Sjdp r_index = 0; 531033965Sjdp } 531133965Sjdp } 531233965Sjdp 531333965Sjdp relocation = 0; 531433965Sjdp 531533965Sjdp /* If this is a PC relative reloc, then the addend 531633965Sjdp is the negative of the source VMA. We must 531733965Sjdp adjust it by the change in the source VMA. This 531833965Sjdp is done below. */ 531933965Sjdp } 532033965Sjdp 532133965Sjdp /* Write out the new r_index value. */ 532233965Sjdp if (bfd_header_big_endian (output_bfd)) 532333965Sjdp { 532433965Sjdp rel->r_index[0] = r_index >> 16; 532533965Sjdp rel->r_index[1] = r_index >> 8; 532633965Sjdp rel->r_index[2] = r_index; 532733965Sjdp } 532833965Sjdp else 532933965Sjdp { 533033965Sjdp rel->r_index[2] = r_index >> 16; 533133965Sjdp rel->r_index[1] = r_index >> 8; 533233965Sjdp rel->r_index[0] = r_index; 533333965Sjdp } 533433965Sjdp } 533533965Sjdp else 533633965Sjdp { 533733965Sjdp /* This is a relocation against a section. We must 533833965Sjdp adjust by the amount that the section moved. */ 533933965Sjdp r_section = aout_reloc_index_to_section (input_bfd, r_index); 534033965Sjdp relocation = (r_section->output_section->vma 534133965Sjdp + r_section->output_offset 534233965Sjdp - r_section->vma); 534333965Sjdp 534433965Sjdp /* If this is a PC relative reloc, then the addend is 534533965Sjdp the difference in VMA between the destination and the 534633965Sjdp source. We have just adjusted for the change in VMA 534733965Sjdp of the destination, so we must also adjust by the 534833965Sjdp change in VMA of the source. This is done below. */ 534933965Sjdp } 535033965Sjdp 535133965Sjdp /* As described above, we must always adjust a PC relative 535233965Sjdp reloc by the change in VMA of the source. However, if 535333965Sjdp pcrel_offset is set, then the addend does not include the 535433965Sjdp location within the section, in which case we don't need 535533965Sjdp to adjust anything. */ 535633965Sjdp if (howto_table_ext[r_type].pc_relative 535733965Sjdp && ! howto_table_ext[r_type].pcrel_offset) 535833965Sjdp relocation -= (input_section->output_section->vma 535933965Sjdp + input_section->output_offset 536033965Sjdp - input_section->vma); 536133965Sjdp 536233965Sjdp /* Change the addend if necessary. */ 536333965Sjdp if (relocation != 0) 536433965Sjdp PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend); 536533965Sjdp 536633965Sjdp /* Change the address of the relocation. */ 536733965Sjdp PUT_WORD (output_bfd, 536833965Sjdp r_addr + input_section->output_offset, 536933965Sjdp rel->r_address); 537033965Sjdp } 537133965Sjdp else 537233965Sjdp { 537333965Sjdp boolean hundef; 537433965Sjdp bfd_reloc_status_type r; 537533965Sjdp 537633965Sjdp /* We are generating an executable, and must do a full 537733965Sjdp relocation. */ 537833965Sjdp hundef = false; 537960484Sobrien 538033965Sjdp if (r_extern) 538133965Sjdp { 538233965Sjdp h = sym_hashes[r_index]; 538333965Sjdp 538433965Sjdp if (h != (struct aout_link_hash_entry *) NULL 538533965Sjdp && (h->root.type == bfd_link_hash_defined 538633965Sjdp || h->root.type == bfd_link_hash_defweak)) 538733965Sjdp { 538833965Sjdp relocation = (h->root.u.def.value 538933965Sjdp + h->root.u.def.section->output_section->vma 539033965Sjdp + h->root.u.def.section->output_offset); 539133965Sjdp } 539233965Sjdp else if (h != (struct aout_link_hash_entry *) NULL 539333965Sjdp && h->root.type == bfd_link_hash_undefweak) 539433965Sjdp relocation = 0; 539533965Sjdp else 539633965Sjdp { 539733965Sjdp hundef = true; 539833965Sjdp relocation = 0; 539933965Sjdp } 540033965Sjdp } 540133965Sjdp else if (r_type == RELOC_BASE10 540233965Sjdp || r_type == RELOC_BASE13 540333965Sjdp || r_type == RELOC_BASE22) 540433965Sjdp { 540533965Sjdp struct external_nlist *sym; 540633965Sjdp int type; 540733965Sjdp 540833965Sjdp /* For base relative relocs, r_index is always an index 540933965Sjdp into the symbol table, even if r_extern is 0. */ 541033965Sjdp sym = syms + r_index; 541189857Sobrien type = H_GET_8 (input_bfd, sym->e_type); 541233965Sjdp if ((type & N_TYPE) == N_TEXT 541333965Sjdp || type == N_WEAKT) 541433965Sjdp r_section = obj_textsec (input_bfd); 541533965Sjdp else if ((type & N_TYPE) == N_DATA 541633965Sjdp || type == N_WEAKD) 541733965Sjdp r_section = obj_datasec (input_bfd); 541833965Sjdp else if ((type & N_TYPE) == N_BSS 541933965Sjdp || type == N_WEAKB) 542033965Sjdp r_section = obj_bsssec (input_bfd); 542133965Sjdp else if ((type & N_TYPE) == N_ABS 542233965Sjdp || type == N_WEAKA) 542333965Sjdp r_section = bfd_abs_section_ptr; 542433965Sjdp else 542533965Sjdp abort (); 542633965Sjdp relocation = (r_section->output_section->vma 542733965Sjdp + r_section->output_offset 542833965Sjdp + (GET_WORD (input_bfd, sym->e_value) 542933965Sjdp - r_section->vma)); 543033965Sjdp } 543133965Sjdp else 543233965Sjdp { 543333965Sjdp r_section = aout_reloc_index_to_section (input_bfd, r_index); 543433965Sjdp 543533965Sjdp /* If this is a PC relative reloc, then R_ADDEND is the 543633965Sjdp difference between the two vmas, or 543733965Sjdp old_dest_sec + old_dest_off - (old_src_sec + old_src_off) 543833965Sjdp where 543933965Sjdp old_dest_sec == section->vma 544033965Sjdp and 544133965Sjdp old_src_sec == input_section->vma 544233965Sjdp and 544333965Sjdp old_src_off == r_addr 544433965Sjdp 544533965Sjdp _bfd_final_link_relocate expects RELOCATION + 544633965Sjdp R_ADDEND to be the VMA of the destination minus 544733965Sjdp r_addr (the minus r_addr is because this relocation 544833965Sjdp is not pcrel_offset, which is a bit confusing and 544933965Sjdp should, perhaps, be changed), or 545033965Sjdp new_dest_sec 545133965Sjdp where 545233965Sjdp new_dest_sec == output_section->vma + output_offset 545333965Sjdp We arrange for this to happen by setting RELOCATION to 545433965Sjdp new_dest_sec + old_src_sec - old_dest_sec 545533965Sjdp 545633965Sjdp If this is not a PC relative reloc, then R_ADDEND is 545733965Sjdp simply the VMA of the destination, so we set 545833965Sjdp RELOCATION to the change in the destination VMA, or 545933965Sjdp new_dest_sec - old_dest_sec 546033965Sjdp */ 546133965Sjdp relocation = (r_section->output_section->vma 546233965Sjdp + r_section->output_offset 546333965Sjdp - r_section->vma); 546433965Sjdp if (howto_table_ext[r_type].pc_relative) 546533965Sjdp relocation += input_section->vma; 546633965Sjdp } 546733965Sjdp 546833965Sjdp if (check_dynamic_reloc != NULL) 546933965Sjdp { 547033965Sjdp boolean skip; 547133965Sjdp 547233965Sjdp if (! ((*check_dynamic_reloc) 547333965Sjdp (finfo->info, input_bfd, input_section, h, 547433965Sjdp (PTR) rel, contents, &skip, &relocation))) 547533965Sjdp return false; 547633965Sjdp if (skip) 547733965Sjdp continue; 547833965Sjdp } 547933965Sjdp 548033965Sjdp /* Now warn if a global symbol is undefined. We could not 548133965Sjdp do this earlier, because check_dynamic_reloc might want 548233965Sjdp to skip this reloc. */ 548333965Sjdp if (hundef 548433965Sjdp && ! finfo->info->shared 548533965Sjdp && r_type != RELOC_BASE10 548633965Sjdp && r_type != RELOC_BASE13 548733965Sjdp && r_type != RELOC_BASE22) 548833965Sjdp { 548933965Sjdp const char *name; 549033965Sjdp 549133965Sjdp if (h != NULL) 549233965Sjdp name = h->root.root.string; 549333965Sjdp else 549433965Sjdp name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); 549533965Sjdp if (! ((*finfo->info->callbacks->undefined_symbol) 549660484Sobrien (finfo->info, name, input_bfd, input_section, 549760484Sobrien r_addr, true))) 549833965Sjdp return false; 549933965Sjdp } 550033965Sjdp 550160484Sobrien if (r_type != RELOC_SPARC_REV32) 550260484Sobrien r = MY_final_link_relocate (howto_table_ext + r_type, 550360484Sobrien input_bfd, input_section, 550460484Sobrien contents, r_addr, relocation, 550560484Sobrien r_addend); 550660484Sobrien else 550760484Sobrien { 550860484Sobrien bfd_vma x; 550960484Sobrien 551060484Sobrien x = bfd_get_32 (input_bfd, contents + r_addr); 551160484Sobrien x = x + relocation + r_addend; 551260484Sobrien bfd_putl32 (/*input_bfd,*/ x, contents + r_addr); 551360484Sobrien r = bfd_reloc_ok; 551460484Sobrien } 551560484Sobrien 551633965Sjdp if (r != bfd_reloc_ok) 551733965Sjdp { 551833965Sjdp switch (r) 551933965Sjdp { 552033965Sjdp default: 552133965Sjdp case bfd_reloc_outofrange: 552233965Sjdp abort (); 552333965Sjdp case bfd_reloc_overflow: 552433965Sjdp { 552533965Sjdp const char *name; 552633965Sjdp 552733965Sjdp if (h != NULL) 552833965Sjdp name = h->root.root.string; 552933965Sjdp else if (r_extern 553033965Sjdp || r_type == RELOC_BASE10 553133965Sjdp || r_type == RELOC_BASE13 553233965Sjdp || r_type == RELOC_BASE22) 553333965Sjdp name = strings + GET_WORD (input_bfd, 553433965Sjdp syms[r_index].e_strx); 553533965Sjdp else 553633965Sjdp { 553733965Sjdp asection *s; 553833965Sjdp 553933965Sjdp s = aout_reloc_index_to_section (input_bfd, r_index); 554033965Sjdp name = bfd_section_name (input_bfd, s); 554133965Sjdp } 554233965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 554333965Sjdp (finfo->info, name, howto_table_ext[r_type].name, 554433965Sjdp r_addend, input_bfd, input_section, r_addr))) 554533965Sjdp return false; 554633965Sjdp } 554733965Sjdp break; 554833965Sjdp } 554933965Sjdp } 555033965Sjdp } 555133965Sjdp } 555233965Sjdp 555333965Sjdp return true; 555433965Sjdp} 555533965Sjdp 555633965Sjdp/* Handle a link order which is supposed to generate a reloc. */ 555733965Sjdp 555833965Sjdpstatic boolean 555933965Sjdpaout_link_reloc_link_order (finfo, o, p) 556033965Sjdp struct aout_final_link_info *finfo; 556133965Sjdp asection *o; 556233965Sjdp struct bfd_link_order *p; 556333965Sjdp{ 556433965Sjdp struct bfd_link_order_reloc *pr; 556533965Sjdp int r_index; 556633965Sjdp int r_extern; 556733965Sjdp reloc_howto_type *howto; 556860484Sobrien file_ptr *reloff_ptr = NULL; 556933965Sjdp struct reloc_std_external srel; 557033965Sjdp struct reloc_ext_external erel; 557133965Sjdp PTR rel_ptr; 557289857Sobrien bfd_size_type amt; 557333965Sjdp 557433965Sjdp pr = p->u.reloc.p; 557533965Sjdp 557633965Sjdp if (p->type == bfd_section_reloc_link_order) 557733965Sjdp { 557833965Sjdp r_extern = 0; 557933965Sjdp if (bfd_is_abs_section (pr->u.section)) 558033965Sjdp r_index = N_ABS | N_EXT; 558133965Sjdp else 558233965Sjdp { 558333965Sjdp BFD_ASSERT (pr->u.section->owner == finfo->output_bfd); 558433965Sjdp r_index = pr->u.section->target_index; 558533965Sjdp } 558633965Sjdp } 558733965Sjdp else 558833965Sjdp { 558933965Sjdp struct aout_link_hash_entry *h; 559033965Sjdp 559133965Sjdp BFD_ASSERT (p->type == bfd_symbol_reloc_link_order); 559233965Sjdp r_extern = 1; 559333965Sjdp h = ((struct aout_link_hash_entry *) 559433965Sjdp bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info, 559533965Sjdp pr->u.name, false, false, true)); 559633965Sjdp if (h != (struct aout_link_hash_entry *) NULL 559733965Sjdp && h->indx >= 0) 559833965Sjdp r_index = h->indx; 559933965Sjdp else if (h != NULL) 560033965Sjdp { 560133965Sjdp /* We decided to strip this symbol, but it turns out that we 560233965Sjdp can't. Note that we lose the other and desc information 560333965Sjdp here. I don't think that will ever matter for a global 560433965Sjdp symbol. */ 560533965Sjdp h->indx = -2; 560633965Sjdp h->written = false; 560733965Sjdp if (! aout_link_write_other_symbol (h, (PTR) finfo)) 560833965Sjdp return false; 560933965Sjdp r_index = h->indx; 561033965Sjdp } 561133965Sjdp else 561233965Sjdp { 561333965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 561433965Sjdp (finfo->info, pr->u.name, (bfd *) NULL, 561533965Sjdp (asection *) NULL, (bfd_vma) 0))) 561633965Sjdp return false; 561733965Sjdp r_index = 0; 561833965Sjdp } 561933965Sjdp } 562033965Sjdp 562133965Sjdp howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc); 562233965Sjdp if (howto == 0) 562333965Sjdp { 562433965Sjdp bfd_set_error (bfd_error_bad_value); 562533965Sjdp return false; 562633965Sjdp } 562733965Sjdp 562833965Sjdp if (o == obj_textsec (finfo->output_bfd)) 562933965Sjdp reloff_ptr = &finfo->treloff; 563033965Sjdp else if (o == obj_datasec (finfo->output_bfd)) 563133965Sjdp reloff_ptr = &finfo->dreloff; 563233965Sjdp else 563333965Sjdp abort (); 563433965Sjdp 563533965Sjdp if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE) 563633965Sjdp { 563733965Sjdp#ifdef MY_put_reloc 563889857Sobrien MY_put_reloc (finfo->output_bfd, r_extern, r_index, p->offset, howto, 563989857Sobrien &srel); 564033965Sjdp#else 564133965Sjdp { 564233965Sjdp int r_pcrel; 564333965Sjdp int r_baserel; 564433965Sjdp int r_jmptable; 564533965Sjdp int r_relative; 564633965Sjdp int r_length; 564733965Sjdp 564833965Sjdp r_pcrel = howto->pc_relative; 564933965Sjdp r_baserel = (howto->type & 8) != 0; 565033965Sjdp r_jmptable = (howto->type & 16) != 0; 565133965Sjdp r_relative = (howto->type & 32) != 0; 565233965Sjdp r_length = howto->size; 565333965Sjdp 565433965Sjdp PUT_WORD (finfo->output_bfd, p->offset, srel.r_address); 565533965Sjdp if (bfd_header_big_endian (finfo->output_bfd)) 565633965Sjdp { 565733965Sjdp srel.r_index[0] = r_index >> 16; 565833965Sjdp srel.r_index[1] = r_index >> 8; 565933965Sjdp srel.r_index[2] = r_index; 566033965Sjdp srel.r_type[0] = 566133965Sjdp ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) 566233965Sjdp | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) 566333965Sjdp | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) 566433965Sjdp | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) 566533965Sjdp | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) 566633965Sjdp | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); 566733965Sjdp } 566833965Sjdp else 566933965Sjdp { 567033965Sjdp srel.r_index[2] = r_index >> 16; 567133965Sjdp srel.r_index[1] = r_index >> 8; 567233965Sjdp srel.r_index[0] = r_index; 567333965Sjdp srel.r_type[0] = 567433965Sjdp ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) 567533965Sjdp | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) 567633965Sjdp | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) 567733965Sjdp | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) 567833965Sjdp | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) 567933965Sjdp | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 568033965Sjdp } 568133965Sjdp } 568233965Sjdp#endif 568333965Sjdp rel_ptr = (PTR) &srel; 568433965Sjdp 568533965Sjdp /* We have to write the addend into the object file, since 568633965Sjdp standard a.out relocs are in place. It would be more 568733965Sjdp reliable if we had the current contents of the file here, 568833965Sjdp rather than assuming zeroes, but we can't read the file since 568933965Sjdp it was opened using bfd_openw. */ 569033965Sjdp if (pr->addend != 0) 569133965Sjdp { 569233965Sjdp bfd_size_type size; 569333965Sjdp bfd_reloc_status_type r; 569433965Sjdp bfd_byte *buf; 569533965Sjdp boolean ok; 569633965Sjdp 569733965Sjdp size = bfd_get_reloc_size (howto); 569833965Sjdp buf = (bfd_byte *) bfd_zmalloc (size); 569933965Sjdp if (buf == (bfd_byte *) NULL) 570033965Sjdp return false; 570133965Sjdp r = MY_relocate_contents (howto, finfo->output_bfd, 570289857Sobrien (bfd_vma) pr->addend, buf); 570333965Sjdp switch (r) 570433965Sjdp { 570533965Sjdp case bfd_reloc_ok: 570633965Sjdp break; 570733965Sjdp default: 570833965Sjdp case bfd_reloc_outofrange: 570933965Sjdp abort (); 571033965Sjdp case bfd_reloc_overflow: 571133965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 571233965Sjdp (finfo->info, 571333965Sjdp (p->type == bfd_section_reloc_link_order 571433965Sjdp ? bfd_section_name (finfo->output_bfd, 571533965Sjdp pr->u.section) 571633965Sjdp : pr->u.name), 571733965Sjdp howto->name, pr->addend, (bfd *) NULL, 571833965Sjdp (asection *) NULL, (bfd_vma) 0))) 571933965Sjdp { 572033965Sjdp free (buf); 572133965Sjdp return false; 572233965Sjdp } 572333965Sjdp break; 572433965Sjdp } 572589857Sobrien ok = bfd_set_section_contents (finfo->output_bfd, o, (PTR) buf, 572689857Sobrien (file_ptr) p->offset, size); 572733965Sjdp free (buf); 572833965Sjdp if (! ok) 572933965Sjdp return false; 573033965Sjdp } 573133965Sjdp } 573233965Sjdp else 573333965Sjdp { 573477298Sobrien#ifdef MY_put_ext_reloc 573577298Sobrien MY_put_ext_reloc (finfo->output_bfd, r_extern, r_index, p->offset, 573677298Sobrien howto, &erel, pr->addend); 573777298Sobrien#else 573833965Sjdp PUT_WORD (finfo->output_bfd, p->offset, erel.r_address); 573933965Sjdp 574033965Sjdp if (bfd_header_big_endian (finfo->output_bfd)) 574133965Sjdp { 574233965Sjdp erel.r_index[0] = r_index >> 16; 574333965Sjdp erel.r_index[1] = r_index >> 8; 574433965Sjdp erel.r_index[2] = r_index; 574533965Sjdp erel.r_type[0] = 574633965Sjdp ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) 574733965Sjdp | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG)); 574833965Sjdp } 574933965Sjdp else 575033965Sjdp { 575133965Sjdp erel.r_index[2] = r_index >> 16; 575233965Sjdp erel.r_index[1] = r_index >> 8; 575333965Sjdp erel.r_index[0] = r_index; 575433965Sjdp erel.r_type[0] = 575533965Sjdp (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) 575633965Sjdp | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE); 575733965Sjdp } 575833965Sjdp 575989857Sobrien PUT_WORD (finfo->output_bfd, (bfd_vma) pr->addend, erel.r_addend); 576077298Sobrien#endif /* MY_put_ext_reloc */ 576133965Sjdp 576233965Sjdp rel_ptr = (PTR) &erel; 576333965Sjdp } 576433965Sjdp 576589857Sobrien amt = obj_reloc_entry_size (finfo->output_bfd); 576633965Sjdp if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0 576789857Sobrien || bfd_bwrite (rel_ptr, amt, finfo->output_bfd) != amt) 576833965Sjdp return false; 576933965Sjdp 577033965Sjdp *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd); 577133965Sjdp 577233965Sjdp /* Assert that the relocs have not run into the symbols, and that n 577333965Sjdp the text relocs have not run into the data relocs. */ 577433965Sjdp BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) 577533965Sjdp && (reloff_ptr != &finfo->treloff 577633965Sjdp || (*reloff_ptr 577733965Sjdp <= obj_datasec (finfo->output_bfd)->rel_filepos))); 577833965Sjdp 577933965Sjdp return true; 578033965Sjdp} 5781