133965Sjdp/* BFD semi-generic back-end for a.out binaries. 2218822Sdim Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3218822Sdim 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 438889Sjdp Free Software Foundation, Inc. 533965Sjdp Written by Cygnus Support. 633965Sjdp 7130561Sobrien This file is part of BFD, the Binary File Descriptor library. 833965Sjdp 9130561Sobrien This program is free software; you can redistribute it and/or modify 10130561Sobrien it under the terms of the GNU General Public License as published by 11130561Sobrien the Free Software Foundation; either version 2 of the License, or 12130561Sobrien (at your option) any later version. 1333965Sjdp 14130561Sobrien This program is distributed in the hope that it will be useful, 15130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 16130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17130561Sobrien GNU General Public License for more details. 1833965Sjdp 19130561Sobrien You should have received a copy of the GNU General Public License 20130561Sobrien along with this program; if not, write to the Free Software 21218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 108130561Sobrien configuration is selected. */ 10933965Sjdp 11033965Sjdp/* Some assumptions: 11133965Sjdp * Any BFD with D_PAGED set is ZMAGIC, and vice versa. 11233965Sjdp Doesn't matter what the setting of WP_TEXT is on output, but it'll 11333965Sjdp get set on input. 11433965Sjdp * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC. 11533965Sjdp * Any BFD with both flags clear is OMAGIC. 11633965Sjdp (Just want to make these explicit, so the conditions tested in this 11733965Sjdp file make sense if you're more familiar with a.out than with BFD.) */ 11833965Sjdp 11933965Sjdp#define KEEPIT udata.i 12033965Sjdp 121218822Sdim#include "sysdep.h" 12233965Sjdp#include "bfd.h" 12389857Sobrien#include "safe-ctype.h" 12433965Sjdp#include "bfdlink.h" 12533965Sjdp 12633965Sjdp#include "libaout.h" 12733965Sjdp#include "libbfd.h" 12833965Sjdp#include "aout/aout64.h" 12933965Sjdp#include "aout/stab_gnu.h" 13033965Sjdp#include "aout/ar.h" 13133965Sjdp 13233965Sjdp/* 13333965SjdpSUBSECTION 13433965Sjdp Relocations 13533965Sjdp 13633965SjdpDESCRIPTION 13733965Sjdp The file @file{aoutx.h} provides for both the @emph{standard} 13833965Sjdp and @emph{extended} forms of a.out relocation records. 13933965Sjdp 14033965Sjdp The standard records contain only an 14133965Sjdp address, a symbol index, and a type field. The extended records 14233965Sjdp (used on 29ks and sparcs) also have a full integer for an 143130561Sobrien addend. */ 14433965Sjdp 14533965Sjdp#ifndef CTOR_TABLE_RELOC_HOWTO 14633965Sjdp#define CTOR_TABLE_RELOC_IDX 2 14789857Sobrien#define CTOR_TABLE_RELOC_HOWTO(BFD) \ 14889857Sobrien ((obj_reloc_entry_size (BFD) == RELOC_EXT_SIZE \ 14989857Sobrien ? howto_table_ext : howto_table_std) \ 15089857Sobrien + CTOR_TABLE_RELOC_IDX) 15133965Sjdp#endif 15233965Sjdp 15333965Sjdp#ifndef MY_swap_std_reloc_in 154218822Sdim#define MY_swap_std_reloc_in NAME (aout, swap_std_reloc_in) 15533965Sjdp#endif 15633965Sjdp 15777298Sobrien#ifndef MY_swap_ext_reloc_in 158218822Sdim#define MY_swap_ext_reloc_in NAME (aout, swap_ext_reloc_in) 15977298Sobrien#endif 16077298Sobrien 16133965Sjdp#ifndef MY_swap_std_reloc_out 162218822Sdim#define MY_swap_std_reloc_out NAME (aout, swap_std_reloc_out) 16333965Sjdp#endif 16433965Sjdp 16577298Sobrien#ifndef MY_swap_ext_reloc_out 166218822Sdim#define MY_swap_ext_reloc_out NAME (aout, swap_ext_reloc_out) 16777298Sobrien#endif 16877298Sobrien 16933965Sjdp#ifndef MY_final_link_relocate 17033965Sjdp#define MY_final_link_relocate _bfd_final_link_relocate 17133965Sjdp#endif 17233965Sjdp 17333965Sjdp#ifndef MY_relocate_contents 17433965Sjdp#define MY_relocate_contents _bfd_relocate_contents 17533965Sjdp#endif 17633965Sjdp 177218822Sdim#define howto_table_ext NAME (aout, ext_howto_table) 178218822Sdim#define howto_table_std NAME (aout, std_howto_table) 17933965Sjdp 18033965Sjdpreloc_howto_type howto_table_ext[] = 18133965Sjdp{ 182218822Sdim /* Type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone. */ 183218822Sdim HOWTO (RELOC_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "8", FALSE, 0, 0x000000ff, FALSE), 184218822Sdim HOWTO (RELOC_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "16", FALSE, 0, 0x0000ffff, FALSE), 185218822Sdim HOWTO (RELOC_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "32", FALSE, 0, 0xffffffff, FALSE), 186218822Sdim HOWTO (RELOC_DISP8, 0, 0, 8, TRUE, 0, complain_overflow_signed, 0, "DISP8", FALSE, 0, 0x000000ff, FALSE), 187218822Sdim HOWTO (RELOC_DISP16, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "DISP16", FALSE, 0, 0x0000ffff, FALSE), 188218822Sdim HOWTO (RELOC_DISP32, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0, "DISP32", FALSE, 0, 0xffffffff, FALSE), 189218822Sdim HOWTO (RELOC_WDISP30, 2, 2, 30, TRUE, 0, complain_overflow_signed, 0, "WDISP30", FALSE, 0, 0x3fffffff, FALSE), 190218822Sdim HOWTO (RELOC_WDISP22, 2, 2, 22, TRUE, 0, complain_overflow_signed, 0, "WDISP22", FALSE, 0, 0x003fffff, FALSE), 191218822Sdim HOWTO (RELOC_HI22, 10, 2, 22, FALSE, 0, complain_overflow_bitfield, 0, "HI22", FALSE, 0, 0x003fffff, FALSE), 192218822Sdim HOWTO (RELOC_22, 0, 2, 22, FALSE, 0, complain_overflow_bitfield, 0, "22", FALSE, 0, 0x003fffff, FALSE), 193218822Sdim HOWTO (RELOC_13, 0, 2, 13, FALSE, 0, complain_overflow_bitfield, 0, "13", FALSE, 0, 0x00001fff, FALSE), 194218822Sdim HOWTO (RELOC_LO10, 0, 2, 10, FALSE, 0, complain_overflow_dont, 0, "LO10", FALSE, 0, 0x000003ff, FALSE), 195218822Sdim HOWTO (RELOC_SFA_BASE,0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "SFA_BASE", FALSE, 0, 0xffffffff, FALSE), 196218822Sdim HOWTO (RELOC_SFA_OFF13,0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "SFA_OFF13", FALSE, 0, 0xffffffff, FALSE), 197218822Sdim HOWTO (RELOC_BASE10, 0, 2, 10, FALSE, 0, complain_overflow_dont, 0, "BASE10", FALSE, 0, 0x000003ff, FALSE), 198218822Sdim HOWTO (RELOC_BASE13, 0, 2, 13, FALSE, 0, complain_overflow_signed, 0, "BASE13", FALSE, 0, 0x00001fff, FALSE), 199218822Sdim HOWTO (RELOC_BASE22, 10, 2, 22, FALSE, 0, complain_overflow_bitfield, 0, "BASE22", FALSE, 0, 0x003fffff, FALSE), 200218822Sdim HOWTO (RELOC_PC10, 0, 2, 10, TRUE, 0, complain_overflow_dont, 0, "PC10", FALSE, 0, 0x000003ff, TRUE), 201218822Sdim HOWTO (RELOC_PC22, 10, 2, 22, TRUE, 0, complain_overflow_signed, 0, "PC22", FALSE, 0, 0x003fffff, TRUE), 202218822Sdim HOWTO (RELOC_JMP_TBL, 2, 2, 30, TRUE, 0, complain_overflow_signed, 0, "JMP_TBL", FALSE, 0, 0x3fffffff, FALSE), 203218822Sdim HOWTO (RELOC_SEGOFF16,0, 2, 0, FALSE, 0, complain_overflow_bitfield, 0, "SEGOFF16", FALSE, 0, 0x00000000, FALSE), 204218822Sdim HOWTO (RELOC_GLOB_DAT,0, 2, 0, FALSE, 0, complain_overflow_bitfield, 0, "GLOB_DAT", FALSE, 0, 0x00000000, FALSE), 205218822Sdim HOWTO (RELOC_JMP_SLOT,0, 2, 0, FALSE, 0, complain_overflow_bitfield, 0, "JMP_SLOT", FALSE, 0, 0x00000000, FALSE), 206218822Sdim HOWTO (RELOC_RELATIVE,0, 2, 0, FALSE, 0, complain_overflow_bitfield, 0, "RELATIVE", FALSE, 0, 0x00000000, FALSE), 207218822Sdim HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, 0, "R_SPARC_NONE",FALSE, 0, 0x00000000, TRUE), 208218822Sdim HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, 0, "R_SPARC_NONE",FALSE, 0, 0x00000000, TRUE), 20960484Sobrien#define RELOC_SPARC_REV32 RELOC_WDISP19 210218822Sdim HOWTO (RELOC_SPARC_REV32, 0, 2, 32, FALSE, 0, complain_overflow_dont, 0,"R_SPARC_REV32",FALSE, 0, 0xffffffff, FALSE), 21133965Sjdp}; 21233965Sjdp 21333965Sjdp/* Convert standard reloc records to "arelent" format (incl byte swap). */ 21433965Sjdp 215130561Sobrienreloc_howto_type howto_table_std[] = 216130561Sobrien{ 217130561Sobrien /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone. */ 218130561SobrienHOWTO ( 0, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,0,"8", TRUE, 0x000000ff,0x000000ff, FALSE), 219130561SobrienHOWTO ( 1, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,0,"16", TRUE, 0x0000ffff,0x0000ffff, FALSE), 220130561SobrienHOWTO ( 2, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"32", TRUE, 0xffffffff,0xffffffff, FALSE), 221130561SobrienHOWTO ( 3, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,0,"64", TRUE, 0xdeaddead,0xdeaddead, FALSE), 222130561SobrienHOWTO ( 4, 0, 0, 8, TRUE, 0, complain_overflow_signed, 0,"DISP8", TRUE, 0x000000ff,0x000000ff, FALSE), 223130561SobrienHOWTO ( 5, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0,"DISP16", TRUE, 0x0000ffff,0x0000ffff, FALSE), 224130561SobrienHOWTO ( 6, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0,"DISP32", TRUE, 0xffffffff,0xffffffff, FALSE), 225130561SobrienHOWTO ( 7, 0, 4, 64, TRUE, 0, complain_overflow_signed, 0,"DISP64", TRUE, 0xfeedface,0xfeedface, FALSE), 226130561SobrienHOWTO ( 8, 0, 2, 0, FALSE, 0, complain_overflow_bitfield,0,"GOT_REL", FALSE, 0,0x00000000, FALSE), 227130561SobrienHOWTO ( 9, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,0,"BASE16", FALSE,0xffffffff,0xffffffff, FALSE), 228130561SobrienHOWTO (10, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"BASE32", FALSE,0xffffffff,0xffffffff, FALSE), 22960484SobrienEMPTY_HOWTO (-1), 23060484SobrienEMPTY_HOWTO (-1), 23160484SobrienEMPTY_HOWTO (-1), 23260484SobrienEMPTY_HOWTO (-1), 23360484SobrienEMPTY_HOWTO (-1), 234130561Sobrien HOWTO (16, 0, 2, 0, FALSE, 0, complain_overflow_bitfield,0,"JMP_TABLE", FALSE, 0,0x00000000, FALSE), 23560484SobrienEMPTY_HOWTO (-1), 23660484SobrienEMPTY_HOWTO (-1), 23760484SobrienEMPTY_HOWTO (-1), 23860484SobrienEMPTY_HOWTO (-1), 23960484SobrienEMPTY_HOWTO (-1), 24060484SobrienEMPTY_HOWTO (-1), 24160484SobrienEMPTY_HOWTO (-1), 24260484SobrienEMPTY_HOWTO (-1), 24360484SobrienEMPTY_HOWTO (-1), 24460484SobrienEMPTY_HOWTO (-1), 24560484SobrienEMPTY_HOWTO (-1), 24660484SobrienEMPTY_HOWTO (-1), 24760484SobrienEMPTY_HOWTO (-1), 24860484SobrienEMPTY_HOWTO (-1), 24960484SobrienEMPTY_HOWTO (-1), 250130561Sobrien HOWTO (32, 0, 2, 0, FALSE, 0, complain_overflow_bitfield,0,"RELATIVE", FALSE, 0,0x00000000, FALSE), 25160484SobrienEMPTY_HOWTO (-1), 25260484SobrienEMPTY_HOWTO (-1), 25360484SobrienEMPTY_HOWTO (-1), 25460484SobrienEMPTY_HOWTO (-1), 25560484SobrienEMPTY_HOWTO (-1), 25660484SobrienEMPTY_HOWTO (-1), 25760484SobrienEMPTY_HOWTO (-1), 258130561Sobrien HOWTO (40, 0, 2, 0, FALSE, 0, complain_overflow_bitfield,0,"BASEREL", FALSE, 0,0x00000000, FALSE), 25933965Sjdp}; 26033965Sjdp 26189857Sobrien#define TABLE_SIZE(TABLE) (sizeof (TABLE) / sizeof (TABLE[0])) 26233965Sjdp 26333965Sjdpreloc_howto_type * 264218822SdimNAME (aout, reloc_type_lookup) (bfd *abfd, bfd_reloc_code_real_type code) 26533965Sjdp{ 266218822Sdim#define EXT(i, j) case i: return & howto_table_ext [j] 267218822Sdim#define STD(i, j) case i: return & howto_table_std [j] 26833965Sjdp int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE; 269130561Sobrien 27033965Sjdp if (code == BFD_RELOC_CTOR) 27133965Sjdp switch (bfd_get_arch_info (abfd)->bits_per_address) 27233965Sjdp { 27333965Sjdp case 32: 27433965Sjdp code = BFD_RELOC_32; 27533965Sjdp break; 27633965Sjdp case 64: 27733965Sjdp code = BFD_RELOC_64; 27833965Sjdp break; 27933965Sjdp } 280130561Sobrien 28133965Sjdp if (ext) 28233965Sjdp switch (code) 28333965Sjdp { 28477298Sobrien EXT (BFD_RELOC_8, 0); 28577298Sobrien EXT (BFD_RELOC_16, 1); 28633965Sjdp EXT (BFD_RELOC_32, 2); 28733965Sjdp EXT (BFD_RELOC_HI22, 8); 28833965Sjdp EXT (BFD_RELOC_LO10, 11); 28933965Sjdp EXT (BFD_RELOC_32_PCREL_S2, 6); 29033965Sjdp EXT (BFD_RELOC_SPARC_WDISP22, 7); 29133965Sjdp EXT (BFD_RELOC_SPARC13, 10); 29233965Sjdp EXT (BFD_RELOC_SPARC_GOT10, 14); 29333965Sjdp EXT (BFD_RELOC_SPARC_BASE13, 15); 29433965Sjdp EXT (BFD_RELOC_SPARC_GOT13, 15); 29533965Sjdp EXT (BFD_RELOC_SPARC_GOT22, 16); 29633965Sjdp EXT (BFD_RELOC_SPARC_PC10, 17); 29733965Sjdp EXT (BFD_RELOC_SPARC_PC22, 18); 29833965Sjdp EXT (BFD_RELOC_SPARC_WPLT30, 19); 29960484Sobrien EXT (BFD_RELOC_SPARC_REV32, 26); 300218822Sdim default: 301218822Sdim return NULL; 30233965Sjdp } 30333965Sjdp else 304130561Sobrien /* std relocs. */ 30533965Sjdp switch (code) 30633965Sjdp { 307130561Sobrien STD (BFD_RELOC_8, 0); 30833965Sjdp STD (BFD_RELOC_16, 1); 30933965Sjdp STD (BFD_RELOC_32, 2); 31033965Sjdp STD (BFD_RELOC_8_PCREL, 4); 31133965Sjdp STD (BFD_RELOC_16_PCREL, 5); 31233965Sjdp STD (BFD_RELOC_32_PCREL, 6); 31333965Sjdp STD (BFD_RELOC_16_BASEREL, 9); 31433965Sjdp STD (BFD_RELOC_32_BASEREL, 10); 315218822Sdim default: 316218822Sdim return NULL; 31733965Sjdp } 31833965Sjdp} 31933965Sjdp 320218822Sdimreloc_howto_type * 321218822SdimNAME (aout, reloc_name_lookup) (bfd *abfd, const char *r_name) 322218822Sdim{ 323218822Sdim unsigned int i, size; 324218822Sdim reloc_howto_type *howto_table; 325218822Sdim 326218822Sdim if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE) 327218822Sdim { 328218822Sdim howto_table = howto_table_ext; 329218822Sdim size = sizeof (howto_table_ext) / sizeof (howto_table_ext[0]); 330218822Sdim } 331218822Sdim else 332218822Sdim { 333218822Sdim howto_table = howto_table_std; 334218822Sdim size = sizeof (howto_table_std) / sizeof (howto_table_std[0]); 335218822Sdim } 336218822Sdim 337218822Sdim for (i = 0; i < size; i++) 338218822Sdim if (howto_table[i].name != NULL 339218822Sdim && strcasecmp (howto_table[i].name, r_name) == 0) 340218822Sdim return &howto_table[i]; 341218822Sdim 342218822Sdim return NULL; 343218822Sdim} 344218822Sdim 34533965Sjdp/* 34633965SjdpSUBSECTION 34733965Sjdp Internal entry points 34833965Sjdp 34933965SjdpDESCRIPTION 35033965Sjdp @file{aoutx.h} exports several routines for accessing the 35133965Sjdp contents of an a.out file, which are gathered and exported in 35233965Sjdp turn by various format specific files (eg sunos.c). 35333965Sjdp*/ 35433965Sjdp 35533965Sjdp/* 35633965SjdpFUNCTION 35733965Sjdp aout_@var{size}_swap_exec_header_in 35833965Sjdp 35933965SjdpSYNOPSIS 36033965Sjdp void aout_@var{size}_swap_exec_header_in, 36133965Sjdp (bfd *abfd, 362218822Sdim struct external_exec *bytes, 36333965Sjdp struct internal_exec *execp); 36433965Sjdp 36533965SjdpDESCRIPTION 36633965Sjdp Swap the information in an executable header @var{raw_bytes} taken 36733965Sjdp from a raw byte stream memory image into the internal exec header 36833965Sjdp structure @var{execp}. 36933965Sjdp*/ 37033965Sjdp 37133965Sjdp#ifndef NAME_swap_exec_header_in 37233965Sjdpvoid 373218822SdimNAME (aout, swap_exec_header_in) (bfd *abfd, 374218822Sdim struct external_exec *bytes, 375218822Sdim struct internal_exec *execp) 37633965Sjdp{ 37733965Sjdp /* The internal_exec structure has some fields that are unused in this 37833965Sjdp configuration (IE for i960), so ensure that all such uninitialized 37933965Sjdp fields are zero'd out. There are places where two of these structs 38077298Sobrien are memcmp'd, and thus the contents do matter. */ 381218822Sdim memset ((void *) execp, 0, sizeof (struct internal_exec)); 38233965Sjdp /* Now fill in fields in the execp, from the bytes in the raw data. */ 38389857Sobrien execp->a_info = H_GET_32 (abfd, bytes->e_info); 38433965Sjdp execp->a_text = GET_WORD (abfd, bytes->e_text); 38533965Sjdp execp->a_data = GET_WORD (abfd, bytes->e_data); 38633965Sjdp execp->a_bss = GET_WORD (abfd, bytes->e_bss); 38733965Sjdp execp->a_syms = GET_WORD (abfd, bytes->e_syms); 38833965Sjdp execp->a_entry = GET_WORD (abfd, bytes->e_entry); 38933965Sjdp execp->a_trsize = GET_WORD (abfd, bytes->e_trsize); 39033965Sjdp execp->a_drsize = GET_WORD (abfd, bytes->e_drsize); 39133965Sjdp} 392218822Sdim#define NAME_swap_exec_header_in NAME (aout, swap_exec_header_in) 39333965Sjdp#endif 39433965Sjdp 39533965Sjdp/* 39633965SjdpFUNCTION 39733965Sjdp aout_@var{size}_swap_exec_header_out 39833965Sjdp 39933965SjdpSYNOPSIS 40033965Sjdp void aout_@var{size}_swap_exec_header_out 40133965Sjdp (bfd *abfd, 40233965Sjdp struct internal_exec *execp, 40333965Sjdp struct external_exec *raw_bytes); 40433965Sjdp 40533965SjdpDESCRIPTION 40633965Sjdp Swap the information in an internal exec header structure 40733965Sjdp @var{execp} into the buffer @var{raw_bytes} ready for writing to disk. 40833965Sjdp*/ 40933965Sjdpvoid 410218822SdimNAME (aout, swap_exec_header_out) (bfd *abfd, 411218822Sdim struct internal_exec *execp, 412218822Sdim struct external_exec *bytes) 41333965Sjdp{ 41477298Sobrien /* Now fill in fields in the raw data, from the fields in the exec struct. */ 41589857Sobrien H_PUT_32 (abfd, execp->a_info , bytes->e_info); 41633965Sjdp PUT_WORD (abfd, execp->a_text , bytes->e_text); 41733965Sjdp PUT_WORD (abfd, execp->a_data , bytes->e_data); 41833965Sjdp PUT_WORD (abfd, execp->a_bss , bytes->e_bss); 41933965Sjdp PUT_WORD (abfd, execp->a_syms , bytes->e_syms); 42033965Sjdp PUT_WORD (abfd, execp->a_entry , bytes->e_entry); 42133965Sjdp PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize); 42233965Sjdp PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize); 42333965Sjdp} 42433965Sjdp 42533965Sjdp/* Make all the section for an a.out file. */ 42633965Sjdp 427130561Sobrienbfd_boolean 428218822SdimNAME (aout, make_sections) (bfd *abfd) 42933965Sjdp{ 430218822Sdim if (obj_textsec (abfd) == NULL && bfd_make_section (abfd, ".text") == NULL) 431130561Sobrien return FALSE; 432218822Sdim if (obj_datasec (abfd) == NULL && bfd_make_section (abfd, ".data") == NULL) 433130561Sobrien return FALSE; 434218822Sdim if (obj_bsssec (abfd) == NULL && bfd_make_section (abfd, ".bss") == NULL) 435130561Sobrien return FALSE; 436130561Sobrien return TRUE; 43733965Sjdp} 43833965Sjdp 43933965Sjdp/* 44033965SjdpFUNCTION 44133965Sjdp aout_@var{size}_some_aout_object_p 44233965Sjdp 44333965SjdpSYNOPSIS 44433965Sjdp const bfd_target *aout_@var{size}_some_aout_object_p 44533965Sjdp (bfd *abfd, 446218822Sdim struct internal_exec *execp, 447218822Sdim const bfd_target *(*callback_to_real_object_p) (bfd *)); 44833965Sjdp 44933965SjdpDESCRIPTION 45033965Sjdp Some a.out variant thinks that the file open in @var{abfd} 45133965Sjdp checking is an a.out file. Do some more checking, and set up 45233965Sjdp for access if it really is. Call back to the calling 45333965Sjdp environment's "finish up" function just before returning, to 45433965Sjdp handle any last-minute setup. 45533965Sjdp*/ 45633965Sjdp 45733965Sjdpconst bfd_target * 458218822SdimNAME (aout, some_aout_object_p) (bfd *abfd, 459218822Sdim struct internal_exec *execp, 460218822Sdim const bfd_target *(*callback_to_real_object_p) (bfd *)) 46133965Sjdp{ 46233965Sjdp struct aout_data_struct *rawptr, *oldrawptr; 46333965Sjdp const bfd_target *result; 464218822Sdim bfd_size_type amt = sizeof (* rawptr); 46533965Sjdp 466218822Sdim rawptr = bfd_zalloc (abfd, amt); 46733965Sjdp if (rawptr == NULL) 468218822Sdim return NULL; 46933965Sjdp 47033965Sjdp oldrawptr = abfd->tdata.aout_data; 47133965Sjdp abfd->tdata.aout_data = rawptr; 47233965Sjdp 47333965Sjdp /* Copy the contents of the old tdata struct. 47433965Sjdp In particular, we want the subformat, since for hpux it was set in 47533965Sjdp hp300hpux.c:swap_exec_header_in and will be used in 47633965Sjdp hp300hpux.c:callback. */ 47733965Sjdp if (oldrawptr != NULL) 47833965Sjdp *abfd->tdata.aout_data = *oldrawptr; 47933965Sjdp 48033965Sjdp abfd->tdata.aout_data->a.hdr = &rawptr->e; 481130561Sobrien /* Copy in the internal_exec struct. */ 482130561Sobrien *(abfd->tdata.aout_data->a.hdr) = *execp; 48333965Sjdp execp = abfd->tdata.aout_data->a.hdr; 48433965Sjdp 485130561Sobrien /* Set the file flags. */ 48633965Sjdp abfd->flags = BFD_NO_FLAGS; 48733965Sjdp if (execp->a_drsize || execp->a_trsize) 48833965Sjdp abfd->flags |= HAS_RELOC; 489130561Sobrien /* Setting of EXEC_P has been deferred to the bottom of this function. */ 49033965Sjdp if (execp->a_syms) 49133965Sjdp abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; 49289857Sobrien if (N_DYNAMIC (*execp)) 49333965Sjdp abfd->flags |= DYNAMIC; 49433965Sjdp 49533965Sjdp if (N_MAGIC (*execp) == ZMAGIC) 49633965Sjdp { 49733965Sjdp abfd->flags |= D_PAGED | WP_TEXT; 49833965Sjdp adata (abfd).magic = z_magic; 49933965Sjdp } 50033965Sjdp else if (N_MAGIC (*execp) == QMAGIC) 50133965Sjdp { 50233965Sjdp abfd->flags |= D_PAGED | WP_TEXT; 50333965Sjdp adata (abfd).magic = z_magic; 50433965Sjdp adata (abfd).subformat = q_magic_format; 50533965Sjdp } 50633965Sjdp else if (N_MAGIC (*execp) == NMAGIC) 50733965Sjdp { 50833965Sjdp abfd->flags |= WP_TEXT; 50933965Sjdp adata (abfd).magic = n_magic; 51033965Sjdp } 51133965Sjdp else if (N_MAGIC (*execp) == OMAGIC 51233965Sjdp || N_MAGIC (*execp) == BMAGIC) 51333965Sjdp adata (abfd).magic = o_magic; 51433965Sjdp else 515218822Sdim /* Should have been checked with N_BADMAG before this routine 516218822Sdim was called. */ 517218822Sdim abort (); 51833965Sjdp 51933965Sjdp bfd_get_start_address (abfd) = execp->a_entry; 52033965Sjdp 521218822Sdim obj_aout_symbols (abfd) = NULL; 52233965Sjdp bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist); 52333965Sjdp 52433965Sjdp /* The default relocation entry size is that of traditional V7 Unix. */ 52533965Sjdp obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 52633965Sjdp 52777298Sobrien /* The default symbol entry size is that of traditional Unix. */ 52833965Sjdp obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE; 52933965Sjdp 53033965Sjdp#ifdef USE_MMAP 53133965Sjdp bfd_init_window (&obj_aout_sym_window (abfd)); 53233965Sjdp bfd_init_window (&obj_aout_string_window (abfd)); 53333965Sjdp#endif 53433965Sjdp obj_aout_external_syms (abfd) = NULL; 53533965Sjdp obj_aout_external_strings (abfd) = NULL; 53633965Sjdp obj_aout_sym_hashes (abfd) = NULL; 53733965Sjdp 538218822Sdim if (! NAME (aout, make_sections) (abfd)) 539104834Sobrien goto error_ret; 54033965Sjdp 541218822Sdim obj_datasec (abfd)->size = execp->a_data; 542218822Sdim obj_bsssec (abfd)->size = execp->a_bss; 54333965Sjdp 54433965Sjdp obj_textsec (abfd)->flags = 54533965Sjdp (execp->a_trsize != 0 54633965Sjdp ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) 54733965Sjdp : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); 54833965Sjdp obj_datasec (abfd)->flags = 54933965Sjdp (execp->a_drsize != 0 55033965Sjdp ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) 55133965Sjdp : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); 55233965Sjdp obj_bsssec (abfd)->flags = SEC_ALLOC; 55333965Sjdp 55433965Sjdp#ifdef THIS_IS_ONLY_DOCUMENTATION 55533965Sjdp /* The common code can't fill in these things because they depend 55633965Sjdp on either the start address of the text segment, the rounding 55733965Sjdp up of virtual addresses between segments, or the starting file 55833965Sjdp position of the text segment -- all of which varies among different 55933965Sjdp versions of a.out. */ 56033965Sjdp 56133965Sjdp /* Call back to the format-dependent code to fill in the rest of the 56233965Sjdp fields and do any further cleanup. Things that should be filled 56333965Sjdp in by the callback: */ 56433965Sjdp 56533965Sjdp struct exec *execp = exec_hdr (abfd); 56633965Sjdp 56789857Sobrien obj_textsec (abfd)->size = N_TXTSIZE (*execp); 568130561Sobrien /* Data and bss are already filled in since they're so standard. */ 56933965Sjdp 570130561Sobrien /* The virtual memory addresses of the sections. */ 57189857Sobrien obj_textsec (abfd)->vma = N_TXTADDR (*execp); 57289857Sobrien obj_datasec (abfd)->vma = N_DATADDR (*execp); 57389857Sobrien obj_bsssec (abfd)->vma = N_BSSADDR (*execp); 57433965Sjdp 575130561Sobrien /* The file offsets of the sections. */ 57689857Sobrien obj_textsec (abfd)->filepos = N_TXTOFF (*execp); 57789857Sobrien obj_datasec (abfd)->filepos = N_DATOFF (*execp); 57833965Sjdp 579130561Sobrien /* The file offsets of the relocation info. */ 58089857Sobrien obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp); 58189857Sobrien obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp); 58233965Sjdp 58333965Sjdp /* The file offsets of the string table and symbol table. */ 58433965Sjdp obj_str_filepos (abfd) = N_STROFF (*execp); 58533965Sjdp obj_sym_filepos (abfd) = N_SYMOFF (*execp); 58633965Sjdp 58733965Sjdp /* Determine the architecture and machine type of the object file. */ 58889857Sobrien switch (N_MACHTYPE (*exec_hdr (abfd))) 58989857Sobrien { 59089857Sobrien default: 59189857Sobrien abfd->obj_arch = bfd_arch_obscure; 59289857Sobrien break; 59389857Sobrien } 59433965Sjdp 59589857Sobrien adata (abfd)->page_size = TARGET_PAGE_SIZE; 59689857Sobrien adata (abfd)->segment_size = SEGMENT_SIZE; 59789857Sobrien adata (abfd)->exec_bytes_size = EXEC_BYTES_SIZE; 59833965Sjdp 59933965Sjdp return abfd->xvec; 60033965Sjdp 60133965Sjdp /* The architecture is encoded in various ways in various a.out variants, 60233965Sjdp or is not encoded at all in some of them. The relocation size depends 60333965Sjdp on the architecture and the a.out variant. Finally, the return value 60433965Sjdp is the bfd_target vector in use. If an error occurs, return zero and 60533965Sjdp set bfd_error to the appropriate error code. 60633965Sjdp 60733965Sjdp Formats such as b.out, which have additional fields in the a.out 60833965Sjdp header, should cope with them in this callback as well. */ 60933965Sjdp#endif /* DOCUMENTATION */ 61033965Sjdp 61177298Sobrien result = (*callback_to_real_object_p) (abfd); 61233965Sjdp 61333965Sjdp /* Now that the segment addresses have been worked out, take a better 61433965Sjdp guess at whether the file is executable. If the entry point 61533965Sjdp is within the text segment, assume it is. (This makes files 61633965Sjdp executable even if their entry point address is 0, as long as 61733965Sjdp their text starts at zero.). 61833965Sjdp 61933965Sjdp This test had to be changed to deal with systems where the text segment 62033965Sjdp runs at a different location than the default. The problem is that the 62133965Sjdp entry address can appear to be outside the text segment, thus causing an 62233965Sjdp erroneous conclusion that the file isn't executable. 62333965Sjdp 62433965Sjdp To fix this, we now accept any non-zero entry point as an indication of 62533965Sjdp executability. This will work most of the time, since only the linker 62677298Sobrien sets the entry point, and that is likely to be non-zero for most systems. */ 62733965Sjdp 62833965Sjdp if (execp->a_entry != 0 62989857Sobrien || (execp->a_entry >= obj_textsec (abfd)->vma 63089857Sobrien && execp->a_entry < (obj_textsec (abfd)->vma 631218822Sdim + obj_textsec (abfd)->size))) 63233965Sjdp abfd->flags |= EXEC_P; 63333965Sjdp#ifdef STAT_FOR_EXEC 63433965Sjdp else 63533965Sjdp { 63633965Sjdp struct stat stat_buf; 63733965Sjdp 63833965Sjdp /* The original heuristic doesn't work in some important cases. 63933965Sjdp The a.out file has no information about the text start 64033965Sjdp address. For files (like kernels) linked to non-standard 64133965Sjdp addresses (ld -Ttext nnn) the entry point may not be between 64233965Sjdp the default text start (obj_textsec(abfd)->vma) and 64333965Sjdp (obj_textsec(abfd)->vma) + text size. This is not just a mach 64433965Sjdp issue. Many kernels are loaded at non standard addresses. */ 64533965Sjdp if (abfd->iostream != NULL 64633965Sjdp && (abfd->flags & BFD_IN_MEMORY) == 0 64789857Sobrien && (fstat (fileno ((FILE *) (abfd->iostream)), &stat_buf) == 0) 64833965Sjdp && ((stat_buf.st_mode & 0111) != 0)) 64933965Sjdp abfd->flags |= EXEC_P; 65033965Sjdp } 65133965Sjdp#endif /* STAT_FOR_EXEC */ 65233965Sjdp 65333965Sjdp if (result) 654218822Sdim return result; 655104834Sobrien 656104834Sobrien error_ret: 657104834Sobrien bfd_release (abfd, rawptr); 658104834Sobrien abfd->tdata.aout_data = oldrawptr; 659104834Sobrien return NULL; 66033965Sjdp} 66133965Sjdp 66233965Sjdp/* 66333965SjdpFUNCTION 66433965Sjdp aout_@var{size}_mkobject 66533965Sjdp 66633965SjdpSYNOPSIS 667130561Sobrien bfd_boolean aout_@var{size}_mkobject, (bfd *abfd); 66833965Sjdp 66933965SjdpDESCRIPTION 67033965Sjdp Initialize BFD @var{abfd} for use with a.out files. 67133965Sjdp*/ 67233965Sjdp 673130561Sobrienbfd_boolean 674218822SdimNAME (aout, mkobject) (bfd *abfd) 67533965Sjdp{ 67689857Sobrien struct aout_data_struct *rawptr; 677218822Sdim bfd_size_type amt = sizeof (* rawptr); 67833965Sjdp 67933965Sjdp bfd_set_error (bfd_error_system_call); 68033965Sjdp 681218822Sdim rawptr = bfd_zalloc (abfd, amt); 68233965Sjdp if (rawptr == NULL) 683130561Sobrien return FALSE; 68433965Sjdp 68533965Sjdp abfd->tdata.aout_data = rawptr; 68633965Sjdp exec_hdr (abfd) = &(rawptr->e); 68733965Sjdp 688218822Sdim obj_textsec (abfd) = NULL; 689218822Sdim obj_datasec (abfd) = NULL; 690218822Sdim obj_bsssec (abfd) = NULL; 69133965Sjdp 692130561Sobrien return TRUE; 69333965Sjdp} 69433965Sjdp 69533965Sjdp/* 69633965SjdpFUNCTION 69733965Sjdp aout_@var{size}_machine_type 69833965Sjdp 69933965SjdpSYNOPSIS 70033965Sjdp enum machine_type aout_@var{size}_machine_type 70133965Sjdp (enum bfd_architecture arch, 702218822Sdim unsigned long machine, 703218822Sdim bfd_boolean *unknown); 70433965Sjdp 70533965SjdpDESCRIPTION 70633965Sjdp Keep track of machine architecture and machine type for 70733965Sjdp a.out's. Return the <<machine_type>> for a particular 70833965Sjdp architecture and machine, or <<M_UNKNOWN>> if that exact architecture 70933965Sjdp and machine can't be represented in a.out format. 71033965Sjdp 71133965Sjdp If the architecture is understood, machine type 0 (default) 71233965Sjdp is always understood. 71333965Sjdp*/ 71433965Sjdp 71533965Sjdpenum machine_type 716218822SdimNAME (aout, machine_type) (enum bfd_architecture arch, 717218822Sdim unsigned long machine, 718218822Sdim bfd_boolean *unknown) 71933965Sjdp{ 72033965Sjdp enum machine_type arch_flags; 72133965Sjdp 72233965Sjdp arch_flags = M_UNKNOWN; 723130561Sobrien *unknown = TRUE; 72433965Sjdp 72589857Sobrien switch (arch) 72689857Sobrien { 72789857Sobrien case bfd_arch_sparc: 72889857Sobrien if (machine == 0 72989857Sobrien || machine == bfd_mach_sparc 73089857Sobrien || machine == bfd_mach_sparc_sparclite 73189857Sobrien || machine == bfd_mach_sparc_sparclite_le 732218822Sdim || machine == bfd_mach_sparc_v8plus 733218822Sdim || machine == bfd_mach_sparc_v8plusa 734218822Sdim || machine == bfd_mach_sparc_v8plusb 735218822Sdim || machine == bfd_mach_sparc_v9 736218822Sdim || machine == bfd_mach_sparc_v9a 737218822Sdim || machine == bfd_mach_sparc_v9b) 73889857Sobrien arch_flags = M_SPARC; 73989857Sobrien else if (machine == bfd_mach_sparc_sparclet) 74089857Sobrien arch_flags = M_SPARCLET; 74189857Sobrien break; 74233965Sjdp 74389857Sobrien case bfd_arch_m68k: 74489857Sobrien switch (machine) 74589857Sobrien { 74689857Sobrien case 0: arch_flags = M_68010; break; 747130561Sobrien case bfd_mach_m68000: arch_flags = M_UNKNOWN; *unknown = FALSE; break; 74889857Sobrien case bfd_mach_m68010: arch_flags = M_68010; break; 74989857Sobrien case bfd_mach_m68020: arch_flags = M_68020; break; 75089857Sobrien default: arch_flags = M_UNKNOWN; break; 75189857Sobrien } 75289857Sobrien break; 75333965Sjdp 75489857Sobrien case bfd_arch_i386: 755130561Sobrien if (machine == 0 756130561Sobrien || machine == bfd_mach_i386_i386 757130561Sobrien || machine == bfd_mach_i386_i386_intel_syntax) 75889857Sobrien arch_flags = M_386; 75989857Sobrien break; 76033965Sjdp 76189857Sobrien case bfd_arch_arm: 76289857Sobrien if (machine == 0) 76389857Sobrien arch_flags = M_ARM; 76489857Sobrien break; 76577298Sobrien 76689857Sobrien case bfd_arch_mips: 76789857Sobrien switch (machine) 76889857Sobrien { 76989857Sobrien case 0: 77089857Sobrien case bfd_mach_mips3000: 77189857Sobrien case bfd_mach_mips3900: 77289857Sobrien arch_flags = M_MIPS1; 77389857Sobrien break; 77489857Sobrien case bfd_mach_mips6000: 77589857Sobrien arch_flags = M_MIPS2; 77689857Sobrien break; 77789857Sobrien case bfd_mach_mips4000: 77889857Sobrien case bfd_mach_mips4010: 77989857Sobrien case bfd_mach_mips4100: 78089857Sobrien case bfd_mach_mips4300: 78189857Sobrien case bfd_mach_mips4400: 78289857Sobrien case bfd_mach_mips4600: 78389857Sobrien case bfd_mach_mips4650: 78489857Sobrien case bfd_mach_mips8000: 785218822Sdim case bfd_mach_mips9000: 78689857Sobrien case bfd_mach_mips10000: 78789857Sobrien case bfd_mach_mips12000: 78889857Sobrien case bfd_mach_mips16: 78989857Sobrien case bfd_mach_mipsisa32: 790130561Sobrien case bfd_mach_mipsisa32r2: 79189857Sobrien case bfd_mach_mips5: 79289857Sobrien case bfd_mach_mipsisa64: 793130561Sobrien case bfd_mach_mipsisa64r2: 79489857Sobrien case bfd_mach_mips_sb1: 79589857Sobrien /* FIXME: These should be MIPS3, MIPS4, MIPS16, MIPS32, etc. */ 79689857Sobrien arch_flags = M_MIPS2; 79789857Sobrien break; 79889857Sobrien default: 79989857Sobrien arch_flags = M_UNKNOWN; 80089857Sobrien break; 80189857Sobrien } 80260484Sobrien break; 80389857Sobrien 80489857Sobrien case bfd_arch_ns32k: 80589857Sobrien switch (machine) 80689857Sobrien { 80789857Sobrien case 0: arch_flags = M_NS32532; break; 80889857Sobrien case 32032: arch_flags = M_NS32032; break; 80989857Sobrien case 32532: arch_flags = M_NS32532; break; 81089857Sobrien default: arch_flags = M_UNKNOWN; break; 81189857Sobrien } 81260484Sobrien break; 81389857Sobrien 81489857Sobrien case bfd_arch_vax: 815130561Sobrien *unknown = FALSE; 81660484Sobrien break; 81789857Sobrien 81889857Sobrien case bfd_arch_cris: 81989857Sobrien if (machine == 0 || machine == 255) 82089857Sobrien arch_flags = M_CRIS; 82189857Sobrien break; 82289857Sobrien 823218822Sdim case bfd_arch_m88k: 824218822Sdim *unknown = FALSE; 825218822Sdim break; 826218822Sdim 82760484Sobrien default: 82860484Sobrien arch_flags = M_UNKNOWN; 82933965Sjdp } 83033965Sjdp 83133965Sjdp if (arch_flags != M_UNKNOWN) 832130561Sobrien *unknown = FALSE; 83333965Sjdp 83433965Sjdp return arch_flags; 83533965Sjdp} 83633965Sjdp 83733965Sjdp/* 83833965SjdpFUNCTION 83933965Sjdp aout_@var{size}_set_arch_mach 84033965Sjdp 84133965SjdpSYNOPSIS 842130561Sobrien bfd_boolean aout_@var{size}_set_arch_mach, 84333965Sjdp (bfd *, 84433965Sjdp enum bfd_architecture arch, 845218822Sdim unsigned long machine); 84633965Sjdp 84733965SjdpDESCRIPTION 84833965Sjdp Set the architecture and the machine of the BFD @var{abfd} to the 84933965Sjdp values @var{arch} and @var{machine}. Verify that @var{abfd}'s format 85033965Sjdp can support the architecture required. 85133965Sjdp*/ 85233965Sjdp 853130561Sobrienbfd_boolean 854218822SdimNAME (aout, set_arch_mach) (bfd *abfd, 855218822Sdim enum bfd_architecture arch, 856218822Sdim unsigned long machine) 85733965Sjdp{ 85833965Sjdp if (! bfd_default_set_arch_mach (abfd, arch, machine)) 859130561Sobrien return FALSE; 86033965Sjdp 86133965Sjdp if (arch != bfd_arch_unknown) 86233965Sjdp { 863130561Sobrien bfd_boolean unknown; 86433965Sjdp 865218822Sdim NAME (aout, machine_type) (arch, machine, &unknown); 86633965Sjdp if (unknown) 867130561Sobrien return FALSE; 86833965Sjdp } 86933965Sjdp 870130561Sobrien /* Determine the size of a relocation entry. */ 87189857Sobrien switch (arch) 87289857Sobrien { 87389857Sobrien case bfd_arch_sparc: 87489857Sobrien case bfd_arch_mips: 87589857Sobrien obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE; 87689857Sobrien break; 87789857Sobrien default: 87889857Sobrien obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 87989857Sobrien break; 88089857Sobrien } 88133965Sjdp 88289857Sobrien return (*aout_backend_info (abfd)->set_sizes) (abfd); 88333965Sjdp} 88433965Sjdp 88533965Sjdpstatic void 886218822Sdimadjust_o_magic (bfd *abfd, struct internal_exec *execp) 88733965Sjdp{ 88833965Sjdp file_ptr pos = adata (abfd).exec_bytes_size; 88933965Sjdp bfd_vma vma = 0; 89033965Sjdp int pad = 0; 89133965Sjdp 89233965Sjdp /* Text. */ 89389857Sobrien obj_textsec (abfd)->filepos = pos; 89489857Sobrien if (!obj_textsec (abfd)->user_set_vma) 89589857Sobrien obj_textsec (abfd)->vma = vma; 89633965Sjdp else 89789857Sobrien vma = obj_textsec (abfd)->vma; 89833965Sjdp 899218822Sdim pos += obj_textsec (abfd)->size; 900218822Sdim vma += obj_textsec (abfd)->size; 90133965Sjdp 90233965Sjdp /* Data. */ 90389857Sobrien if (!obj_datasec (abfd)->user_set_vma) 90433965Sjdp { 905218822Sdim obj_textsec (abfd)->size += pad; 90633965Sjdp pos += pad; 90733965Sjdp vma += pad; 90889857Sobrien obj_datasec (abfd)->vma = vma; 90933965Sjdp } 91033965Sjdp else 91189857Sobrien vma = obj_datasec (abfd)->vma; 91289857Sobrien obj_datasec (abfd)->filepos = pos; 913218822Sdim pos += obj_datasec (abfd)->size; 914218822Sdim vma += obj_datasec (abfd)->size; 91533965Sjdp 91633965Sjdp /* BSS. */ 91789857Sobrien if (!obj_bsssec (abfd)->user_set_vma) 91833965Sjdp { 919218822Sdim obj_datasec (abfd)->size += pad; 92033965Sjdp pos += pad; 92133965Sjdp vma += pad; 92289857Sobrien obj_bsssec (abfd)->vma = vma; 92333965Sjdp } 92433965Sjdp else 92533965Sjdp { 92689857Sobrien /* The VMA of the .bss section is set by the VMA of the 92733965Sjdp .data section plus the size of the .data section. We may 92833965Sjdp need to add padding bytes to make this true. */ 92933965Sjdp pad = obj_bsssec (abfd)->vma - vma; 93033965Sjdp if (pad > 0) 93133965Sjdp { 932218822Sdim obj_datasec (abfd)->size += pad; 93333965Sjdp pos += pad; 93433965Sjdp } 93533965Sjdp } 93689857Sobrien obj_bsssec (abfd)->filepos = pos; 93733965Sjdp 93833965Sjdp /* Fix up the exec header. */ 939218822Sdim execp->a_text = obj_textsec (abfd)->size; 940218822Sdim execp->a_data = obj_datasec (abfd)->size; 941218822Sdim execp->a_bss = obj_bsssec (abfd)->size; 94233965Sjdp N_SET_MAGIC (*execp, OMAGIC); 94333965Sjdp} 94433965Sjdp 94533965Sjdpstatic void 946218822Sdimadjust_z_magic (bfd *abfd, struct internal_exec *execp) 94733965Sjdp{ 94833965Sjdp bfd_size_type data_pad, text_pad; 94933965Sjdp file_ptr text_end; 95089857Sobrien const struct aout_backend_data *abdp; 951218822Sdim /* TRUE if text includes exec header. */ 952218822Sdim bfd_boolean ztih; 95377298Sobrien 95433965Sjdp abdp = aout_backend_info (abfd); 95533965Sjdp 95633965Sjdp /* Text. */ 95733965Sjdp ztih = (abdp != NULL 95833965Sjdp && (abdp->text_includes_header 95933965Sjdp || obj_aout_subformat (abfd) == q_magic_format)); 96089857Sobrien obj_textsec (abfd)->filepos = (ztih 96189857Sobrien ? adata (abfd).exec_bytes_size 96289857Sobrien : adata (abfd).zmagic_disk_block_size); 96389857Sobrien if (! obj_textsec (abfd)->user_set_vma) 96433965Sjdp { 96533965Sjdp /* ?? Do we really need to check for relocs here? */ 96689857Sobrien obj_textsec (abfd)->vma = ((abfd->flags & HAS_RELOC) 96789857Sobrien ? 0 96889857Sobrien : (ztih 96989857Sobrien ? (abdp->default_text_vma 97089857Sobrien + adata (abfd).exec_bytes_size) 97189857Sobrien : abdp->default_text_vma)); 97233965Sjdp text_pad = 0; 97333965Sjdp } 97433965Sjdp else 97533965Sjdp { 97633965Sjdp /* The .text section is being loaded at an unusual address. We 97733965Sjdp may need to pad it such that the .data section starts at a page 97833965Sjdp boundary. */ 97933965Sjdp if (ztih) 98033965Sjdp text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma) 98133965Sjdp & (adata (abfd).page_size - 1)); 98233965Sjdp else 98333965Sjdp text_pad = ((- obj_textsec (abfd)->vma) 98433965Sjdp & (adata (abfd).page_size - 1)); 98533965Sjdp } 98633965Sjdp 98733965Sjdp /* Find start of data. */ 98833965Sjdp if (ztih) 98933965Sjdp { 990218822Sdim text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->size; 99133965Sjdp text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; 99233965Sjdp } 99333965Sjdp else 99433965Sjdp { 99533965Sjdp /* Note that if page_size == zmagic_disk_block_size, then 99633965Sjdp filepos == page_size, and this case is the same as the ztih 99733965Sjdp case. */ 998218822Sdim text_end = obj_textsec (abfd)->size; 99933965Sjdp text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; 100033965Sjdp text_end += obj_textsec (abfd)->filepos; 100133965Sjdp } 1002218822Sdim obj_textsec (abfd)->size += text_pad; 100333965Sjdp text_end += text_pad; 100433965Sjdp 100533965Sjdp /* Data. */ 100689857Sobrien if (!obj_datasec (abfd)->user_set_vma) 100733965Sjdp { 100833965Sjdp bfd_vma vma; 1009218822Sdim vma = obj_textsec (abfd)->vma + obj_textsec (abfd)->size; 101089857Sobrien obj_datasec (abfd)->vma = BFD_ALIGN (vma, adata (abfd).segment_size); 101133965Sjdp } 101233965Sjdp if (abdp && abdp->zmagic_mapped_contiguous) 101333965Sjdp { 101489857Sobrien asection * text = obj_textsec (abfd); 101589857Sobrien asection * data = obj_datasec (abfd); 101689857Sobrien 1017218822Sdim text_pad = data->vma - (text->vma + text->size); 101889857Sobrien /* Only pad the text section if the data 101989857Sobrien section is going to be placed after it. */ 102089857Sobrien if (text_pad > 0) 1021218822Sdim text->size += text_pad; 102233965Sjdp } 102389857Sobrien obj_datasec (abfd)->filepos = (obj_textsec (abfd)->filepos 1024218822Sdim + obj_textsec (abfd)->size); 102577298Sobrien 102633965Sjdp /* Fix up exec header while we're at it. */ 1027218822Sdim execp->a_text = obj_textsec (abfd)->size; 102833965Sjdp if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) 102989857Sobrien execp->a_text += adata (abfd).exec_bytes_size; 103033965Sjdp if (obj_aout_subformat (abfd) == q_magic_format) 103133965Sjdp N_SET_MAGIC (*execp, QMAGIC); 103233965Sjdp else 103333965Sjdp N_SET_MAGIC (*execp, ZMAGIC); 103433965Sjdp 103533965Sjdp /* Spec says data section should be rounded up to page boundary. */ 1036218822Sdim obj_datasec (abfd)->size 1037218822Sdim = align_power (obj_datasec (abfd)->size, 103889857Sobrien obj_bsssec (abfd)->alignment_power); 1039218822Sdim execp->a_data = BFD_ALIGN (obj_datasec (abfd)->size, 104089857Sobrien adata (abfd).page_size); 1041218822Sdim data_pad = execp->a_data - obj_datasec (abfd)->size; 104233965Sjdp 104333965Sjdp /* BSS. */ 104489857Sobrien if (!obj_bsssec (abfd)->user_set_vma) 104589857Sobrien obj_bsssec (abfd)->vma = (obj_datasec (abfd)->vma 1046218822Sdim + obj_datasec (abfd)->size); 104733965Sjdp /* If the BSS immediately follows the data section and extra space 104833965Sjdp in the page is left after the data section, fudge data 104933965Sjdp in the header so that the bss section looks smaller by that 105033965Sjdp amount. We'll start the bss section there, and lie to the OS. 105133965Sjdp (Note that a linker script, as well as the above assignment, 105233965Sjdp could have explicitly set the BSS vma to immediately follow 105333965Sjdp the data section.) */ 105489857Sobrien if (align_power (obj_bsssec (abfd)->vma, obj_bsssec (abfd)->alignment_power) 1055218822Sdim == obj_datasec (abfd)->vma + obj_datasec (abfd)->size) 1056218822Sdim execp->a_bss = (data_pad > obj_bsssec (abfd)->size 1057218822Sdim ? 0 : obj_bsssec (abfd)->size - data_pad); 105833965Sjdp else 1059218822Sdim execp->a_bss = obj_bsssec (abfd)->size; 106033965Sjdp} 106133965Sjdp 106233965Sjdpstatic void 1063218822Sdimadjust_n_magic (bfd *abfd, struct internal_exec *execp) 106433965Sjdp{ 106589857Sobrien file_ptr pos = adata (abfd).exec_bytes_size; 106633965Sjdp bfd_vma vma = 0; 106733965Sjdp int pad; 106877298Sobrien 106933965Sjdp /* Text. */ 107089857Sobrien obj_textsec (abfd)->filepos = pos; 107189857Sobrien if (!obj_textsec (abfd)->user_set_vma) 107289857Sobrien obj_textsec (abfd)->vma = vma; 107333965Sjdp else 107489857Sobrien vma = obj_textsec (abfd)->vma; 1075218822Sdim pos += obj_textsec (abfd)->size; 1076218822Sdim vma += obj_textsec (abfd)->size; 107733965Sjdp 107833965Sjdp /* Data. */ 107989857Sobrien obj_datasec (abfd)->filepos = pos; 108089857Sobrien if (!obj_datasec (abfd)->user_set_vma) 108189857Sobrien obj_datasec (abfd)->vma = BFD_ALIGN (vma, adata (abfd).segment_size); 108289857Sobrien vma = obj_datasec (abfd)->vma; 108377298Sobrien 108433965Sjdp /* Since BSS follows data immediately, see if it needs alignment. */ 1085218822Sdim vma += obj_datasec (abfd)->size; 108689857Sobrien pad = align_power (vma, obj_bsssec (abfd)->alignment_power) - vma; 1087218822Sdim obj_datasec (abfd)->size += pad; 1088218822Sdim pos += obj_datasec (abfd)->size; 108933965Sjdp 109033965Sjdp /* BSS. */ 109189857Sobrien if (!obj_bsssec (abfd)->user_set_vma) 109289857Sobrien obj_bsssec (abfd)->vma = vma; 109333965Sjdp else 109489857Sobrien vma = obj_bsssec (abfd)->vma; 109533965Sjdp 109633965Sjdp /* Fix up exec header. */ 1097218822Sdim execp->a_text = obj_textsec (abfd)->size; 1098218822Sdim execp->a_data = obj_datasec (abfd)->size; 1099218822Sdim execp->a_bss = obj_bsssec (abfd)->size; 110033965Sjdp N_SET_MAGIC (*execp, NMAGIC); 110133965Sjdp} 110233965Sjdp 1103130561Sobrienbfd_boolean 1104218822SdimNAME (aout, adjust_sizes_and_vmas) (bfd *abfd, 1105218822Sdim bfd_size_type *text_size, 1106218822Sdim file_ptr *text_end ATTRIBUTE_UNUSED) 110733965Sjdp{ 110833965Sjdp struct internal_exec *execp = exec_hdr (abfd); 110933965Sjdp 1110218822Sdim if (! NAME (aout, make_sections) (abfd)) 1111130561Sobrien return FALSE; 111233965Sjdp 111389857Sobrien if (adata (abfd).magic != undecided_magic) 1114130561Sobrien return TRUE; 111533965Sjdp 1116218822Sdim obj_textsec (abfd)->size = 1117218822Sdim align_power (obj_textsec (abfd)->size, 111889857Sobrien obj_textsec (abfd)->alignment_power); 111933965Sjdp 1120218822Sdim *text_size = obj_textsec (abfd)->size; 112133965Sjdp /* Rule (heuristic) for when to pad to a new page. Note that there 112233965Sjdp are (at least) two ways demand-paged (ZMAGIC) files have been 112333965Sjdp handled. Most Berkeley-based systems start the text segment at 112433965Sjdp (TARGET_PAGE_SIZE). However, newer versions of SUNOS start the text 112533965Sjdp segment right after the exec header; the latter is counted in the 112633965Sjdp text segment size, and is paged in by the kernel with the rest of 112777298Sobrien the text. */ 112833965Sjdp 112933965Sjdp /* This perhaps isn't the right way to do this, but made it simpler for me 113033965Sjdp to understand enough to implement it. Better would probably be to go 113133965Sjdp right from BFD flags to alignment/positioning characteristics. But the 113233965Sjdp old code was sloppy enough about handling the flags, and had enough 113333965Sjdp other magic, that it was a little hard for me to understand. I think 113433965Sjdp I understand it better now, but I haven't time to do the cleanup this 113533965Sjdp minute. */ 113633965Sjdp 113733965Sjdp if (abfd->flags & D_PAGED) 113833965Sjdp /* Whether or not WP_TEXT is set -- let D_PAGED override. */ 113989857Sobrien adata (abfd).magic = z_magic; 114033965Sjdp else if (abfd->flags & WP_TEXT) 114189857Sobrien adata (abfd).magic = n_magic; 114233965Sjdp else 114389857Sobrien adata (abfd).magic = o_magic; 114433965Sjdp 114533965Sjdp#ifdef BFD_AOUT_DEBUG /* requires gcc2 */ 114633965Sjdp#if __GNUC__ >= 2 114733965Sjdp fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n", 114833965Sjdp ({ char *str; 114989857Sobrien switch (adata (abfd).magic) 115089857Sobrien { 115189857Sobrien case n_magic: str = "NMAGIC"; break; 115289857Sobrien case o_magic: str = "OMAGIC"; break; 115389857Sobrien case z_magic: str = "ZMAGIC"; break; 115489857Sobrien default: abort (); 115589857Sobrien } 115633965Sjdp str; 115733965Sjdp }), 1158218822Sdim obj_textsec (abfd)->vma, obj_textsec (abfd)->size, 115989857Sobrien obj_textsec (abfd)->alignment_power, 1160218822Sdim obj_datasec (abfd)->vma, obj_datasec (abfd)->size, 116189857Sobrien obj_datasec (abfd)->alignment_power, 1162218822Sdim obj_bsssec (abfd)->vma, obj_bsssec (abfd)->size, 116389857Sobrien obj_bsssec (abfd)->alignment_power); 116433965Sjdp#endif 116533965Sjdp#endif 116633965Sjdp 116789857Sobrien switch (adata (abfd).magic) 116833965Sjdp { 116933965Sjdp case o_magic: 117033965Sjdp adjust_o_magic (abfd, execp); 117133965Sjdp break; 117233965Sjdp case z_magic: 117333965Sjdp adjust_z_magic (abfd, execp); 117433965Sjdp break; 117533965Sjdp case n_magic: 117633965Sjdp adjust_n_magic (abfd, execp); 117733965Sjdp break; 117833965Sjdp default: 117933965Sjdp abort (); 118033965Sjdp } 118133965Sjdp 118233965Sjdp#ifdef BFD_AOUT_DEBUG 118333965Sjdp fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n", 1184218822Sdim obj_textsec (abfd)->vma, obj_textsec (abfd)->size, 118589857Sobrien obj_textsec (abfd)->filepos, 1186218822Sdim obj_datasec (abfd)->vma, obj_datasec (abfd)->size, 118789857Sobrien obj_datasec (abfd)->filepos, 1188218822Sdim obj_bsssec (abfd)->vma, obj_bsssec (abfd)->size); 118933965Sjdp#endif 119033965Sjdp 1191130561Sobrien return TRUE; 119233965Sjdp} 119333965Sjdp 119433965Sjdp/* 119533965SjdpFUNCTION 119633965Sjdp aout_@var{size}_new_section_hook 119733965Sjdp 119833965SjdpSYNOPSIS 1199130561Sobrien bfd_boolean aout_@var{size}_new_section_hook, 120033965Sjdp (bfd *abfd, 1201218822Sdim asection *newsect); 120233965Sjdp 120333965SjdpDESCRIPTION 120433965Sjdp Called by the BFD in response to a @code{bfd_make_section} 120533965Sjdp request. 120633965Sjdp*/ 1207130561Sobrienbfd_boolean 1208218822SdimNAME (aout, new_section_hook) (bfd *abfd, asection *newsect) 120933965Sjdp{ 1210130561Sobrien /* Align to double at least. */ 121189857Sobrien newsect->alignment_power = bfd_get_arch_info (abfd)->section_align_power; 121233965Sjdp 121333965Sjdp if (bfd_get_format (abfd) == bfd_object) 1214130561Sobrien { 1215130561Sobrien if (obj_textsec (abfd) == NULL && !strcmp (newsect->name, ".text")) 1216130561Sobrien { 1217130561Sobrien obj_textsec (abfd)= newsect; 1218130561Sobrien newsect->target_index = N_TEXT; 1219130561Sobrien } 1220218822Sdim else if (obj_datasec (abfd) == NULL && !strcmp (newsect->name, ".data")) 1221130561Sobrien { 1222130561Sobrien obj_datasec (abfd) = newsect; 1223130561Sobrien newsect->target_index = N_DATA; 1224130561Sobrien } 1225218822Sdim else if (obj_bsssec (abfd) == NULL && !strcmp (newsect->name, ".bss")) 1226130561Sobrien { 1227130561Sobrien obj_bsssec (abfd) = newsect; 1228130561Sobrien newsect->target_index = N_BSS; 1229130561Sobrien } 1230130561Sobrien } 123133965Sjdp 1232130561Sobrien /* We allow more than three sections internally. */ 1233218822Sdim return _bfd_generic_new_section_hook (abfd, newsect); 123433965Sjdp} 123533965Sjdp 1236130561Sobrienbfd_boolean 1237218822SdimNAME (aout, set_section_contents) (bfd *abfd, 1238218822Sdim sec_ptr section, 1239218822Sdim const void * location, 1240218822Sdim file_ptr offset, 1241218822Sdim bfd_size_type count) 124233965Sjdp{ 124333965Sjdp file_ptr text_end; 124433965Sjdp bfd_size_type text_size; 124533965Sjdp 124633965Sjdp if (! abfd->output_has_begun) 124733965Sjdp { 1248218822Sdim if (! NAME (aout, adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) 1249130561Sobrien return FALSE; 125033965Sjdp } 125133965Sjdp 125233965Sjdp if (section == obj_bsssec (abfd)) 125333965Sjdp { 125433965Sjdp bfd_set_error (bfd_error_no_contents); 1255130561Sobrien return FALSE; 125633965Sjdp } 125733965Sjdp 125833965Sjdp if (section != obj_textsec (abfd) 125933965Sjdp && section != obj_datasec (abfd)) 126033965Sjdp { 1261130561Sobrien if (aout_section_merge_with_text_p (abfd, section)) 1262130561Sobrien section->filepos = obj_textsec (abfd)->filepos + 1263130561Sobrien (section->vma - obj_textsec (abfd)->vma); 1264130561Sobrien else 1265130561Sobrien { 1266130561Sobrien (*_bfd_error_handler) 1267130561Sobrien (_("%s: can not represent section `%s' in a.out object file format"), 1268130561Sobrien bfd_get_filename (abfd), bfd_get_section_name (abfd, section)); 1269130561Sobrien bfd_set_error (bfd_error_nonrepresentable_section); 1270130561Sobrien return FALSE; 1271130561Sobrien } 127233965Sjdp } 127333965Sjdp 127433965Sjdp if (count != 0) 127533965Sjdp { 127633965Sjdp if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 127789857Sobrien || bfd_bwrite (location, count, abfd) != count) 1278130561Sobrien return FALSE; 127933965Sjdp } 128033965Sjdp 1281130561Sobrien return TRUE; 128233965Sjdp} 128333965Sjdp 128433965Sjdp/* Read the external symbols from an a.out file. */ 128533965Sjdp 1286130561Sobrienstatic bfd_boolean 1287218822Sdimaout_get_external_symbols (bfd *abfd) 128833965Sjdp{ 1289218822Sdim if (obj_aout_external_syms (abfd) == NULL) 129033965Sjdp { 129133965Sjdp bfd_size_type count; 129233965Sjdp struct external_nlist *syms; 129389857Sobrien bfd_size_type amt; 129433965Sjdp 129533965Sjdp count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE; 129633965Sjdp 129733965Sjdp#ifdef USE_MMAP 1298104834Sobrien if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd), 1299104834Sobrien exec_hdr (abfd)->a_syms, 1300130561Sobrien &obj_aout_sym_window (abfd), TRUE)) 1301130561Sobrien return FALSE; 130233965Sjdp syms = (struct external_nlist *) obj_aout_sym_window (abfd).data; 130333965Sjdp#else 130433965Sjdp /* We allocate using malloc to make the values easy to free 130533965Sjdp later on. If we put them on the objalloc it might not be 130633965Sjdp possible to free them. */ 1307218822Sdim syms = bfd_malloc (count * EXTERNAL_NLIST_SIZE); 1308218822Sdim if (syms == NULL && count != 0) 1309130561Sobrien return FALSE; 131033965Sjdp 131189857Sobrien amt = exec_hdr (abfd)->a_syms; 131233965Sjdp if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 131389857Sobrien || bfd_bread (syms, amt, abfd) != amt) 131433965Sjdp { 131533965Sjdp free (syms); 1316130561Sobrien return FALSE; 131733965Sjdp } 131833965Sjdp#endif 131933965Sjdp 132033965Sjdp obj_aout_external_syms (abfd) = syms; 132133965Sjdp obj_aout_external_sym_count (abfd) = count; 132233965Sjdp } 132377298Sobrien 132433965Sjdp if (obj_aout_external_strings (abfd) == NULL 132533965Sjdp && exec_hdr (abfd)->a_syms != 0) 132633965Sjdp { 132733965Sjdp unsigned char string_chars[BYTES_IN_WORD]; 132833965Sjdp bfd_size_type stringsize; 132933965Sjdp char *strings; 133089857Sobrien bfd_size_type amt = BYTES_IN_WORD; 133133965Sjdp 133233965Sjdp /* Get the size of the strings. */ 133333965Sjdp if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 1334218822Sdim || bfd_bread ((void *) string_chars, amt, abfd) != amt) 1335130561Sobrien return FALSE; 133633965Sjdp stringsize = GET_WORD (abfd, string_chars); 133733965Sjdp 133833965Sjdp#ifdef USE_MMAP 1339104834Sobrien if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize, 1340130561Sobrien &obj_aout_string_window (abfd), TRUE)) 1341130561Sobrien return FALSE; 134233965Sjdp strings = (char *) obj_aout_string_window (abfd).data; 134333965Sjdp#else 1344218822Sdim strings = bfd_malloc (stringsize + 1); 134533965Sjdp if (strings == NULL) 1346130561Sobrien return FALSE; 134733965Sjdp 134833965Sjdp /* Skip space for the string count in the buffer for convenience 134933965Sjdp when using indexes. */ 135089857Sobrien amt = stringsize - BYTES_IN_WORD; 135189857Sobrien if (bfd_bread (strings + BYTES_IN_WORD, amt, abfd) != amt) 135233965Sjdp { 135333965Sjdp free (strings); 1354130561Sobrien return FALSE; 135533965Sjdp } 135633965Sjdp#endif 135733965Sjdp 135833965Sjdp /* Ensure that a zero index yields an empty string. */ 135933965Sjdp strings[0] = '\0'; 136033965Sjdp 136133965Sjdp strings[stringsize - 1] = 0; 136233965Sjdp 136333965Sjdp obj_aout_external_strings (abfd) = strings; 136433965Sjdp obj_aout_external_string_size (abfd) = stringsize; 136533965Sjdp } 136633965Sjdp 1367130561Sobrien return TRUE; 136833965Sjdp} 136933965Sjdp 137033965Sjdp/* Translate an a.out symbol into a BFD symbol. The desc, other, type 137133965Sjdp and symbol->value fields of CACHE_PTR will be set from the a.out 137233965Sjdp nlist structure. This function is responsible for setting 137333965Sjdp symbol->flags and symbol->section, and adjusting symbol->value. */ 137433965Sjdp 1375130561Sobrienstatic bfd_boolean 1376218822Sdimtranslate_from_native_sym_flags (bfd *abfd, aout_symbol_type *cache_ptr) 137733965Sjdp{ 137833965Sjdp flagword visible; 137933965Sjdp 138033965Sjdp if ((cache_ptr->type & N_STAB) != 0 138133965Sjdp || cache_ptr->type == N_FN) 138233965Sjdp { 138333965Sjdp asection *sec; 138433965Sjdp 138533965Sjdp /* This is a debugging symbol. */ 138633965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING; 138733965Sjdp 138833965Sjdp /* Work out the symbol section. */ 138933965Sjdp switch (cache_ptr->type & N_TYPE) 139033965Sjdp { 139133965Sjdp case N_TEXT: 139233965Sjdp case N_FN: 139333965Sjdp sec = obj_textsec (abfd); 139433965Sjdp break; 139533965Sjdp case N_DATA: 139633965Sjdp sec = obj_datasec (abfd); 139733965Sjdp break; 139833965Sjdp case N_BSS: 139933965Sjdp sec = obj_bsssec (abfd); 140033965Sjdp break; 140133965Sjdp default: 140233965Sjdp case N_ABS: 140333965Sjdp sec = bfd_abs_section_ptr; 140433965Sjdp break; 140533965Sjdp } 140633965Sjdp 140733965Sjdp cache_ptr->symbol.section = sec; 140833965Sjdp cache_ptr->symbol.value -= sec->vma; 140933965Sjdp 1410130561Sobrien return TRUE; 141133965Sjdp } 141233965Sjdp 141333965Sjdp /* Get the default visibility. This does not apply to all types, so 141433965Sjdp we just hold it in a local variable to use if wanted. */ 141533965Sjdp if ((cache_ptr->type & N_EXT) == 0) 141633965Sjdp visible = BSF_LOCAL; 141733965Sjdp else 141833965Sjdp visible = BSF_GLOBAL; 141933965Sjdp 142033965Sjdp switch (cache_ptr->type) 142133965Sjdp { 142233965Sjdp default: 142333965Sjdp case N_ABS: case N_ABS | N_EXT: 142433965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 142533965Sjdp cache_ptr->symbol.flags = visible; 142633965Sjdp break; 142733965Sjdp 142833965Sjdp case N_UNDF | N_EXT: 142933965Sjdp if (cache_ptr->symbol.value != 0) 143033965Sjdp { 143133965Sjdp /* This is a common symbol. */ 143233965Sjdp cache_ptr->symbol.flags = BSF_GLOBAL; 143333965Sjdp cache_ptr->symbol.section = bfd_com_section_ptr; 143433965Sjdp } 143533965Sjdp else 143633965Sjdp { 143733965Sjdp cache_ptr->symbol.flags = 0; 143833965Sjdp cache_ptr->symbol.section = bfd_und_section_ptr; 143933965Sjdp } 144033965Sjdp break; 144133965Sjdp 144233965Sjdp case N_TEXT: case N_TEXT | N_EXT: 144333965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 144433965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 144533965Sjdp cache_ptr->symbol.flags = visible; 144633965Sjdp break; 144733965Sjdp 144833965Sjdp /* N_SETV symbols used to represent set vectors placed in the 144933965Sjdp data section. They are no longer generated. Theoretically, 145033965Sjdp it was possible to extract the entries and combine them with 145133965Sjdp new ones, although I don't know if that was ever actually 145233965Sjdp done. Unless that feature is restored, treat them as data 145333965Sjdp symbols. */ 145433965Sjdp case N_SETV: case N_SETV | N_EXT: 145533965Sjdp case N_DATA: case N_DATA | N_EXT: 145633965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 145733965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 145833965Sjdp cache_ptr->symbol.flags = visible; 145933965Sjdp break; 146033965Sjdp 146133965Sjdp case N_BSS: case N_BSS | N_EXT: 146233965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 146333965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 146433965Sjdp cache_ptr->symbol.flags = visible; 146533965Sjdp break; 146633965Sjdp 146733965Sjdp case N_SETA: case N_SETA | N_EXT: 146833965Sjdp case N_SETT: case N_SETT | N_EXT: 146933965Sjdp case N_SETD: case N_SETD | N_EXT: 147033965Sjdp case N_SETB: case N_SETB | N_EXT: 147133965Sjdp { 147233965Sjdp /* This code is no longer needed. It used to be used to make 147333965Sjdp the linker handle set symbols, but they are now handled in 147433965Sjdp the add_symbols routine instead. */ 147533965Sjdp switch (cache_ptr->type & N_TYPE) 147633965Sjdp { 147733965Sjdp case N_SETA: 147833965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 147933965Sjdp break; 148033965Sjdp case N_SETT: 148133965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 148233965Sjdp break; 148333965Sjdp case N_SETD: 148433965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 148533965Sjdp break; 148633965Sjdp case N_SETB: 148733965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 148833965Sjdp break; 148933965Sjdp } 149033965Sjdp 149133965Sjdp cache_ptr->symbol.flags |= BSF_CONSTRUCTOR; 149233965Sjdp } 149333965Sjdp break; 149433965Sjdp 149533965Sjdp case N_WARNING: 149633965Sjdp /* This symbol is the text of a warning message. The next 149733965Sjdp symbol is the symbol to associate the warning with. If a 149833965Sjdp reference is made to that symbol, a warning is issued. */ 149933965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING; 150033965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 150133965Sjdp break; 150233965Sjdp 150333965Sjdp case N_INDR: case N_INDR | N_EXT: 150433965Sjdp /* An indirect symbol. This consists of two symbols in a row. 150533965Sjdp The first symbol is the name of the indirection. The second 150633965Sjdp symbol is the name of the target. A reference to the first 150733965Sjdp symbol becomes a reference to the second. */ 150833965Sjdp cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible; 150933965Sjdp cache_ptr->symbol.section = bfd_ind_section_ptr; 151033965Sjdp break; 151133965Sjdp 151233965Sjdp case N_WEAKU: 151333965Sjdp cache_ptr->symbol.section = bfd_und_section_ptr; 151433965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 151533965Sjdp break; 151633965Sjdp 151733965Sjdp case N_WEAKA: 151833965Sjdp cache_ptr->symbol.section = bfd_abs_section_ptr; 151933965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 152033965Sjdp break; 152133965Sjdp 152233965Sjdp case N_WEAKT: 152333965Sjdp cache_ptr->symbol.section = obj_textsec (abfd); 152433965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 152533965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 152633965Sjdp break; 152733965Sjdp 152833965Sjdp case N_WEAKD: 152933965Sjdp cache_ptr->symbol.section = obj_datasec (abfd); 153033965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 153133965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 153233965Sjdp break; 153333965Sjdp 153433965Sjdp case N_WEAKB: 153533965Sjdp cache_ptr->symbol.section = obj_bsssec (abfd); 153633965Sjdp cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; 153733965Sjdp cache_ptr->symbol.flags = BSF_WEAK; 153833965Sjdp break; 153933965Sjdp } 154033965Sjdp 1541130561Sobrien return TRUE; 154233965Sjdp} 154333965Sjdp 154433965Sjdp/* Set the fields of SYM_POINTER according to CACHE_PTR. */ 154533965Sjdp 1546130561Sobrienstatic bfd_boolean 1547218822Sdimtranslate_to_native_sym_flags (bfd *abfd, 1548218822Sdim asymbol *cache_ptr, 1549218822Sdim struct external_nlist *sym_pointer) 155033965Sjdp{ 155133965Sjdp bfd_vma value = cache_ptr->value; 155233965Sjdp asection *sec; 155333965Sjdp bfd_vma off; 155433965Sjdp 155533965Sjdp /* Mask out any existing type bits in case copying from one section 155633965Sjdp to another. */ 155733965Sjdp sym_pointer->e_type[0] &= ~N_TYPE; 155833965Sjdp 155933965Sjdp sec = bfd_get_section (cache_ptr); 156033965Sjdp off = 0; 156133965Sjdp 156233965Sjdp if (sec == NULL) 156333965Sjdp { 156433965Sjdp /* This case occurs, e.g., for the *DEBUG* section of a COFF 156533965Sjdp file. */ 156633965Sjdp (*_bfd_error_handler) 156760484Sobrien (_("%s: can not represent section for symbol `%s' in a.out object file format"), 156877298Sobrien bfd_get_filename (abfd), 156960484Sobrien cache_ptr->name != NULL ? cache_ptr->name : _("*unknown*")); 157033965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 1571130561Sobrien return FALSE; 157233965Sjdp } 157333965Sjdp 157433965Sjdp if (sec->output_section != NULL) 157533965Sjdp { 157633965Sjdp off = sec->output_offset; 157733965Sjdp sec = sec->output_section; 157833965Sjdp } 157933965Sjdp 158033965Sjdp if (bfd_is_abs_section (sec)) 158133965Sjdp sym_pointer->e_type[0] |= N_ABS; 158233965Sjdp else if (sec == obj_textsec (abfd)) 158333965Sjdp sym_pointer->e_type[0] |= N_TEXT; 158433965Sjdp else if (sec == obj_datasec (abfd)) 158533965Sjdp sym_pointer->e_type[0] |= N_DATA; 158633965Sjdp else if (sec == obj_bsssec (abfd)) 158733965Sjdp sym_pointer->e_type[0] |= N_BSS; 158833965Sjdp else if (bfd_is_und_section (sec)) 158933965Sjdp sym_pointer->e_type[0] = N_UNDF | N_EXT; 159033965Sjdp else if (bfd_is_ind_section (sec)) 159133965Sjdp sym_pointer->e_type[0] = N_INDR; 159233965Sjdp else if (bfd_is_com_section (sec)) 159333965Sjdp sym_pointer->e_type[0] = N_UNDF | N_EXT; 159433965Sjdp else 159533965Sjdp { 1596130561Sobrien if (aout_section_merge_with_text_p (abfd, sec)) 1597130561Sobrien sym_pointer->e_type[0] |= N_TEXT; 1598130561Sobrien else 1599130561Sobrien { 1600130561Sobrien (*_bfd_error_handler) 1601130561Sobrien (_("%s: can not represent section `%s' in a.out object file format"), 1602130561Sobrien bfd_get_filename (abfd), bfd_get_section_name (abfd, sec)); 1603130561Sobrien bfd_set_error (bfd_error_nonrepresentable_section); 1604130561Sobrien return FALSE; 1605130561Sobrien } 160633965Sjdp } 160733965Sjdp 1608130561Sobrien /* Turn the symbol from section relative to absolute again. */ 160933965Sjdp value += sec->vma + off; 161033965Sjdp 161133965Sjdp if ((cache_ptr->flags & BSF_WARNING) != 0) 161233965Sjdp sym_pointer->e_type[0] = N_WARNING; 161333965Sjdp 161433965Sjdp if ((cache_ptr->flags & BSF_DEBUGGING) != 0) 161533965Sjdp sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type; 161633965Sjdp else if ((cache_ptr->flags & BSF_GLOBAL) != 0) 161733965Sjdp sym_pointer->e_type[0] |= N_EXT; 161877298Sobrien else if ((cache_ptr->flags & BSF_LOCAL) != 0) 161977298Sobrien sym_pointer->e_type[0] &= ~N_EXT; 162033965Sjdp 162133965Sjdp if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0) 162233965Sjdp { 162333965Sjdp int type = ((aout_symbol_type *) cache_ptr)->type; 1624130561Sobrien 162533965Sjdp switch (type) 162633965Sjdp { 162733965Sjdp case N_ABS: type = N_SETA; break; 162833965Sjdp case N_TEXT: type = N_SETT; break; 162933965Sjdp case N_DATA: type = N_SETD; break; 163033965Sjdp case N_BSS: type = N_SETB; break; 163133965Sjdp } 163233965Sjdp sym_pointer->e_type[0] = type; 163333965Sjdp } 163433965Sjdp 163533965Sjdp if ((cache_ptr->flags & BSF_WEAK) != 0) 163633965Sjdp { 163733965Sjdp int type; 163833965Sjdp 163933965Sjdp switch (sym_pointer->e_type[0] & N_TYPE) 164033965Sjdp { 164133965Sjdp default: 164233965Sjdp case N_ABS: type = N_WEAKA; break; 164333965Sjdp case N_TEXT: type = N_WEAKT; break; 164433965Sjdp case N_DATA: type = N_WEAKD; break; 164533965Sjdp case N_BSS: type = N_WEAKB; break; 164633965Sjdp case N_UNDF: type = N_WEAKU; break; 164733965Sjdp } 164833965Sjdp sym_pointer->e_type[0] = type; 164933965Sjdp } 165033965Sjdp 165189857Sobrien PUT_WORD (abfd, value, sym_pointer->e_value); 165233965Sjdp 1653130561Sobrien return TRUE; 165433965Sjdp} 165533965Sjdp 165677298Sobrien/* Native-level interface to symbols. */ 165733965Sjdp 165833965Sjdpasymbol * 1659218822SdimNAME (aout, make_empty_symbol) (bfd *abfd) 166033965Sjdp{ 166189857Sobrien bfd_size_type amt = sizeof (aout_symbol_type); 1662218822Sdim 1663218822Sdim aout_symbol_type *new = bfd_zalloc (abfd, amt); 166433965Sjdp if (!new) 166533965Sjdp return NULL; 166633965Sjdp new->symbol.the_bfd = abfd; 166733965Sjdp 166833965Sjdp return &new->symbol; 166933965Sjdp} 167033965Sjdp 167133965Sjdp/* Translate a set of internal symbols into external symbols. */ 167233965Sjdp 1673130561Sobrienbfd_boolean 1674218822SdimNAME (aout, translate_symbol_table) (bfd *abfd, 1675218822Sdim aout_symbol_type *in, 1676218822Sdim struct external_nlist *ext, 1677218822Sdim bfd_size_type count, 1678218822Sdim char *str, 1679218822Sdim bfd_size_type strsize, 1680218822Sdim bfd_boolean dynamic) 168133965Sjdp{ 168233965Sjdp struct external_nlist *ext_end; 168333965Sjdp 168433965Sjdp ext_end = ext + count; 168533965Sjdp for (; ext < ext_end; ext++, in++) 168633965Sjdp { 168733965Sjdp bfd_vma x; 168833965Sjdp 168933965Sjdp x = GET_WORD (abfd, ext->e_strx); 169033965Sjdp in->symbol.the_bfd = abfd; 169133965Sjdp 169233965Sjdp /* For the normal symbols, the zero index points at the number 169333965Sjdp of bytes in the string table but is to be interpreted as the 169433965Sjdp null string. For the dynamic symbols, the number of bytes in 169533965Sjdp the string table is stored in the __DYNAMIC structure and the 169633965Sjdp zero index points at an actual string. */ 169733965Sjdp if (x == 0 && ! dynamic) 169833965Sjdp in->symbol.name = ""; 169933965Sjdp else if (x < strsize) 170033965Sjdp in->symbol.name = str + x; 170133965Sjdp else 1702130561Sobrien return FALSE; 170333965Sjdp 170433965Sjdp in->symbol.value = GET_SWORD (abfd, ext->e_value); 170589857Sobrien in->desc = H_GET_16 (abfd, ext->e_desc); 170689857Sobrien in->other = H_GET_8 (abfd, ext->e_other); 170789857Sobrien in->type = H_GET_8 (abfd, ext->e_type); 170833965Sjdp in->symbol.udata.p = NULL; 170933965Sjdp 171033965Sjdp if (! translate_from_native_sym_flags (abfd, in)) 1711130561Sobrien return FALSE; 171233965Sjdp 171333965Sjdp if (dynamic) 171433965Sjdp in->symbol.flags |= BSF_DYNAMIC; 171533965Sjdp } 171633965Sjdp 1717130561Sobrien return TRUE; 171833965Sjdp} 171933965Sjdp 172033965Sjdp/* We read the symbols into a buffer, which is discarded when this 172133965Sjdp function exits. We read the strings into a buffer large enough to 172277298Sobrien hold them all plus all the cached symbol entries. */ 172333965Sjdp 1724130561Sobrienbfd_boolean 1725218822SdimNAME (aout, slurp_symbol_table) (bfd *abfd) 172633965Sjdp{ 172733965Sjdp struct external_nlist *old_external_syms; 172833965Sjdp aout_symbol_type *cached; 172989857Sobrien bfd_size_type cached_size; 173033965Sjdp 1731130561Sobrien /* If there's no work to be done, don't do any. */ 1732218822Sdim if (obj_aout_symbols (abfd) != NULL) 1733130561Sobrien return TRUE; 173433965Sjdp 173533965Sjdp old_external_syms = obj_aout_external_syms (abfd); 173633965Sjdp 173733965Sjdp if (! aout_get_external_symbols (abfd)) 1738130561Sobrien return FALSE; 173933965Sjdp 174089857Sobrien cached_size = obj_aout_external_sym_count (abfd); 174189857Sobrien cached_size *= sizeof (aout_symbol_type); 1742218822Sdim cached = bfd_zmalloc (cached_size); 174333965Sjdp if (cached == NULL && cached_size != 0) 1744130561Sobrien return FALSE; 174533965Sjdp 174633965Sjdp /* Convert from external symbol information to internal. */ 1747218822Sdim if (! (NAME (aout, translate_symbol_table) 174833965Sjdp (abfd, cached, 174933965Sjdp obj_aout_external_syms (abfd), 175033965Sjdp obj_aout_external_sym_count (abfd), 175133965Sjdp obj_aout_external_strings (abfd), 175233965Sjdp obj_aout_external_string_size (abfd), 1753130561Sobrien FALSE))) 175433965Sjdp { 175533965Sjdp free (cached); 1756130561Sobrien return FALSE; 175733965Sjdp } 175833965Sjdp 175933965Sjdp bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd); 176033965Sjdp 176133965Sjdp obj_aout_symbols (abfd) = cached; 176233965Sjdp 176333965Sjdp /* It is very likely that anybody who calls this function will not 176433965Sjdp want the external symbol information, so if it was allocated 176533965Sjdp because of our call to aout_get_external_symbols, we free it up 176633965Sjdp right away to save space. */ 1767218822Sdim if (old_external_syms == NULL 1768218822Sdim && obj_aout_external_syms (abfd) != NULL) 176933965Sjdp { 177033965Sjdp#ifdef USE_MMAP 177133965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 177233965Sjdp#else 177333965Sjdp free (obj_aout_external_syms (abfd)); 177433965Sjdp#endif 177533965Sjdp obj_aout_external_syms (abfd) = NULL; 177633965Sjdp } 177733965Sjdp 1778130561Sobrien return TRUE; 177933965Sjdp} 178033965Sjdp 178133965Sjdp/* We use a hash table when writing out symbols so that we only write 178233965Sjdp out a particular string once. This helps particularly when the 178333965Sjdp linker writes out stabs debugging entries, because each different 178433965Sjdp contributing object file tends to have many duplicate stabs 178533965Sjdp strings. 178633965Sjdp 178733965Sjdp This hash table code breaks dbx on SunOS 4.1.3, so we don't do it 178833965Sjdp if BFD_TRADITIONAL_FORMAT is set. */ 178933965Sjdp 179033965Sjdp/* Get the index of a string in a strtab, adding it if it is not 179133965Sjdp already present. */ 179233965Sjdp 1793218822Sdimstatic inline bfd_size_type 1794218822Sdimadd_to_stringtab (bfd *abfd, 1795218822Sdim struct bfd_strtab_hash *tab, 1796218822Sdim const char *str, 1797218822Sdim bfd_boolean copy) 179833965Sjdp{ 1799130561Sobrien bfd_boolean hash; 180033965Sjdp bfd_size_type index; 180133965Sjdp 180233965Sjdp /* An index of 0 always means the empty string. */ 180333965Sjdp if (str == 0 || *str == '\0') 180433965Sjdp return 0; 180533965Sjdp 180633965Sjdp /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx 180733965Sjdp doesn't understand a hashed string table. */ 1808130561Sobrien hash = TRUE; 180933965Sjdp if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0) 1810130561Sobrien hash = FALSE; 181133965Sjdp 181233965Sjdp index = _bfd_stringtab_add (tab, str, hash, copy); 181333965Sjdp 181433965Sjdp if (index != (bfd_size_type) -1) 1815218822Sdim /* Add BYTES_IN_WORD to the return value to account for the 1816218822Sdim space taken up by the string table size. */ 1817218822Sdim index += BYTES_IN_WORD; 181833965Sjdp 181933965Sjdp return index; 182033965Sjdp} 182133965Sjdp 182233965Sjdp/* Write out a strtab. ABFD is already at the right location in the 182333965Sjdp file. */ 182433965Sjdp 1825130561Sobrienstatic bfd_boolean 1826218822Sdimemit_stringtab (bfd *abfd, struct bfd_strtab_hash *tab) 182733965Sjdp{ 182833965Sjdp bfd_byte buffer[BYTES_IN_WORD]; 182989857Sobrien bfd_size_type amt = BYTES_IN_WORD; 183033965Sjdp 183133965Sjdp /* The string table starts with the size. */ 183233965Sjdp PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer); 1833218822Sdim if (bfd_bwrite ((void *) buffer, amt, abfd) != amt) 1834130561Sobrien return FALSE; 183533965Sjdp 183633965Sjdp return _bfd_stringtab_emit (abfd, tab); 183733965Sjdp} 183833965Sjdp 1839130561Sobrienbfd_boolean 1840218822SdimNAME (aout, write_syms) (bfd *abfd) 184133965Sjdp{ 184233965Sjdp unsigned int count ; 184333965Sjdp asymbol **generic = bfd_get_outsymbols (abfd); 184433965Sjdp struct bfd_strtab_hash *strtab; 184533965Sjdp 184633965Sjdp strtab = _bfd_stringtab_init (); 184733965Sjdp if (strtab == NULL) 1848130561Sobrien return FALSE; 184933965Sjdp 185033965Sjdp for (count = 0; count < bfd_get_symcount (abfd); count++) 185133965Sjdp { 185233965Sjdp asymbol *g = generic[count]; 185333965Sjdp bfd_size_type indx; 185433965Sjdp struct external_nlist nsp; 185589857Sobrien bfd_size_type amt; 185633965Sjdp 1857130561Sobrien indx = add_to_stringtab (abfd, strtab, g->name, FALSE); 185833965Sjdp if (indx == (bfd_size_type) -1) 185933965Sjdp goto error_return; 186033965Sjdp PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx); 186133965Sjdp 186289857Sobrien if (bfd_asymbol_flavour (g) == abfd->xvec->flavour) 186333965Sjdp { 186489857Sobrien H_PUT_16 (abfd, aout_symbol (g)->desc, nsp.e_desc); 186589857Sobrien H_PUT_8 (abfd, aout_symbol (g)->other, nsp.e_other); 186689857Sobrien H_PUT_8 (abfd, aout_symbol (g)->type, nsp.e_type); 186733965Sjdp } 186833965Sjdp else 186933965Sjdp { 187089857Sobrien H_PUT_16 (abfd, 0, nsp.e_desc); 187189857Sobrien H_PUT_8 (abfd, 0, nsp.e_other); 187289857Sobrien H_PUT_8 (abfd, 0, nsp.e_type); 187333965Sjdp } 187433965Sjdp 187533965Sjdp if (! translate_to_native_sym_flags (abfd, g, &nsp)) 187633965Sjdp goto error_return; 187733965Sjdp 187889857Sobrien amt = EXTERNAL_NLIST_SIZE; 1879218822Sdim if (bfd_bwrite ((void *) &nsp, amt, abfd) != amt) 188033965Sjdp goto error_return; 188133965Sjdp 188233965Sjdp /* NB: `KEEPIT' currently overlays `udata.p', so set this only 188333965Sjdp here, at the end. */ 188433965Sjdp g->KEEPIT = count; 188533965Sjdp } 188633965Sjdp 188733965Sjdp if (! emit_stringtab (abfd, strtab)) 188833965Sjdp goto error_return; 188933965Sjdp 189033965Sjdp _bfd_stringtab_free (strtab); 189133965Sjdp 1892130561Sobrien return TRUE; 189333965Sjdp 189433965Sjdperror_return: 189533965Sjdp _bfd_stringtab_free (strtab); 1896130561Sobrien return FALSE; 189733965Sjdp} 189833965Sjdp 189933965Sjdplong 1900218822SdimNAME (aout, canonicalize_symtab) (bfd *abfd, asymbol **location) 190133965Sjdp{ 1902218822Sdim unsigned int counter = 0; 1903218822Sdim aout_symbol_type *symbase; 190433965Sjdp 1905218822Sdim if (!NAME (aout, slurp_symbol_table) (abfd)) 1906218822Sdim return -1; 190733965Sjdp 1908218822Sdim for (symbase = obj_aout_symbols (abfd); 1909218822Sdim counter++ < bfd_get_symcount (abfd); 1910218822Sdim ) 1911218822Sdim *(location++) = (asymbol *) (symbase++); 1912218822Sdim *location++ =0; 1913218822Sdim return bfd_get_symcount (abfd); 191433965Sjdp} 191533965Sjdp 1916130561Sobrien/* Standard reloc stuff. */ 191777298Sobrien/* Output standard relocation information to a file in target byte order. */ 191833965Sjdp 1919218822Sdimextern void NAME (aout, swap_std_reloc_out) 1920218822Sdim (bfd *, arelent *, struct reloc_std_external *); 192133965Sjdp 192233965Sjdpvoid 1923218822SdimNAME (aout, swap_std_reloc_out) (bfd *abfd, 1924218822Sdim arelent *g, 1925218822Sdim struct reloc_std_external *natptr) 192633965Sjdp{ 192733965Sjdp int r_index; 192833965Sjdp asymbol *sym = *(g->sym_ptr_ptr); 192933965Sjdp int r_extern; 193033965Sjdp unsigned int r_length; 193133965Sjdp int r_pcrel; 193233965Sjdp int r_baserel, r_jmptable, r_relative; 193333965Sjdp asection *output_section = sym->section->output_section; 193433965Sjdp 193589857Sobrien PUT_WORD (abfd, g->address, natptr->r_address); 193633965Sjdp 1937130561Sobrien r_length = g->howto->size ; /* Size as a power of two. */ 1938130561Sobrien r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ 193933965Sjdp /* XXX This relies on relocs coming from a.out files. */ 194033965Sjdp r_baserel = (g->howto->type & 8) != 0; 194133965Sjdp r_jmptable = (g->howto->type & 16) != 0; 194233965Sjdp r_relative = (g->howto->type & 32) != 0; 194333965Sjdp 1944130561Sobrien /* Name was clobbered by aout_write_syms to be symbol index. */ 194533965Sjdp 194633965Sjdp /* If this relocation is relative to a symbol then set the 194733965Sjdp r_index to the symbols index, and the r_extern bit. 194833965Sjdp 194933965Sjdp Absolute symbols can come in in two ways, either as an offset 195033965Sjdp from the abs section, or as a symbol which has an abs value. 1951130561Sobrien check for that here. */ 195233965Sjdp 195333965Sjdp if (bfd_is_com_section (output_section) 195433965Sjdp || bfd_is_abs_section (output_section) 1955218822Sdim || bfd_is_und_section (output_section) 1956218822Sdim /* PR gas/3041 a.out relocs against weak symbols 1957218822Sdim must be treated as if they were against externs. */ 1958218822Sdim || (sym->flags & BSF_WEAK)) 195933965Sjdp { 196033965Sjdp if (bfd_abs_section_ptr->symbol == sym) 1961130561Sobrien { 1962130561Sobrien /* Whoops, looked like an abs symbol, but is 1963130561Sobrien really an offset from the abs section. */ 1964130561Sobrien r_index = N_ABS; 1965130561Sobrien r_extern = 0; 1966130561Sobrien } 196733965Sjdp else 1968130561Sobrien { 1969130561Sobrien /* Fill in symbol. */ 1970130561Sobrien r_extern = 1; 1971130561Sobrien r_index = (*(g->sym_ptr_ptr))->KEEPIT; 1972130561Sobrien } 197333965Sjdp } 197433965Sjdp else 197533965Sjdp { 1976130561Sobrien /* Just an ordinary section. */ 197733965Sjdp r_extern = 0; 197833965Sjdp r_index = output_section->target_index; 197933965Sjdp } 198033965Sjdp 1981130561Sobrien /* Now the fun stuff. */ 198289857Sobrien if (bfd_header_big_endian (abfd)) 198389857Sobrien { 198433965Sjdp natptr->r_index[0] = r_index >> 16; 198533965Sjdp natptr->r_index[1] = r_index >> 8; 198633965Sjdp natptr->r_index[2] = r_index; 198789857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) 198889857Sobrien | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) 198989857Sobrien | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) 199089857Sobrien | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) 199189857Sobrien | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) 199289857Sobrien | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); 199389857Sobrien } 199489857Sobrien else 199589857Sobrien { 199689857Sobrien natptr->r_index[2] = r_index >> 16; 199789857Sobrien natptr->r_index[1] = r_index >> 8; 199889857Sobrien natptr->r_index[0] = r_index; 199989857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) 200089857Sobrien | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) 200189857Sobrien | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) 200289857Sobrien | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) 200389857Sobrien | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) 200489857Sobrien | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 200589857Sobrien } 200633965Sjdp} 200733965Sjdp 2008130561Sobrien/* Extended stuff. */ 200977298Sobrien/* Output extended relocation information to a file in target byte order. */ 201033965Sjdp 2011218822Sdimextern void NAME (aout, swap_ext_reloc_out) 2012218822Sdim (bfd *, arelent *, struct reloc_ext_external *); 201333965Sjdp 201433965Sjdpvoid 2015218822SdimNAME (aout, swap_ext_reloc_out) (bfd *abfd, 2016218822Sdim arelent *g, 2017218822Sdim struct reloc_ext_external *natptr) 201833965Sjdp{ 201933965Sjdp int r_index; 202033965Sjdp int r_extern; 202133965Sjdp unsigned int r_type; 202289857Sobrien bfd_vma r_addend; 202333965Sjdp asymbol *sym = *(g->sym_ptr_ptr); 202433965Sjdp asection *output_section = sym->section->output_section; 202533965Sjdp 202633965Sjdp PUT_WORD (abfd, g->address, natptr->r_address); 202733965Sjdp 202833965Sjdp r_type = (unsigned int) g->howto->type; 202933965Sjdp 203033965Sjdp r_addend = g->addend; 203133965Sjdp if ((sym->flags & BSF_SECTION_SYM) != 0) 203233965Sjdp r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma; 203333965Sjdp 203433965Sjdp /* If this relocation is relative to a symbol then set the 203533965Sjdp r_index to the symbols index, and the r_extern bit. 203633965Sjdp 203733965Sjdp Absolute symbols can come in in two ways, either as an offset 203833965Sjdp from the abs section, or as a symbol which has an abs value. 203933965Sjdp check for that here. */ 204033965Sjdp if (bfd_is_abs_section (bfd_get_section (sym))) 204133965Sjdp { 204233965Sjdp r_extern = 0; 204333965Sjdp r_index = N_ABS; 204433965Sjdp } 204533965Sjdp else if ((sym->flags & BSF_SECTION_SYM) == 0) 204633965Sjdp { 204733965Sjdp if (bfd_is_und_section (bfd_get_section (sym)) 204833965Sjdp || (sym->flags & BSF_GLOBAL) != 0) 204933965Sjdp r_extern = 1; 205033965Sjdp else 205133965Sjdp r_extern = 0; 205233965Sjdp r_index = (*(g->sym_ptr_ptr))->KEEPIT; 205333965Sjdp } 205433965Sjdp else 205533965Sjdp { 2056130561Sobrien /* Just an ordinary section. */ 205733965Sjdp r_extern = 0; 205833965Sjdp r_index = output_section->target_index; 205933965Sjdp } 206033965Sjdp 2061130561Sobrien /* Now the fun stuff. */ 206289857Sobrien if (bfd_header_big_endian (abfd)) 206389857Sobrien { 206489857Sobrien natptr->r_index[0] = r_index >> 16; 206589857Sobrien natptr->r_index[1] = r_index >> 8; 206689857Sobrien natptr->r_index[2] = r_index; 206789857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) 206889857Sobrien | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG)); 206989857Sobrien } 207089857Sobrien else 207189857Sobrien { 207289857Sobrien natptr->r_index[2] = r_index >> 16; 207389857Sobrien natptr->r_index[1] = r_index >> 8; 207489857Sobrien natptr->r_index[0] = r_index; 207589857Sobrien natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) 207689857Sobrien | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE)); 207789857Sobrien } 207833965Sjdp 207933965Sjdp PUT_WORD (abfd, r_addend, natptr->r_addend); 208033965Sjdp} 208133965Sjdp 208233965Sjdp/* BFD deals internally with all things based from the section they're 208333965Sjdp in. so, something in 10 bytes into a text section with a base of 208433965Sjdp 50 would have a symbol (.text+10) and know .text vma was 50. 208533965Sjdp 208633965Sjdp Aout keeps all it's symbols based from zero, so the symbol would 208733965Sjdp contain 60. This macro subs the base of each section from the value 208889857Sobrien to give the true offset from the section. */ 208933965Sjdp 209089857Sobrien#define MOVE_ADDRESS(ad) \ 209189857Sobrien if (r_extern) \ 209289857Sobrien { \ 209389857Sobrien /* Undefined symbol. */ \ 209489857Sobrien cache_ptr->sym_ptr_ptr = symbols + r_index; \ 209533965Sjdp cache_ptr->addend = ad; \ 209633965Sjdp } \ 209789857Sobrien else \ 209889857Sobrien { \ 209989857Sobrien /* Defined, section relative. Replace symbol with pointer to \ 210089857Sobrien symbol which points to section. */ \ 210189857Sobrien switch (r_index) \ 210289857Sobrien { \ 210389857Sobrien case N_TEXT: \ 210489857Sobrien case N_TEXT | N_EXT: \ 210589857Sobrien cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr; \ 210689857Sobrien cache_ptr->addend = ad - su->textsec->vma; \ 210789857Sobrien break; \ 210889857Sobrien case N_DATA: \ 210989857Sobrien case N_DATA | N_EXT: \ 211089857Sobrien cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr; \ 211189857Sobrien cache_ptr->addend = ad - su->datasec->vma; \ 211289857Sobrien break; \ 211389857Sobrien case N_BSS: \ 211489857Sobrien case N_BSS | N_EXT: \ 211589857Sobrien cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr; \ 211689857Sobrien cache_ptr->addend = ad - su->bsssec->vma; \ 211789857Sobrien break; \ 211889857Sobrien default: \ 211989857Sobrien case N_ABS: \ 212089857Sobrien case N_ABS | N_EXT: \ 212189857Sobrien cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \ 212289857Sobrien cache_ptr->addend = ad; \ 212389857Sobrien break; \ 212489857Sobrien } \ 212589857Sobrien } 212633965Sjdp 212733965Sjdpvoid 2128218822SdimNAME (aout, swap_ext_reloc_in) (bfd *abfd, 2129218822Sdim struct reloc_ext_external *bytes, 2130218822Sdim arelent *cache_ptr, 2131218822Sdim asymbol **symbols, 2132218822Sdim bfd_size_type symcount) 213333965Sjdp{ 213433965Sjdp unsigned int r_index; 213533965Sjdp int r_extern; 213633965Sjdp unsigned int r_type; 213733965Sjdp struct aoutdata *su = &(abfd->tdata.aout_data->a); 213833965Sjdp 213933965Sjdp cache_ptr->address = (GET_SWORD (abfd, bytes->r_address)); 214033965Sjdp 2141130561Sobrien /* Now the fun stuff. */ 214289857Sobrien if (bfd_header_big_endian (abfd)) 214389857Sobrien { 2144107492Sobrien r_index = (((unsigned int) bytes->r_index[0] << 16) 2145107492Sobrien | ((unsigned int) bytes->r_index[1] << 8) 214689857Sobrien | bytes->r_index[2]); 214789857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 214889857Sobrien r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 214989857Sobrien >> RELOC_EXT_BITS_TYPE_SH_BIG); 215089857Sobrien } 215189857Sobrien else 215289857Sobrien { 2153107492Sobrien r_index = (((unsigned int) bytes->r_index[2] << 16) 2154107492Sobrien | ((unsigned int) bytes->r_index[1] << 8) 215589857Sobrien | bytes->r_index[0]); 215689857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 215789857Sobrien r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 215889857Sobrien >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 215989857Sobrien } 216033965Sjdp 216133965Sjdp cache_ptr->howto = howto_table_ext + r_type; 216233965Sjdp 216333965Sjdp /* Base relative relocs are always against the symbol table, 216433965Sjdp regardless of the setting of r_extern. r_extern just reflects 216533965Sjdp whether the symbol the reloc is against is local or global. */ 2166107492Sobrien if (r_type == (unsigned int) RELOC_BASE10 2167107492Sobrien || r_type == (unsigned int) RELOC_BASE13 2168107492Sobrien || r_type == (unsigned int) RELOC_BASE22) 216933965Sjdp r_extern = 1; 217033965Sjdp 217133965Sjdp if (r_extern && r_index > symcount) 217233965Sjdp { 217333965Sjdp /* We could arrange to return an error, but it might be useful 217433965Sjdp to see the file even if it is bad. */ 217533965Sjdp r_extern = 0; 217633965Sjdp r_index = N_ABS; 217733965Sjdp } 217833965Sjdp 217989857Sobrien MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend)); 218033965Sjdp} 218133965Sjdp 218233965Sjdpvoid 2183218822SdimNAME (aout, swap_std_reloc_in) (bfd *abfd, 2184218822Sdim struct reloc_std_external *bytes, 2185218822Sdim arelent *cache_ptr, 2186218822Sdim asymbol **symbols, 2187218822Sdim bfd_size_type symcount) 218833965Sjdp{ 218933965Sjdp unsigned int r_index; 219033965Sjdp int r_extern; 219133965Sjdp unsigned int r_length; 219233965Sjdp int r_pcrel; 219333965Sjdp int r_baserel, r_jmptable, r_relative; 219433965Sjdp struct aoutdata *su = &(abfd->tdata.aout_data->a); 219533965Sjdp unsigned int howto_idx; 219633965Sjdp 219789857Sobrien cache_ptr->address = H_GET_32 (abfd, bytes->r_address); 219833965Sjdp 2199130561Sobrien /* Now the fun stuff. */ 220089857Sobrien if (bfd_header_big_endian (abfd)) 220189857Sobrien { 2202107492Sobrien r_index = (((unsigned int) bytes->r_index[0] << 16) 2203107492Sobrien | ((unsigned int) bytes->r_index[1] << 8) 220489857Sobrien | bytes->r_index[2]); 220589857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); 220689857Sobrien r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 220789857Sobrien r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 220889857Sobrien r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 220989857Sobrien r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); 221089857Sobrien r_length = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) 221189857Sobrien >> RELOC_STD_BITS_LENGTH_SH_BIG); 221289857Sobrien } 221389857Sobrien else 221489857Sobrien { 2215107492Sobrien r_index = (((unsigned int) bytes->r_index[2] << 16) 2216107492Sobrien | ((unsigned int) bytes->r_index[1] << 8) 221789857Sobrien | bytes->r_index[0]); 221889857Sobrien r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); 221989857Sobrien r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 222089857Sobrien r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); 222189857Sobrien r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); 222289857Sobrien r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE)); 222389857Sobrien r_length = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) 222489857Sobrien >> RELOC_STD_BITS_LENGTH_SH_LITTLE); 222589857Sobrien } 222633965Sjdp 222789857Sobrien howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel 222889857Sobrien + 16 * r_jmptable + 32 * r_relative); 222933965Sjdp BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); 223033965Sjdp cache_ptr->howto = howto_table_std + howto_idx; 223133965Sjdp BFD_ASSERT (cache_ptr->howto->type != (unsigned int) -1); 223233965Sjdp 223333965Sjdp /* Base relative relocs are always against the symbol table, 223433965Sjdp regardless of the setting of r_extern. r_extern just reflects 223533965Sjdp whether the symbol the reloc is against is local or global. */ 223633965Sjdp if (r_baserel) 223733965Sjdp r_extern = 1; 223833965Sjdp 223933965Sjdp if (r_extern && r_index > symcount) 224033965Sjdp { 224133965Sjdp /* We could arrange to return an error, but it might be useful 224233965Sjdp to see the file even if it is bad. */ 224333965Sjdp r_extern = 0; 224433965Sjdp r_index = N_ABS; 224533965Sjdp } 224633965Sjdp 224789857Sobrien MOVE_ADDRESS (0); 224833965Sjdp} 224933965Sjdp 225033965Sjdp/* Read and swap the relocs for a section. */ 225133965Sjdp 2252130561Sobrienbfd_boolean 2253218822SdimNAME (aout, slurp_reloc_table) (bfd *abfd, sec_ptr asect, asymbol **symbols) 225433965Sjdp{ 225589857Sobrien bfd_size_type count; 225633965Sjdp bfd_size_type reloc_size; 2257218822Sdim void * relocs; 225833965Sjdp arelent *reloc_cache; 225933965Sjdp size_t each_size; 226033965Sjdp unsigned int counter = 0; 226133965Sjdp arelent *cache_ptr; 226289857Sobrien bfd_size_type amt; 226333965Sjdp 226433965Sjdp if (asect->relocation) 2265130561Sobrien return TRUE; 226633965Sjdp 226733965Sjdp if (asect->flags & SEC_CONSTRUCTOR) 2268130561Sobrien return TRUE; 226933965Sjdp 227033965Sjdp if (asect == obj_datasec (abfd)) 227189857Sobrien reloc_size = exec_hdr (abfd)->a_drsize; 227233965Sjdp else if (asect == obj_textsec (abfd)) 227389857Sobrien reloc_size = exec_hdr (abfd)->a_trsize; 227433965Sjdp else if (asect == obj_bsssec (abfd)) 227533965Sjdp reloc_size = 0; 227633965Sjdp else 227733965Sjdp { 227833965Sjdp bfd_set_error (bfd_error_invalid_operation); 2279130561Sobrien return FALSE; 228033965Sjdp } 228133965Sjdp 228233965Sjdp if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) 2283130561Sobrien return FALSE; 228433965Sjdp 228533965Sjdp each_size = obj_reloc_entry_size (abfd); 228633965Sjdp 228733965Sjdp count = reloc_size / each_size; 228833965Sjdp 228989857Sobrien amt = count * sizeof (arelent); 2290218822Sdim reloc_cache = bfd_zmalloc (amt); 229133965Sjdp if (reloc_cache == NULL && count != 0) 2292130561Sobrien return FALSE; 229333965Sjdp 229489857Sobrien relocs = bfd_malloc (reloc_size); 229533965Sjdp if (relocs == NULL && reloc_size != 0) 229633965Sjdp { 229733965Sjdp free (reloc_cache); 2298130561Sobrien return FALSE; 229933965Sjdp } 230033965Sjdp 230189857Sobrien if (bfd_bread (relocs, reloc_size, abfd) != reloc_size) 230233965Sjdp { 230333965Sjdp free (relocs); 230433965Sjdp free (reloc_cache); 2305130561Sobrien return FALSE; 230633965Sjdp } 230733965Sjdp 230833965Sjdp cache_ptr = reloc_cache; 230933965Sjdp if (each_size == RELOC_EXT_SIZE) 231033965Sjdp { 231189857Sobrien struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs; 231233965Sjdp 231333965Sjdp for (; counter < count; counter++, rptr++, cache_ptr++) 231477298Sobrien MY_swap_ext_reloc_in (abfd, rptr, cache_ptr, symbols, 231589857Sobrien (bfd_size_type) bfd_get_symcount (abfd)); 231633965Sjdp } 231733965Sjdp else 231833965Sjdp { 231989857Sobrien struct reloc_std_external *rptr = (struct reloc_std_external *) relocs; 232033965Sjdp 232133965Sjdp for (; counter < count; counter++, rptr++, cache_ptr++) 232233965Sjdp MY_swap_std_reloc_in (abfd, rptr, cache_ptr, symbols, 232389857Sobrien (bfd_size_type) bfd_get_symcount (abfd)); 232433965Sjdp } 232533965Sjdp 232633965Sjdp free (relocs); 232733965Sjdp 232833965Sjdp asect->relocation = reloc_cache; 232933965Sjdp asect->reloc_count = cache_ptr - reloc_cache; 233033965Sjdp 2331130561Sobrien return TRUE; 233233965Sjdp} 233333965Sjdp 233433965Sjdp/* Write out a relocation section into an object file. */ 233533965Sjdp 2336130561Sobrienbfd_boolean 2337218822SdimNAME (aout, squirt_out_relocs) (bfd *abfd, asection *section) 233833965Sjdp{ 233933965Sjdp arelent **generic; 234033965Sjdp unsigned char *native, *natptr; 234133965Sjdp size_t each_size; 234233965Sjdp 234333965Sjdp unsigned int count = section->reloc_count; 234489857Sobrien bfd_size_type natsize; 234533965Sjdp 234633965Sjdp if (count == 0 || section->orelocation == NULL) 2347130561Sobrien return TRUE; 234833965Sjdp 234933965Sjdp each_size = obj_reloc_entry_size (abfd); 235089857Sobrien natsize = (bfd_size_type) each_size * count; 2351218822Sdim native = bfd_zalloc (abfd, natsize); 235233965Sjdp if (!native) 2353130561Sobrien return FALSE; 235433965Sjdp 235533965Sjdp generic = section->orelocation; 235633965Sjdp 235733965Sjdp if (each_size == RELOC_EXT_SIZE) 235833965Sjdp { 235933965Sjdp for (natptr = native; 236033965Sjdp count != 0; 236133965Sjdp --count, natptr += each_size, ++generic) 236277298Sobrien MY_swap_ext_reloc_out (abfd, *generic, 236377298Sobrien (struct reloc_ext_external *) natptr); 236433965Sjdp } 236533965Sjdp else 236633965Sjdp { 236733965Sjdp for (natptr = native; 236833965Sjdp count != 0; 236933965Sjdp --count, natptr += each_size, ++generic) 237089857Sobrien MY_swap_std_reloc_out (abfd, *generic, 237189857Sobrien (struct reloc_std_external *) natptr); 237233965Sjdp } 237333965Sjdp 2374218822Sdim if (bfd_bwrite ((void *) native, natsize, abfd) != natsize) 237589857Sobrien { 237689857Sobrien bfd_release (abfd, native); 2377130561Sobrien return FALSE; 237889857Sobrien } 237933965Sjdp bfd_release (abfd, native); 238033965Sjdp 2381130561Sobrien return TRUE; 238233965Sjdp} 238333965Sjdp 2384130561Sobrien/* This is stupid. This function should be a boolean predicate. */ 2385130561Sobrien 238633965Sjdplong 2387218822SdimNAME (aout, canonicalize_reloc) (bfd *abfd, 2388218822Sdim sec_ptr section, 2389218822Sdim arelent **relptr, 2390218822Sdim asymbol **symbols) 239133965Sjdp{ 239233965Sjdp arelent *tblptr = section->relocation; 239333965Sjdp unsigned int count; 239433965Sjdp 239533965Sjdp if (section == obj_bsssec (abfd)) 239633965Sjdp { 239733965Sjdp *relptr = NULL; 239833965Sjdp return 0; 239933965Sjdp } 240033965Sjdp 2401218822Sdim if (!(tblptr || NAME (aout, slurp_reloc_table) (abfd, section, symbols))) 240233965Sjdp return -1; 240333965Sjdp 240489857Sobrien if (section->flags & SEC_CONSTRUCTOR) 240589857Sobrien { 240689857Sobrien arelent_chain *chain = section->constructor_chain; 240789857Sobrien for (count = 0; count < section->reloc_count; count ++) 240889857Sobrien { 240989857Sobrien *relptr ++ = &chain->relent; 241089857Sobrien chain = chain->next; 241189857Sobrien } 241233965Sjdp } 241389857Sobrien else 241489857Sobrien { 241589857Sobrien tblptr = section->relocation; 241633965Sjdp 241789857Sobrien for (count = 0; count++ < section->reloc_count; ) 241889857Sobrien { 241989857Sobrien *relptr++ = tblptr++; 242089857Sobrien } 242189857Sobrien } 242233965Sjdp *relptr = 0; 242333965Sjdp 242433965Sjdp return section->reloc_count; 242533965Sjdp} 242633965Sjdp 242733965Sjdplong 2428218822SdimNAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect) 242933965Sjdp{ 243089857Sobrien if (bfd_get_format (abfd) != bfd_object) 243189857Sobrien { 243289857Sobrien bfd_set_error (bfd_error_invalid_operation); 243389857Sobrien return -1; 243489857Sobrien } 2435130561Sobrien 243689857Sobrien if (asect->flags & SEC_CONSTRUCTOR) 2437218822Sdim return sizeof (arelent *) * (asect->reloc_count + 1); 243833965Sjdp 243933965Sjdp if (asect == obj_datasec (abfd)) 2440218822Sdim return sizeof (arelent *) 2441218822Sdim * ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd)) 2442218822Sdim + 1); 244333965Sjdp 244433965Sjdp if (asect == obj_textsec (abfd)) 2445218822Sdim return sizeof (arelent *) 2446218822Sdim * ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd)) 2447218822Sdim + 1); 244833965Sjdp 244933965Sjdp if (asect == obj_bsssec (abfd)) 245033965Sjdp return sizeof (arelent *); 245133965Sjdp 245233965Sjdp if (asect == obj_bsssec (abfd)) 245333965Sjdp return 0; 245433965Sjdp 245533965Sjdp bfd_set_error (bfd_error_invalid_operation); 245633965Sjdp return -1; 245733965Sjdp} 245833965Sjdp 245933965Sjdplong 2460218822SdimNAME (aout, get_symtab_upper_bound) (bfd *abfd) 246133965Sjdp{ 2462218822Sdim if (!NAME (aout, slurp_symbol_table) (abfd)) 246333965Sjdp return -1; 246433965Sjdp 246533965Sjdp return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *)); 246633965Sjdp} 246733965Sjdp 246889857Sobrienalent * 2469218822SdimNAME (aout, get_lineno) (bfd *ignore_abfd ATTRIBUTE_UNUSED, 2470218822Sdim asymbol *ignore_symbol ATTRIBUTE_UNUSED) 247133965Sjdp{ 2472218822Sdim return NULL; 247333965Sjdp} 247433965Sjdp 247533965Sjdpvoid 2476218822SdimNAME (aout, get_symbol_info) (bfd *ignore_abfd ATTRIBUTE_UNUSED, 2477218822Sdim asymbol *symbol, 2478218822Sdim symbol_info *ret) 247933965Sjdp{ 248033965Sjdp bfd_symbol_info (symbol, ret); 248133965Sjdp 248233965Sjdp if (ret->type == '?') 248333965Sjdp { 248489857Sobrien int type_code = aout_symbol (symbol)->type & 0xff; 248533965Sjdp const char *stab_name = bfd_get_stab_name (type_code); 248633965Sjdp static char buf[10]; 248733965Sjdp 248833965Sjdp if (stab_name == NULL) 248933965Sjdp { 249077298Sobrien sprintf (buf, "(%d)", type_code); 249133965Sjdp stab_name = buf; 249233965Sjdp } 249333965Sjdp ret->type = '-'; 249433965Sjdp ret->stab_type = type_code; 249589857Sobrien ret->stab_other = (unsigned) (aout_symbol (symbol)->other & 0xff); 249689857Sobrien ret->stab_desc = (unsigned) (aout_symbol (symbol)->desc & 0xffff); 249733965Sjdp ret->stab_name = stab_name; 249833965Sjdp } 249933965Sjdp} 250033965Sjdp 250133965Sjdpvoid 2502218822SdimNAME (aout, print_symbol) (bfd *abfd, 2503218822Sdim void * afile, 2504218822Sdim asymbol *symbol, 2505218822Sdim bfd_print_symbol_type how) 250633965Sjdp{ 250733965Sjdp FILE *file = (FILE *)afile; 250833965Sjdp 250989857Sobrien switch (how) 251033965Sjdp { 251189857Sobrien case bfd_print_symbol_name: 251289857Sobrien if (symbol->name) 251389857Sobrien fprintf (file,"%s", symbol->name); 251489857Sobrien break; 251589857Sobrien case bfd_print_symbol_more: 251689857Sobrien fprintf (file,"%4x %2x %2x", 251789857Sobrien (unsigned) (aout_symbol (symbol)->desc & 0xffff), 251889857Sobrien (unsigned) (aout_symbol (symbol)->other & 0xff), 251989857Sobrien (unsigned) (aout_symbol (symbol)->type)); 252089857Sobrien break; 252189857Sobrien case bfd_print_symbol_all: 252289857Sobrien { 252389857Sobrien const char *section_name = symbol->section->name; 252433965Sjdp 2525218822Sdim bfd_print_symbol_vandf (abfd, (void *)file, symbol); 252633965Sjdp 252789857Sobrien fprintf (file," %-5s %04x %02x %02x", 252889857Sobrien section_name, 252989857Sobrien (unsigned) (aout_symbol (symbol)->desc & 0xffff), 253089857Sobrien (unsigned) (aout_symbol (symbol)->other & 0xff), 253189857Sobrien (unsigned) (aout_symbol (symbol)->type & 0xff)); 253289857Sobrien if (symbol->name) 253389857Sobrien fprintf (file," %s", symbol->name); 253489857Sobrien } 253589857Sobrien break; 253633965Sjdp } 253733965Sjdp} 253833965Sjdp 253933965Sjdp/* If we don't have to allocate more than 1MB to hold the generic 254033965Sjdp symbols, we use the generic minisymbol methord: it's faster, since 254133965Sjdp it only translates the symbols once, not multiple times. */ 254233965Sjdp#define MINISYM_THRESHOLD (1000000 / sizeof (asymbol)) 254333965Sjdp 254433965Sjdp/* Read minisymbols. For minisymbols, we use the unmodified a.out 254533965Sjdp symbols. The minisymbol_to_symbol function translates these into 254633965Sjdp BFD asymbol structures. */ 254733965Sjdp 254833965Sjdplong 2549218822SdimNAME (aout, read_minisymbols) (bfd *abfd, 2550218822Sdim bfd_boolean dynamic, 2551218822Sdim void * *minisymsp, 2552218822Sdim unsigned int *sizep) 255333965Sjdp{ 255433965Sjdp if (dynamic) 2555218822Sdim /* We could handle the dynamic symbols here as well, but it's 2556218822Sdim easier to hand them off. */ 2557218822Sdim return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); 255833965Sjdp 255933965Sjdp if (! aout_get_external_symbols (abfd)) 256033965Sjdp return -1; 256133965Sjdp 256233965Sjdp if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD) 256333965Sjdp return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); 256433965Sjdp 2565218822Sdim *minisymsp = (void *) obj_aout_external_syms (abfd); 256633965Sjdp 256733965Sjdp /* By passing the external symbols back from this routine, we are 256833965Sjdp giving up control over the memory block. Clear 256933965Sjdp obj_aout_external_syms, so that we do not try to free it 257033965Sjdp ourselves. */ 257133965Sjdp obj_aout_external_syms (abfd) = NULL; 257233965Sjdp 257333965Sjdp *sizep = EXTERNAL_NLIST_SIZE; 257433965Sjdp return obj_aout_external_sym_count (abfd); 257533965Sjdp} 257633965Sjdp 257733965Sjdp/* Convert a minisymbol to a BFD asymbol. A minisymbol is just an 257833965Sjdp unmodified a.out symbol. The SYM argument is a structure returned 257933965Sjdp by bfd_make_empty_symbol, which we fill in here. */ 258033965Sjdp 258133965Sjdpasymbol * 2582218822SdimNAME (aout, minisymbol_to_symbol) (bfd *abfd, 2583218822Sdim bfd_boolean dynamic, 2584218822Sdim const void * minisym, 2585218822Sdim asymbol *sym) 258633965Sjdp{ 258733965Sjdp if (dynamic 258833965Sjdp || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD) 258933965Sjdp return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym); 259033965Sjdp 259133965Sjdp memset (sym, 0, sizeof (aout_symbol_type)); 259233965Sjdp 259333965Sjdp /* We call translate_symbol_table to translate a single symbol. */ 2594218822Sdim if (! (NAME (aout, translate_symbol_table) 259533965Sjdp (abfd, 259633965Sjdp (aout_symbol_type *) sym, 259733965Sjdp (struct external_nlist *) minisym, 259833965Sjdp (bfd_size_type) 1, 259933965Sjdp obj_aout_external_strings (abfd), 260033965Sjdp obj_aout_external_string_size (abfd), 2601130561Sobrien FALSE))) 260233965Sjdp return NULL; 260333965Sjdp 260433965Sjdp return sym; 260533965Sjdp} 260633965Sjdp 2607130561Sobrien/* Provided a BFD, a section and an offset into the section, calculate 2608130561Sobrien and return the name of the source file and the line nearest to the 2609130561Sobrien wanted location. */ 261033965Sjdp 2611130561Sobrienbfd_boolean 2612218822SdimNAME (aout, find_nearest_line) (bfd *abfd, 2613218822Sdim asection *section, 2614218822Sdim asymbol **symbols, 2615218822Sdim bfd_vma offset, 2616218822Sdim const char **filename_ptr, 2617218822Sdim const char **functionname_ptr, 2618218822Sdim unsigned int *line_ptr) 261933965Sjdp{ 2620130561Sobrien /* Run down the file looking for the filename, function and linenumber. */ 262133965Sjdp asymbol **p; 262289857Sobrien const char *directory_name = NULL; 262389857Sobrien const char *main_file_name = NULL; 262489857Sobrien const char *current_file_name = NULL; 2625218822Sdim const char *line_file_name = NULL; /* Value of current_file_name at line number. */ 262689857Sobrien const char *line_directory_name = NULL; /* Value of directory_name at line number. */ 262733965Sjdp bfd_vma low_line_vma = 0; 262833965Sjdp bfd_vma low_func_vma = 0; 262933965Sjdp asymbol *func = 0; 263089857Sobrien bfd_size_type filelen, funclen; 263133965Sjdp char *buf; 263233965Sjdp 263333965Sjdp *filename_ptr = abfd->filename; 263433965Sjdp *functionname_ptr = 0; 263533965Sjdp *line_ptr = 0; 2636130561Sobrien 2637218822Sdim if (symbols != NULL) 263889857Sobrien { 263989857Sobrien for (p = symbols; *p; p++) 264089857Sobrien { 264189857Sobrien aout_symbol_type *q = (aout_symbol_type *) (*p); 264289857Sobrien next: 264389857Sobrien switch (q->type) 264489857Sobrien { 264589857Sobrien case N_TEXT: 264689857Sobrien /* If this looks like a file name symbol, and it comes after 264789857Sobrien the line number we have found so far, but before the 264889857Sobrien offset, then we have probably not found the right line 264989857Sobrien number. */ 265089857Sobrien if (q->symbol.value <= offset 265189857Sobrien && ((q->symbol.value > low_line_vma 265289857Sobrien && (line_file_name != NULL 265389857Sobrien || *line_ptr != 0)) 265489857Sobrien || (q->symbol.value > low_func_vma 265589857Sobrien && func != NULL))) 265689857Sobrien { 265789857Sobrien const char *symname; 265833965Sjdp 265989857Sobrien symname = q->symbol.name; 266089857Sobrien if (strcmp (symname + strlen (symname) - 2, ".o") == 0) 266189857Sobrien { 266289857Sobrien if (q->symbol.value > low_line_vma) 266389857Sobrien { 266489857Sobrien *line_ptr = 0; 266589857Sobrien line_file_name = NULL; 266689857Sobrien } 266789857Sobrien if (q->symbol.value > low_func_vma) 266889857Sobrien func = NULL; 266989857Sobrien } 267089857Sobrien } 267189857Sobrien break; 267233965Sjdp 267389857Sobrien case N_SO: 267489857Sobrien /* If this symbol is less than the offset, but greater than 267589857Sobrien the line number we have found so far, then we have not 267689857Sobrien found the right line number. */ 267789857Sobrien if (q->symbol.value <= offset) 267889857Sobrien { 267989857Sobrien if (q->symbol.value > low_line_vma) 268089857Sobrien { 268189857Sobrien *line_ptr = 0; 268289857Sobrien line_file_name = NULL; 268389857Sobrien } 268489857Sobrien if (q->symbol.value > low_func_vma) 268589857Sobrien func = NULL; 268689857Sobrien } 268733965Sjdp 268889857Sobrien main_file_name = current_file_name = q->symbol.name; 268989857Sobrien /* Look ahead to next symbol to check if that too is an N_SO. */ 269089857Sobrien p++; 269189857Sobrien if (*p == NULL) 2692218822Sdim goto done; 269389857Sobrien q = (aout_symbol_type *) (*p); 269489857Sobrien if (q->type != (int)N_SO) 269589857Sobrien goto next; 269633965Sjdp 269789857Sobrien /* Found a second N_SO First is directory; second is filename. */ 269889857Sobrien directory_name = current_file_name; 269989857Sobrien main_file_name = current_file_name = q->symbol.name; 270089857Sobrien if (obj_textsec (abfd) != section) 270189857Sobrien goto done; 270289857Sobrien break; 270389857Sobrien case N_SOL: 270489857Sobrien current_file_name = q->symbol.name; 270589857Sobrien break; 270633965Sjdp 270789857Sobrien case N_SLINE: 270833965Sjdp 270989857Sobrien case N_DSLINE: 271089857Sobrien case N_BSLINE: 271189857Sobrien /* We'll keep this if it resolves nearer than the one we have 271289857Sobrien already. */ 271389857Sobrien if (q->symbol.value >= low_line_vma 271489857Sobrien && q->symbol.value <= offset) 271589857Sobrien { 271689857Sobrien *line_ptr = q->desc; 271789857Sobrien low_line_vma = q->symbol.value; 271889857Sobrien line_file_name = current_file_name; 271989857Sobrien line_directory_name = directory_name; 272089857Sobrien } 272189857Sobrien break; 272289857Sobrien case N_FUN: 272389857Sobrien { 2724130561Sobrien /* We'll keep this if it is nearer than the one we have already. */ 272589857Sobrien if (q->symbol.value >= low_func_vma && 2726130561Sobrien q->symbol.value <= offset) 2727130561Sobrien { 2728130561Sobrien low_func_vma = q->symbol.value; 2729130561Sobrien func = (asymbol *)q; 2730130561Sobrien } 273189857Sobrien else if (q->symbol.value > offset) 273289857Sobrien goto done; 273389857Sobrien } 273489857Sobrien break; 273589857Sobrien } 273633965Sjdp } 273733965Sjdp } 273833965Sjdp 273933965Sjdp done: 274033965Sjdp if (*line_ptr != 0) 274160484Sobrien { 274260484Sobrien main_file_name = line_file_name; 274360484Sobrien directory_name = line_directory_name; 274460484Sobrien } 274533965Sjdp 274633965Sjdp if (main_file_name == NULL 274761843Sobrien || IS_ABSOLUTE_PATH (main_file_name) 274833965Sjdp || directory_name == NULL) 274933965Sjdp filelen = 0; 275033965Sjdp else 275133965Sjdp filelen = strlen (directory_name) + strlen (main_file_name); 2752130561Sobrien 275333965Sjdp if (func == NULL) 275433965Sjdp funclen = 0; 275533965Sjdp else 275633965Sjdp funclen = strlen (bfd_asymbol_name (func)); 275733965Sjdp 275833965Sjdp if (adata (abfd).line_buf != NULL) 275933965Sjdp free (adata (abfd).line_buf); 2760130561Sobrien 276133965Sjdp if (filelen + funclen == 0) 276233965Sjdp adata (abfd).line_buf = buf = NULL; 276333965Sjdp else 276433965Sjdp { 2765218822Sdim buf = bfd_malloc (filelen + funclen + 3); 276633965Sjdp adata (abfd).line_buf = buf; 276733965Sjdp if (buf == NULL) 2768130561Sobrien return FALSE; 276933965Sjdp } 277033965Sjdp 277133965Sjdp if (main_file_name != NULL) 277233965Sjdp { 277361843Sobrien if (IS_ABSOLUTE_PATH (main_file_name) || directory_name == NULL) 277433965Sjdp *filename_ptr = main_file_name; 277533965Sjdp else 277633965Sjdp { 277733965Sjdp sprintf (buf, "%s%s", directory_name, main_file_name); 277833965Sjdp *filename_ptr = buf; 277933965Sjdp buf += filelen + 1; 278033965Sjdp } 278133965Sjdp } 278233965Sjdp 278333965Sjdp if (func) 278433965Sjdp { 278533965Sjdp const char *function = func->name; 278689857Sobrien char *colon; 278733965Sjdp 278833965Sjdp /* The caller expects a symbol name. We actually have a 278933965Sjdp function name, without the leading underscore. Put the 279033965Sjdp underscore back in, so that the caller gets a symbol name. */ 279133965Sjdp if (bfd_get_symbol_leading_char (abfd) == '\0') 279233965Sjdp strcpy (buf, function); 279333965Sjdp else 279433965Sjdp { 279533965Sjdp buf[0] = bfd_get_symbol_leading_char (abfd); 279633965Sjdp strcpy (buf + 1, function); 279733965Sjdp } 2798130561Sobrien /* Have to remove : stuff. */ 279989857Sobrien colon = strchr (buf, ':'); 280089857Sobrien if (colon != NULL) 280189857Sobrien *colon = '\0'; 280233965Sjdp *functionname_ptr = buf; 280333965Sjdp } 280433965Sjdp 2805130561Sobrien return TRUE; 280633965Sjdp} 280733965Sjdp 280833965Sjdpint 2809218822SdimNAME (aout, sizeof_headers) (bfd *abfd, 2810218822Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 281133965Sjdp{ 281289857Sobrien return adata (abfd).exec_bytes_size; 281333965Sjdp} 281433965Sjdp 281533965Sjdp/* Free all information we have cached for this BFD. We can always 281633965Sjdp read it again later if we need it. */ 281733965Sjdp 2818130561Sobrienbfd_boolean 2819218822SdimNAME (aout, bfd_free_cached_info) (bfd *abfd) 282033965Sjdp{ 282133965Sjdp asection *o; 282233965Sjdp 282378828Sobrien if (bfd_get_format (abfd) != bfd_object 282478828Sobrien || abfd->tdata.aout_data == NULL) 2825130561Sobrien return TRUE; 282633965Sjdp 282733965Sjdp#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; } 282833965Sjdp BFCI_FREE (obj_aout_symbols (abfd)); 282933965Sjdp#ifdef USE_MMAP 283033965Sjdp obj_aout_external_syms (abfd) = 0; 283133965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 283233965Sjdp bfd_free_window (&obj_aout_string_window (abfd)); 283333965Sjdp obj_aout_external_strings (abfd) = 0; 283433965Sjdp#else 283533965Sjdp BFCI_FREE (obj_aout_external_syms (abfd)); 283633965Sjdp BFCI_FREE (obj_aout_external_strings (abfd)); 283733965Sjdp#endif 2838218822Sdim for (o = abfd->sections; o != NULL; o = o->next) 283933965Sjdp BFCI_FREE (o->relocation); 284033965Sjdp#undef BFCI_FREE 284133965Sjdp 2842130561Sobrien return TRUE; 284333965Sjdp} 284433965Sjdp 284533965Sjdp/* a.out link code. */ 284633965Sjdp 284733965Sjdp/* Routine to create an entry in an a.out link hash table. */ 284833965Sjdp 284933965Sjdpstruct bfd_hash_entry * 2850218822SdimNAME (aout, link_hash_newfunc) (struct bfd_hash_entry *entry, 2851218822Sdim struct bfd_hash_table *table, 2852218822Sdim const char *string) 285333965Sjdp{ 285433965Sjdp struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry; 285533965Sjdp 285633965Sjdp /* Allocate the structure if it has not already been allocated by a 285733965Sjdp subclass. */ 2858218822Sdim if (ret == NULL) 2859218822Sdim ret = bfd_hash_allocate (table, sizeof (* ret)); 2860218822Sdim if (ret == NULL) 2861218822Sdim return NULL; 286233965Sjdp 286333965Sjdp /* Call the allocation method of the superclass. */ 286433965Sjdp ret = ((struct aout_link_hash_entry *) 286533965Sjdp _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, 286633965Sjdp table, string)); 286733965Sjdp if (ret) 286833965Sjdp { 286933965Sjdp /* Set local fields. */ 2870130561Sobrien ret->written = FALSE; 287133965Sjdp ret->indx = -1; 287233965Sjdp } 287333965Sjdp 287433965Sjdp return (struct bfd_hash_entry *) ret; 287533965Sjdp} 287633965Sjdp 287733965Sjdp/* Initialize an a.out link hash table. */ 287833965Sjdp 2879130561Sobrienbfd_boolean 2880218822SdimNAME (aout, link_hash_table_init) (struct aout_link_hash_table *table, 2881218822Sdim bfd *abfd, 2882218822Sdim struct bfd_hash_entry *(*newfunc) 2883218822Sdim (struct bfd_hash_entry *, struct bfd_hash_table *, 2884218822Sdim const char *), 2885218822Sdim unsigned int entsize) 288633965Sjdp{ 2887218822Sdim return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize); 288833965Sjdp} 288933965Sjdp 289033965Sjdp/* Create an a.out link hash table. */ 289133965Sjdp 289233965Sjdpstruct bfd_link_hash_table * 2893218822SdimNAME (aout, link_hash_table_create) (bfd *abfd) 289433965Sjdp{ 289533965Sjdp struct aout_link_hash_table *ret; 2896218822Sdim bfd_size_type amt = sizeof (* ret); 289733965Sjdp 2898218822Sdim ret = bfd_malloc (amt); 289933965Sjdp if (ret == NULL) 2900218822Sdim return NULL; 2901130561Sobrien 2902218822Sdim if (!NAME (aout, link_hash_table_init) (ret, abfd, 2903218822Sdim NAME (aout, link_hash_newfunc), 2904218822Sdim sizeof (struct aout_link_hash_entry))) 290533965Sjdp { 290633965Sjdp free (ret); 2907218822Sdim return NULL; 290833965Sjdp } 290933965Sjdp return &ret->root; 291033965Sjdp} 291133965Sjdp 2912218822Sdim/* Add all symbols from an object file to the hash table. */ 291333965Sjdp 2914218822Sdimstatic bfd_boolean 2915218822Sdimaout_link_add_symbols (bfd *abfd, struct bfd_link_info *info) 291633965Sjdp{ 2917218822Sdim bfd_boolean (*add_one_symbol) 2918218822Sdim (struct bfd_link_info *, bfd *, const char *, flagword, asection *, 2919218822Sdim bfd_vma, const char *, bfd_boolean, bfd_boolean, 2920218822Sdim struct bfd_link_hash_entry **); 2921218822Sdim struct external_nlist *syms; 2922218822Sdim bfd_size_type sym_count; 2923218822Sdim char *strings; 2924218822Sdim bfd_boolean copy; 2925218822Sdim struct aout_link_hash_entry **sym_hash; 2926218822Sdim struct external_nlist *p; 2927218822Sdim struct external_nlist *pend; 2928218822Sdim bfd_size_type amt; 292933965Sjdp 2930218822Sdim syms = obj_aout_external_syms (abfd); 2931218822Sdim sym_count = obj_aout_external_sym_count (abfd); 2932218822Sdim strings = obj_aout_external_strings (abfd); 2933218822Sdim if (info->keep_memory) 2934218822Sdim copy = FALSE; 2935218822Sdim else 2936218822Sdim copy = TRUE; 293733965Sjdp 2938218822Sdim if (aout_backend_info (abfd)->add_dynamic_symbols != NULL) 293933965Sjdp { 2940218822Sdim if (! ((*aout_backend_info (abfd)->add_dynamic_symbols) 2941218822Sdim (abfd, info, &syms, &sym_count, &strings))) 2942130561Sobrien return FALSE; 294333965Sjdp } 294433965Sjdp 2945218822Sdim /* We keep a list of the linker hash table entries that correspond 2946218822Sdim to particular symbols. We could just look them up in the hash 2947218822Sdim table, but keeping the list is more efficient. Perhaps this 2948218822Sdim should be conditional on info->keep_memory. */ 2949218822Sdim amt = sym_count * sizeof (struct aout_link_hash_entry *); 2950218822Sdim sym_hash = bfd_alloc (abfd, amt); 2951218822Sdim if (sym_hash == NULL && sym_count != 0) 2952130561Sobrien return FALSE; 2953218822Sdim obj_aout_sym_hashes (abfd) = sym_hash; 295433965Sjdp 2955218822Sdim add_one_symbol = aout_backend_info (abfd)->add_one_symbol; 2956218822Sdim if (add_one_symbol == NULL) 2957218822Sdim add_one_symbol = _bfd_generic_link_add_one_symbol; 295833965Sjdp 2959218822Sdim p = syms; 2960218822Sdim pend = p + sym_count; 2961218822Sdim for (; p < pend; p++, sym_hash++) 296233965Sjdp { 2963218822Sdim int type; 2964218822Sdim const char *name; 2965218822Sdim bfd_vma value; 2966218822Sdim asection *section; 2967218822Sdim flagword flags; 2968218822Sdim const char *string; 2969218822Sdim 2970218822Sdim *sym_hash = NULL; 2971218822Sdim 2972218822Sdim type = H_GET_8 (abfd, p->e_type); 2973218822Sdim 2974218822Sdim /* Ignore debugging symbols. */ 2975218822Sdim if ((type & N_STAB) != 0) 2976218822Sdim continue; 2977218822Sdim 2978218822Sdim name = strings + GET_WORD (abfd, p->e_strx); 2979218822Sdim value = GET_WORD (abfd, p->e_value); 2980218822Sdim flags = BSF_GLOBAL; 2981218822Sdim string = NULL; 2982218822Sdim switch (type) 2983218822Sdim { 2984218822Sdim default: 2985218822Sdim abort (); 2986218822Sdim 2987218822Sdim case N_UNDF: 2988218822Sdim case N_ABS: 2989218822Sdim case N_TEXT: 2990218822Sdim case N_DATA: 2991218822Sdim case N_BSS: 2992218822Sdim case N_FN_SEQ: 2993218822Sdim case N_COMM: 2994218822Sdim case N_SETV: 2995218822Sdim case N_FN: 2996218822Sdim /* Ignore symbols that are not externally visible. */ 2997218822Sdim continue; 2998218822Sdim case N_INDR: 2999218822Sdim /* Ignore local indirect symbol. */ 3000218822Sdim ++p; 3001218822Sdim ++sym_hash; 3002218822Sdim continue; 3003218822Sdim 3004218822Sdim case N_UNDF | N_EXT: 3005218822Sdim if (value == 0) 3006218822Sdim { 3007218822Sdim section = bfd_und_section_ptr; 3008218822Sdim flags = 0; 3009218822Sdim } 3010218822Sdim else 3011218822Sdim section = bfd_com_section_ptr; 3012218822Sdim break; 3013218822Sdim case N_ABS | N_EXT: 3014218822Sdim section = bfd_abs_section_ptr; 3015218822Sdim break; 3016218822Sdim case N_TEXT | N_EXT: 3017218822Sdim section = obj_textsec (abfd); 3018218822Sdim value -= bfd_get_section_vma (abfd, section); 3019218822Sdim break; 3020218822Sdim case N_DATA | N_EXT: 3021218822Sdim case N_SETV | N_EXT: 3022218822Sdim /* Treat N_SETV symbols as N_DATA symbol; see comment in 3023218822Sdim translate_from_native_sym_flags. */ 3024218822Sdim section = obj_datasec (abfd); 3025218822Sdim value -= bfd_get_section_vma (abfd, section); 3026218822Sdim break; 3027218822Sdim case N_BSS | N_EXT: 3028218822Sdim section = obj_bsssec (abfd); 3029218822Sdim value -= bfd_get_section_vma (abfd, section); 3030218822Sdim break; 3031218822Sdim case N_INDR | N_EXT: 3032218822Sdim /* An indirect symbol. The next symbol is the symbol 3033218822Sdim which this one really is. */ 3034218822Sdim BFD_ASSERT (p + 1 < pend); 3035218822Sdim ++p; 3036218822Sdim string = strings + GET_WORD (abfd, p->e_strx); 3037218822Sdim section = bfd_ind_section_ptr; 3038218822Sdim flags |= BSF_INDIRECT; 3039218822Sdim break; 3040218822Sdim case N_COMM | N_EXT: 3041218822Sdim section = bfd_com_section_ptr; 3042218822Sdim break; 3043218822Sdim case N_SETA: case N_SETA | N_EXT: 3044218822Sdim section = bfd_abs_section_ptr; 3045218822Sdim flags |= BSF_CONSTRUCTOR; 3046218822Sdim break; 3047218822Sdim case N_SETT: case N_SETT | N_EXT: 3048218822Sdim section = obj_textsec (abfd); 3049218822Sdim flags |= BSF_CONSTRUCTOR; 3050218822Sdim value -= bfd_get_section_vma (abfd, section); 3051218822Sdim break; 3052218822Sdim case N_SETD: case N_SETD | N_EXT: 3053218822Sdim section = obj_datasec (abfd); 3054218822Sdim flags |= BSF_CONSTRUCTOR; 3055218822Sdim value -= bfd_get_section_vma (abfd, section); 3056218822Sdim break; 3057218822Sdim case N_SETB: case N_SETB | N_EXT: 3058218822Sdim section = obj_bsssec (abfd); 3059218822Sdim flags |= BSF_CONSTRUCTOR; 3060218822Sdim value -= bfd_get_section_vma (abfd, section); 3061218822Sdim break; 3062218822Sdim case N_WARNING: 3063218822Sdim /* A warning symbol. The next symbol is the one to warn 3064218822Sdim about. If there is no next symbol, just look away. */ 3065218822Sdim if (p + 1 >= pend) 3066218822Sdim return TRUE; 3067218822Sdim ++p; 3068218822Sdim string = name; 3069218822Sdim name = strings + GET_WORD (abfd, p->e_strx); 3070218822Sdim section = bfd_und_section_ptr; 3071218822Sdim flags |= BSF_WARNING; 3072218822Sdim break; 3073218822Sdim case N_WEAKU: 3074218822Sdim section = bfd_und_section_ptr; 3075218822Sdim flags = BSF_WEAK; 3076218822Sdim break; 3077218822Sdim case N_WEAKA: 3078218822Sdim section = bfd_abs_section_ptr; 3079218822Sdim flags = BSF_WEAK; 3080218822Sdim break; 3081218822Sdim case N_WEAKT: 3082218822Sdim section = obj_textsec (abfd); 3083218822Sdim value -= bfd_get_section_vma (abfd, section); 3084218822Sdim flags = BSF_WEAK; 3085218822Sdim break; 3086218822Sdim case N_WEAKD: 3087218822Sdim section = obj_datasec (abfd); 3088218822Sdim value -= bfd_get_section_vma (abfd, section); 3089218822Sdim flags = BSF_WEAK; 3090218822Sdim break; 3091218822Sdim case N_WEAKB: 3092218822Sdim section = obj_bsssec (abfd); 3093218822Sdim value -= bfd_get_section_vma (abfd, section); 3094218822Sdim flags = BSF_WEAK; 3095218822Sdim break; 3096218822Sdim } 3097218822Sdim 3098218822Sdim if (! ((*add_one_symbol) 3099218822Sdim (info, abfd, name, flags, section, value, string, copy, FALSE, 3100218822Sdim (struct bfd_link_hash_entry **) sym_hash))) 3101130561Sobrien return FALSE; 310233965Sjdp 3103218822Sdim /* Restrict the maximum alignment of a common symbol based on 3104218822Sdim the architecture, since a.out has no way to represent 3105218822Sdim alignment requirements of a section in a .o file. FIXME: 3106218822Sdim This isn't quite right: it should use the architecture of the 3107218822Sdim output file, not the input files. */ 3108218822Sdim if ((*sym_hash)->root.type == bfd_link_hash_common 3109218822Sdim && ((*sym_hash)->root.u.c.p->alignment_power > 3110218822Sdim bfd_get_arch_info (abfd)->section_align_power)) 3111218822Sdim (*sym_hash)->root.u.c.p->alignment_power = 3112218822Sdim bfd_get_arch_info (abfd)->section_align_power; 3113218822Sdim 3114218822Sdim /* If this is a set symbol, and we are not building sets, then 3115218822Sdim it is possible for the hash entry to not have been set. In 3116218822Sdim such a case, treat the symbol as not globally defined. */ 3117218822Sdim if ((*sym_hash)->root.type == bfd_link_hash_new) 3118218822Sdim { 3119218822Sdim BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0); 3120218822Sdim *sym_hash = NULL; 3121218822Sdim } 3122218822Sdim 3123218822Sdim if (type == (N_INDR | N_EXT) || type == N_WARNING) 3124218822Sdim ++sym_hash; 312533965Sjdp } 312633965Sjdp 3127130561Sobrien return TRUE; 312833965Sjdp} 312933965Sjdp 313033965Sjdp/* Free up the internal symbols read from an a.out file. */ 313133965Sjdp 3132130561Sobrienstatic bfd_boolean 3133218822Sdimaout_link_free_symbols (bfd *abfd) 313433965Sjdp{ 3135218822Sdim if (obj_aout_external_syms (abfd) != NULL) 313633965Sjdp { 313733965Sjdp#ifdef USE_MMAP 313833965Sjdp bfd_free_window (&obj_aout_sym_window (abfd)); 313933965Sjdp#else 3140218822Sdim free ((void *) obj_aout_external_syms (abfd)); 314133965Sjdp#endif 3142218822Sdim obj_aout_external_syms (abfd) = NULL; 314333965Sjdp } 3144218822Sdim if (obj_aout_external_strings (abfd) != NULL) 314533965Sjdp { 314633965Sjdp#ifdef USE_MMAP 314733965Sjdp bfd_free_window (&obj_aout_string_window (abfd)); 314833965Sjdp#else 3149218822Sdim free ((void *) obj_aout_external_strings (abfd)); 315033965Sjdp#endif 3151218822Sdim obj_aout_external_strings (abfd) = NULL; 315233965Sjdp } 3153130561Sobrien return TRUE; 315433965Sjdp} 315533965Sjdp 3156218822Sdim/* Add symbols from an a.out object file. */ 3157218822Sdim 3158218822Sdimstatic bfd_boolean 3159218822Sdimaout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) 3160218822Sdim{ 3161218822Sdim if (! aout_get_external_symbols (abfd)) 3162218822Sdim return FALSE; 3163218822Sdim if (! aout_link_add_symbols (abfd, info)) 3164218822Sdim return FALSE; 3165218822Sdim if (! info->keep_memory) 3166218822Sdim { 3167218822Sdim if (! aout_link_free_symbols (abfd)) 3168218822Sdim return FALSE; 3169218822Sdim } 3170218822Sdim return TRUE; 3171218822Sdim} 3172218822Sdim 317333965Sjdp/* Look through the internal symbols to see if this object file should 317433965Sjdp be included in the link. We should include this object file if it 317533965Sjdp defines any symbols which are currently undefined. If this object 317633965Sjdp file defines a common symbol, then we may adjust the size of the 317733965Sjdp known symbol but we do not include the object file in the link 317833965Sjdp (unless there is some other reason to include it). */ 317933965Sjdp 3180130561Sobrienstatic bfd_boolean 3181218822Sdimaout_link_check_ar_symbols (bfd *abfd, 3182218822Sdim struct bfd_link_info *info, 3183218822Sdim bfd_boolean *pneeded) 318433965Sjdp{ 3185218822Sdim struct external_nlist *p; 318633965Sjdp struct external_nlist *pend; 318733965Sjdp char *strings; 318833965Sjdp 3189130561Sobrien *pneeded = FALSE; 319033965Sjdp 319133965Sjdp /* Look through all the symbols. */ 319233965Sjdp p = obj_aout_external_syms (abfd); 319333965Sjdp pend = p + obj_aout_external_sym_count (abfd); 319433965Sjdp strings = obj_aout_external_strings (abfd); 319533965Sjdp for (; p < pend; p++) 319633965Sjdp { 319789857Sobrien int type = H_GET_8 (abfd, p->e_type); 319833965Sjdp const char *name; 319933965Sjdp struct bfd_link_hash_entry *h; 320033965Sjdp 320133965Sjdp /* Ignore symbols that are not externally visible. This is an 320233965Sjdp optimization only, as we check the type more thoroughly 320333965Sjdp below. */ 320433965Sjdp if (((type & N_EXT) == 0 320533965Sjdp || (type & N_STAB) != 0 320633965Sjdp || type == N_FN) 320733965Sjdp && type != N_WEAKA 320833965Sjdp && type != N_WEAKT 320933965Sjdp && type != N_WEAKD 321033965Sjdp && type != N_WEAKB) 321133965Sjdp { 321233965Sjdp if (type == N_WARNING 321333965Sjdp || type == N_INDR) 321433965Sjdp ++p; 321533965Sjdp continue; 321633965Sjdp } 321733965Sjdp 321833965Sjdp name = strings + GET_WORD (abfd, p->e_strx); 3219130561Sobrien h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); 322033965Sjdp 322133965Sjdp /* We are only interested in symbols that are currently 322233965Sjdp undefined or common. */ 3223218822Sdim if (h == NULL 322433965Sjdp || (h->type != bfd_link_hash_undefined 322533965Sjdp && h->type != bfd_link_hash_common)) 322633965Sjdp { 322733965Sjdp if (type == (N_INDR | N_EXT)) 322833965Sjdp ++p; 322933965Sjdp continue; 323033965Sjdp } 323133965Sjdp 323233965Sjdp if (type == (N_TEXT | N_EXT) 323333965Sjdp || type == (N_DATA | N_EXT) 323433965Sjdp || type == (N_BSS | N_EXT) 323533965Sjdp || type == (N_ABS | N_EXT) 323633965Sjdp || type == (N_INDR | N_EXT)) 323733965Sjdp { 323833965Sjdp /* This object file defines this symbol. We must link it 323933965Sjdp in. This is true regardless of whether the current 3240130561Sobrien definition of the symbol is undefined or common. 3241130561Sobrien 3242130561Sobrien If the current definition is common, we have a case in 3243130561Sobrien which we have already seen an object file including: 324433965Sjdp int a; 3245130561Sobrien and this object file from the archive includes: 324633965Sjdp int a = 5; 3247130561Sobrien In such a case, whether to include this object is target 3248130561Sobrien dependant for backward compatibility. 324933965Sjdp 325033965Sjdp FIXME: The SunOS 4.1.3 linker will pull in the archive 325133965Sjdp element if the symbol is defined in the .data section, 325233965Sjdp but not if it is defined in the .text section. That 3253130561Sobrien seems a bit crazy to me, and it has not been implemented 3254130561Sobrien yet. However, it might be correct. */ 3255130561Sobrien if (h->type == bfd_link_hash_common) 3256130561Sobrien { 3257130561Sobrien int skip = 0; 3258130561Sobrien 3259130561Sobrien switch (info->common_skip_ar_aymbols) 3260130561Sobrien { 3261130561Sobrien case bfd_link_common_skip_text: 3262130561Sobrien skip = (type == (N_TEXT | N_EXT)); 3263130561Sobrien break; 3264130561Sobrien case bfd_link_common_skip_data: 3265130561Sobrien skip = (type == (N_DATA | N_EXT)); 3266130561Sobrien break; 3267130561Sobrien default: 3268130561Sobrien case bfd_link_common_skip_all: 3269130561Sobrien skip = 1; 3270130561Sobrien break; 3271130561Sobrien } 3272130561Sobrien 3273130561Sobrien if (skip) 3274130561Sobrien continue; 3275130561Sobrien } 3276130561Sobrien 327733965Sjdp if (! (*info->callbacks->add_archive_element) (info, abfd, name)) 3278130561Sobrien return FALSE; 3279130561Sobrien *pneeded = TRUE; 3280130561Sobrien return TRUE; 328133965Sjdp } 328233965Sjdp 328333965Sjdp if (type == (N_UNDF | N_EXT)) 328433965Sjdp { 328533965Sjdp bfd_vma value; 328633965Sjdp 328733965Sjdp value = GET_WORD (abfd, p->e_value); 328833965Sjdp if (value != 0) 328933965Sjdp { 329033965Sjdp /* This symbol is common in the object from the archive 329133965Sjdp file. */ 329233965Sjdp if (h->type == bfd_link_hash_undefined) 329333965Sjdp { 329433965Sjdp bfd *symbfd; 329533965Sjdp unsigned int power; 329633965Sjdp 329733965Sjdp symbfd = h->u.undef.abfd; 3298218822Sdim if (symbfd == NULL) 329933965Sjdp { 330033965Sjdp /* This symbol was created as undefined from 330133965Sjdp outside BFD. We assume that we should link 330233965Sjdp in the object file. This is done for the -u 330333965Sjdp option in the linker. */ 330433965Sjdp if (! (*info->callbacks->add_archive_element) (info, 330533965Sjdp abfd, 330633965Sjdp name)) 3307130561Sobrien return FALSE; 3308130561Sobrien *pneeded = TRUE; 3309130561Sobrien return TRUE; 331033965Sjdp } 331133965Sjdp /* Turn the current link symbol into a common 331233965Sjdp symbol. It is already on the undefs list. */ 331333965Sjdp h->type = bfd_link_hash_common; 3314218822Sdim h->u.c.p = bfd_hash_allocate (&info->hash->table, 3315218822Sdim sizeof (struct bfd_link_hash_common_entry)); 331633965Sjdp if (h->u.c.p == NULL) 3317130561Sobrien return FALSE; 331833965Sjdp 331933965Sjdp h->u.c.size = value; 332033965Sjdp 332133965Sjdp /* FIXME: This isn't quite right. The maximum 332233965Sjdp alignment of a common symbol should be set by the 332333965Sjdp architecture of the output file, not of the input 332433965Sjdp file. */ 332533965Sjdp power = bfd_log2 (value); 332633965Sjdp if (power > bfd_get_arch_info (abfd)->section_align_power) 332733965Sjdp power = bfd_get_arch_info (abfd)->section_align_power; 332833965Sjdp h->u.c.p->alignment_power = power; 332933965Sjdp 333033965Sjdp h->u.c.p->section = bfd_make_section_old_way (symbfd, 333133965Sjdp "COMMON"); 333233965Sjdp } 333333965Sjdp else 333433965Sjdp { 333533965Sjdp /* Adjust the size of the common symbol if 333633965Sjdp necessary. */ 333733965Sjdp if (value > h->u.c.size) 333833965Sjdp h->u.c.size = value; 333933965Sjdp } 334033965Sjdp } 334133965Sjdp } 334233965Sjdp 334333965Sjdp if (type == N_WEAKA 334433965Sjdp || type == N_WEAKT 334533965Sjdp || type == N_WEAKD 334633965Sjdp || type == N_WEAKB) 334733965Sjdp { 334833965Sjdp /* This symbol is weak but defined. We must pull it in if 334933965Sjdp the current link symbol is undefined, but we don't want 335033965Sjdp it if the current link symbol is common. */ 335133965Sjdp if (h->type == bfd_link_hash_undefined) 335233965Sjdp { 335333965Sjdp if (! (*info->callbacks->add_archive_element) (info, abfd, name)) 3354130561Sobrien return FALSE; 3355130561Sobrien *pneeded = TRUE; 3356130561Sobrien return TRUE; 335733965Sjdp } 335833965Sjdp } 335933965Sjdp } 336033965Sjdp 336133965Sjdp /* We do not need this object file. */ 3362130561Sobrien return TRUE; 336333965Sjdp} 3364218822Sdim/* Check a single archive element to see if we need to include it in 3365218822Sdim the link. *PNEEDED is set according to whether this element is 3366218822Sdim needed in the link or not. This is called from 3367218822Sdim _bfd_generic_link_add_archive_symbols. */ 336833965Sjdp 3369130561Sobrienstatic bfd_boolean 3370218822Sdimaout_link_check_archive_element (bfd *abfd, 3371218822Sdim struct bfd_link_info *info, 3372218822Sdim bfd_boolean *pneeded) 337333965Sjdp{ 3374218822Sdim if (! aout_get_external_symbols (abfd)) 3375218822Sdim return FALSE; 337633965Sjdp 3377218822Sdim if (! aout_link_check_ar_symbols (abfd, info, pneeded)) 3378218822Sdim return FALSE; 337933965Sjdp 3380218822Sdim if (*pneeded) 338133965Sjdp { 3382218822Sdim if (! aout_link_add_symbols (abfd, info)) 3383130561Sobrien return FALSE; 338433965Sjdp } 338533965Sjdp 3386218822Sdim if (! info->keep_memory || ! *pneeded) 338733965Sjdp { 3388218822Sdim if (! aout_link_free_symbols (abfd)) 3389130561Sobrien return FALSE; 3390218822Sdim } 339133965Sjdp 3392218822Sdim return TRUE; 3393218822Sdim} 339433965Sjdp 3395218822Sdim/* Given an a.out BFD, add symbols to the global hash table as 3396218822Sdim appropriate. */ 339733965Sjdp 3398218822Sdimbfd_boolean 3399218822SdimNAME (aout, link_add_symbols) (bfd *abfd, struct bfd_link_info *info) 3400218822Sdim{ 3401218822Sdim switch (bfd_get_format (abfd)) 3402218822Sdim { 3403218822Sdim case bfd_object: 3404218822Sdim return aout_link_add_object_symbols (abfd, info); 3405218822Sdim case bfd_archive: 3406218822Sdim return _bfd_generic_link_add_archive_symbols 3407218822Sdim (abfd, info, aout_link_check_archive_element); 3408218822Sdim default: 3409218822Sdim bfd_set_error (bfd_error_wrong_format); 3410218822Sdim return FALSE; 341133965Sjdp } 341233965Sjdp} 341333965Sjdp 341433965Sjdp/* A hash table used for header files with N_BINCL entries. */ 341533965Sjdp 341633965Sjdpstruct aout_link_includes_table 341733965Sjdp{ 341833965Sjdp struct bfd_hash_table root; 341933965Sjdp}; 342033965Sjdp 342133965Sjdp/* A linked list of totals that we have found for a particular header 342233965Sjdp file. */ 342333965Sjdp 342433965Sjdpstruct aout_link_includes_totals 342533965Sjdp{ 342633965Sjdp struct aout_link_includes_totals *next; 342733965Sjdp bfd_vma total; 342833965Sjdp}; 342933965Sjdp 343033965Sjdp/* An entry in the header file hash table. */ 343133965Sjdp 343233965Sjdpstruct aout_link_includes_entry 343333965Sjdp{ 343433965Sjdp struct bfd_hash_entry root; 343533965Sjdp /* List of totals we have found for this file. */ 343633965Sjdp struct aout_link_includes_totals *totals; 343733965Sjdp}; 343833965Sjdp 343933965Sjdp/* Look up an entry in an the header file hash table. */ 344033965Sjdp 344189857Sobrien#define aout_link_includes_lookup(table, string, create, copy) \ 344289857Sobrien ((struct aout_link_includes_entry *) \ 344333965Sjdp bfd_hash_lookup (&(table)->root, (string), (create), (copy))) 344433965Sjdp 344533965Sjdp/* During the final link step we need to pass around a bunch of 344633965Sjdp information, so we do it in an instance of this structure. */ 344733965Sjdp 344833965Sjdpstruct aout_final_link_info 344933965Sjdp{ 345033965Sjdp /* General link information. */ 345133965Sjdp struct bfd_link_info *info; 345233965Sjdp /* Output bfd. */ 345333965Sjdp bfd *output_bfd; 345433965Sjdp /* Reloc file positions. */ 345533965Sjdp file_ptr treloff, dreloff; 345633965Sjdp /* File position of symbols. */ 345733965Sjdp file_ptr symoff; 345833965Sjdp /* String table. */ 345933965Sjdp struct bfd_strtab_hash *strtab; 346033965Sjdp /* Header file hash table. */ 346133965Sjdp struct aout_link_includes_table includes; 346233965Sjdp /* A buffer large enough to hold the contents of any section. */ 346333965Sjdp bfd_byte *contents; 346433965Sjdp /* A buffer large enough to hold the relocs of any section. */ 3465218822Sdim void * relocs; 346633965Sjdp /* A buffer large enough to hold the symbol map of any input BFD. */ 346733965Sjdp int *symbol_map; 346833965Sjdp /* A buffer large enough to hold output symbols of any input BFD. */ 346933965Sjdp struct external_nlist *output_syms; 347033965Sjdp}; 347133965Sjdp 347233965Sjdp/* The function to create a new entry in the header file hash table. */ 347333965Sjdp 347433965Sjdpstatic struct bfd_hash_entry * 3475218822Sdimaout_link_includes_newfunc (struct bfd_hash_entry *entry, 3476218822Sdim struct bfd_hash_table *table, 3477218822Sdim const char *string) 347833965Sjdp{ 347933965Sjdp struct aout_link_includes_entry *ret = 348033965Sjdp (struct aout_link_includes_entry *) entry; 348133965Sjdp 348233965Sjdp /* Allocate the structure if it has not already been allocated by a 348333965Sjdp subclass. */ 3484218822Sdim if (ret == NULL) 3485218822Sdim ret = bfd_hash_allocate (table, sizeof (* ret)); 3486218822Sdim if (ret == NULL) 3487218822Sdim return NULL; 348833965Sjdp 348933965Sjdp /* Call the allocation method of the superclass. */ 349033965Sjdp ret = ((struct aout_link_includes_entry *) 349133965Sjdp bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); 349233965Sjdp if (ret) 349333965Sjdp { 349433965Sjdp /* Set local fields. */ 349533965Sjdp ret->totals = NULL; 349633965Sjdp } 349733965Sjdp 349833965Sjdp return (struct bfd_hash_entry *) ret; 349933965Sjdp} 350033965Sjdp 350133965Sjdp/* Write out a symbol that was not associated with an a.out input 350233965Sjdp object. */ 350333965Sjdp 3504130561Sobrienstatic bfd_boolean 3505218822Sdimaout_link_write_other_symbol (struct aout_link_hash_entry *h, void * data) 350633965Sjdp{ 350733965Sjdp struct aout_final_link_info *finfo = (struct aout_final_link_info *) data; 350833965Sjdp bfd *output_bfd; 350933965Sjdp int type; 351033965Sjdp bfd_vma val; 351133965Sjdp struct external_nlist outsym; 351233965Sjdp bfd_size_type indx; 351389857Sobrien bfd_size_type amt; 351433965Sjdp 351594536Sobrien if (h->root.type == bfd_link_hash_warning) 351694536Sobrien { 351794536Sobrien h = (struct aout_link_hash_entry *) h->root.u.i.link; 351894536Sobrien if (h->root.type == bfd_link_hash_new) 3519130561Sobrien return TRUE; 352094536Sobrien } 352194536Sobrien 352233965Sjdp output_bfd = finfo->output_bfd; 352333965Sjdp 352433965Sjdp if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL) 352533965Sjdp { 352633965Sjdp if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol) 352733965Sjdp (output_bfd, finfo->info, h))) 352833965Sjdp { 352933965Sjdp /* FIXME: No way to handle errors. */ 353033965Sjdp abort (); 353133965Sjdp } 353233965Sjdp } 353333965Sjdp 353433965Sjdp if (h->written) 3535130561Sobrien return TRUE; 353633965Sjdp 3537130561Sobrien h->written = TRUE; 353833965Sjdp 353933965Sjdp /* An indx of -2 means the symbol must be written. */ 354033965Sjdp if (h->indx != -2 354133965Sjdp && (finfo->info->strip == strip_all 354233965Sjdp || (finfo->info->strip == strip_some 354333965Sjdp && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string, 3544130561Sobrien FALSE, FALSE) == NULL))) 3545130561Sobrien return TRUE; 354633965Sjdp 354733965Sjdp switch (h->root.type) 354833965Sjdp { 354933965Sjdp default: 355094536Sobrien case bfd_link_hash_warning: 355133965Sjdp abort (); 355233965Sjdp /* Avoid variable not initialized warnings. */ 3553130561Sobrien return TRUE; 355433965Sjdp case bfd_link_hash_new: 355533965Sjdp /* This can happen for set symbols when sets are not being 355633965Sjdp built. */ 3557130561Sobrien return TRUE; 355833965Sjdp case bfd_link_hash_undefined: 355933965Sjdp type = N_UNDF | N_EXT; 356033965Sjdp val = 0; 356133965Sjdp break; 356233965Sjdp case bfd_link_hash_defined: 356333965Sjdp case bfd_link_hash_defweak: 356433965Sjdp { 356533965Sjdp asection *sec; 356633965Sjdp 356733965Sjdp sec = h->root.u.def.section->output_section; 356833965Sjdp BFD_ASSERT (bfd_is_abs_section (sec) 356933965Sjdp || sec->owner == output_bfd); 357033965Sjdp if (sec == obj_textsec (output_bfd)) 357133965Sjdp type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT; 357233965Sjdp else if (sec == obj_datasec (output_bfd)) 357333965Sjdp type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD; 357433965Sjdp else if (sec == obj_bsssec (output_bfd)) 357533965Sjdp type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB; 357633965Sjdp else 357733965Sjdp type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA; 357833965Sjdp type |= N_EXT; 357933965Sjdp val = (h->root.u.def.value 358033965Sjdp + sec->vma 358133965Sjdp + h->root.u.def.section->output_offset); 358233965Sjdp } 358333965Sjdp break; 358433965Sjdp case bfd_link_hash_common: 358533965Sjdp type = N_UNDF | N_EXT; 358633965Sjdp val = h->root.u.c.size; 358733965Sjdp break; 358833965Sjdp case bfd_link_hash_undefweak: 358933965Sjdp type = N_WEAKU; 359033965Sjdp val = 0; 359133965Sjdp case bfd_link_hash_indirect: 359294536Sobrien /* We ignore these symbols, since the indirected symbol is 359394536Sobrien already in the hash table. */ 3594130561Sobrien return TRUE; 359533965Sjdp } 359633965Sjdp 359789857Sobrien H_PUT_8 (output_bfd, type, outsym.e_type); 359889857Sobrien H_PUT_8 (output_bfd, 0, outsym.e_other); 359989857Sobrien H_PUT_16 (output_bfd, 0, outsym.e_desc); 360033965Sjdp indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string, 3601130561Sobrien FALSE); 360289857Sobrien if (indx == - (bfd_size_type) 1) 3603218822Sdim /* FIXME: No way to handle errors. */ 3604218822Sdim abort (); 3605218822Sdim 360633965Sjdp PUT_WORD (output_bfd, indx, outsym.e_strx); 360733965Sjdp PUT_WORD (output_bfd, val, outsym.e_value); 360833965Sjdp 360989857Sobrien amt = EXTERNAL_NLIST_SIZE; 361033965Sjdp if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0 3611218822Sdim || bfd_bwrite ((void *) &outsym, amt, output_bfd) != amt) 3612218822Sdim /* FIXME: No way to handle errors. */ 3613218822Sdim abort (); 361433965Sjdp 361533965Sjdp finfo->symoff += EXTERNAL_NLIST_SIZE; 361633965Sjdp h->indx = obj_aout_external_sym_count (output_bfd); 361733965Sjdp ++obj_aout_external_sym_count (output_bfd); 361833965Sjdp 3619130561Sobrien return TRUE; 362033965Sjdp} 362133965Sjdp 3622218822Sdim/* Handle a link order which is supposed to generate a reloc. */ 362333965Sjdp 3624130561Sobrienstatic bfd_boolean 3625218822Sdimaout_link_reloc_link_order (struct aout_final_link_info *finfo, 3626218822Sdim asection *o, 3627218822Sdim struct bfd_link_order *p) 362833965Sjdp{ 3629218822Sdim struct bfd_link_order_reloc *pr; 3630218822Sdim int r_index; 3631218822Sdim int r_extern; 3632218822Sdim reloc_howto_type *howto; 3633218822Sdim file_ptr *reloff_ptr = NULL; 3634218822Sdim struct reloc_std_external srel; 3635218822Sdim struct reloc_ext_external erel; 3636218822Sdim void * rel_ptr; 3637218822Sdim bfd_size_type amt; 363833965Sjdp 3639218822Sdim pr = p->u.reloc.p; 364033965Sjdp 3641218822Sdim if (p->type == bfd_section_reloc_link_order) 3642218822Sdim { 3643218822Sdim r_extern = 0; 3644218822Sdim if (bfd_is_abs_section (pr->u.section)) 3645218822Sdim r_index = N_ABS | N_EXT; 3646218822Sdim else 3647218822Sdim { 3648218822Sdim BFD_ASSERT (pr->u.section->owner == finfo->output_bfd); 3649218822Sdim r_index = pr->u.section->target_index; 3650218822Sdim } 3651218822Sdim } 365233965Sjdp else 365333965Sjdp { 3654218822Sdim struct aout_link_hash_entry *h; 3655218822Sdim 3656218822Sdim BFD_ASSERT (p->type == bfd_symbol_reloc_link_order); 3657218822Sdim r_extern = 1; 3658218822Sdim h = ((struct aout_link_hash_entry *) 3659218822Sdim bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info, 3660218822Sdim pr->u.name, FALSE, FALSE, TRUE)); 3661218822Sdim if (h != NULL 3662218822Sdim && h->indx >= 0) 3663218822Sdim r_index = h->indx; 3664218822Sdim else if (h != NULL) 366533965Sjdp { 3666218822Sdim /* We decided to strip this symbol, but it turns out that we 3667218822Sdim can't. Note that we lose the other and desc information 3668218822Sdim here. I don't think that will ever matter for a global 3669218822Sdim symbol. */ 3670218822Sdim h->indx = -2; 3671218822Sdim h->written = FALSE; 3672218822Sdim if (! aout_link_write_other_symbol (h, (void *) finfo)) 3673130561Sobrien return FALSE; 3674218822Sdim r_index = h->indx; 367533965Sjdp } 3676218822Sdim else 3677218822Sdim { 3678218822Sdim if (! ((*finfo->info->callbacks->unattached_reloc) 3679218822Sdim (finfo->info, pr->u.name, NULL, NULL, (bfd_vma) 0))) 3680218822Sdim return FALSE; 3681218822Sdim r_index = 0; 3682218822Sdim } 368333965Sjdp } 368433965Sjdp 3685218822Sdim howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc); 3686218822Sdim if (howto == 0) 368733965Sjdp { 3688218822Sdim bfd_set_error (bfd_error_bad_value); 3689218822Sdim return FALSE; 369033965Sjdp } 3691218822Sdim 3692218822Sdim if (o == obj_textsec (finfo->output_bfd)) 3693218822Sdim reloff_ptr = &finfo->treloff; 3694218822Sdim else if (o == obj_datasec (finfo->output_bfd)) 3695218822Sdim reloff_ptr = &finfo->dreloff; 369633965Sjdp else 3697218822Sdim abort (); 3698218822Sdim 3699218822Sdim if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE) 370033965Sjdp { 3701218822Sdim#ifdef MY_put_reloc 3702218822Sdim MY_put_reloc (finfo->output_bfd, r_extern, r_index, p->offset, howto, 3703218822Sdim &srel); 3704218822Sdim#else 3705218822Sdim { 3706218822Sdim int r_pcrel; 3707218822Sdim int r_baserel; 3708218822Sdim int r_jmptable; 3709218822Sdim int r_relative; 3710218822Sdim int r_length; 371133965Sjdp 3712218822Sdim r_pcrel = (int) howto->pc_relative; 3713218822Sdim r_baserel = (howto->type & 8) != 0; 3714218822Sdim r_jmptable = (howto->type & 16) != 0; 3715218822Sdim r_relative = (howto->type & 32) != 0; 3716218822Sdim r_length = howto->size; 371733965Sjdp 3718218822Sdim PUT_WORD (finfo->output_bfd, p->offset, srel.r_address); 3719218822Sdim if (bfd_header_big_endian (finfo->output_bfd)) 3720218822Sdim { 3721218822Sdim srel.r_index[0] = r_index >> 16; 3722218822Sdim srel.r_index[1] = r_index >> 8; 3723218822Sdim srel.r_index[2] = r_index; 3724218822Sdim srel.r_type[0] = 3725218822Sdim ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) 3726218822Sdim | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) 3727218822Sdim | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) 3728218822Sdim | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) 3729218822Sdim | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) 3730218822Sdim | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); 3731218822Sdim } 3732218822Sdim else 3733218822Sdim { 3734218822Sdim srel.r_index[2] = r_index >> 16; 3735218822Sdim srel.r_index[1] = r_index >> 8; 3736218822Sdim srel.r_index[0] = r_index; 3737218822Sdim srel.r_type[0] = 3738218822Sdim ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) 3739218822Sdim | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) 3740218822Sdim | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) 3741218822Sdim | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) 3742218822Sdim | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) 3743218822Sdim | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 3744218822Sdim } 3745218822Sdim } 3746218822Sdim#endif 3747218822Sdim rel_ptr = (void *) &srel; 3748218822Sdim 3749218822Sdim /* We have to write the addend into the object file, since 3750218822Sdim standard a.out relocs are in place. It would be more 3751218822Sdim reliable if we had the current contents of the file here, 3752218822Sdim rather than assuming zeroes, but we can't read the file since 3753218822Sdim it was opened using bfd_openw. */ 3754218822Sdim if (pr->addend != 0) 3755218822Sdim { 3756218822Sdim bfd_size_type size; 3757218822Sdim bfd_reloc_status_type r; 3758218822Sdim bfd_byte *buf; 3759218822Sdim bfd_boolean ok; 3760218822Sdim 3761218822Sdim size = bfd_get_reloc_size (howto); 3762218822Sdim buf = bfd_zmalloc (size); 3763218822Sdim if (buf == NULL) 3764218822Sdim return FALSE; 3765218822Sdim r = MY_relocate_contents (howto, finfo->output_bfd, 3766218822Sdim (bfd_vma) pr->addend, buf); 3767218822Sdim switch (r) 3768218822Sdim { 3769218822Sdim case bfd_reloc_ok: 3770218822Sdim break; 3771218822Sdim default: 3772218822Sdim case bfd_reloc_outofrange: 3773218822Sdim abort (); 3774218822Sdim case bfd_reloc_overflow: 3775218822Sdim if (! ((*finfo->info->callbacks->reloc_overflow) 3776218822Sdim (finfo->info, NULL, 3777218822Sdim (p->type == bfd_section_reloc_link_order 3778218822Sdim ? bfd_section_name (finfo->output_bfd, 3779218822Sdim pr->u.section) 3780218822Sdim : pr->u.name), 3781218822Sdim howto->name, pr->addend, NULL, NULL, (bfd_vma) 0))) 3782218822Sdim { 3783218822Sdim free (buf); 3784218822Sdim return FALSE; 3785218822Sdim } 3786218822Sdim break; 3787218822Sdim } 3788218822Sdim ok = bfd_set_section_contents (finfo->output_bfd, o, (void *) buf, 3789218822Sdim (file_ptr) p->offset, size); 3790218822Sdim free (buf); 3791218822Sdim if (! ok) 3792218822Sdim return FALSE; 3793218822Sdim } 3794218822Sdim } 3795218822Sdim else 379633965Sjdp { 3797218822Sdim#ifdef MY_put_ext_reloc 3798218822Sdim MY_put_ext_reloc (finfo->output_bfd, r_extern, r_index, p->offset, 3799218822Sdim howto, &erel, pr->addend); 3800218822Sdim#else 3801218822Sdim PUT_WORD (finfo->output_bfd, p->offset, erel.r_address); 380233965Sjdp 3803218822Sdim if (bfd_header_big_endian (finfo->output_bfd)) 3804218822Sdim { 3805218822Sdim erel.r_index[0] = r_index >> 16; 3806218822Sdim erel.r_index[1] = r_index >> 8; 3807218822Sdim erel.r_index[2] = r_index; 3808218822Sdim erel.r_type[0] = 3809218822Sdim ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) 3810218822Sdim | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG)); 3811218822Sdim } 3812218822Sdim else 3813218822Sdim { 3814218822Sdim erel.r_index[2] = r_index >> 16; 3815218822Sdim erel.r_index[1] = r_index >> 8; 3816218822Sdim erel.r_index[0] = r_index; 3817218822Sdim erel.r_type[0] = 3818218822Sdim (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) 3819218822Sdim | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE); 3820218822Sdim } 3821218822Sdim 3822218822Sdim PUT_WORD (finfo->output_bfd, (bfd_vma) pr->addend, erel.r_addend); 3823218822Sdim#endif /* MY_put_ext_reloc */ 3824218822Sdim 3825218822Sdim rel_ptr = (void *) &erel; 382633965Sjdp } 382733965Sjdp 3828218822Sdim amt = obj_reloc_entry_size (finfo->output_bfd); 3829218822Sdim if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0 3830218822Sdim || bfd_bwrite (rel_ptr, amt, finfo->output_bfd) != amt) 3831218822Sdim return FALSE; 3832218822Sdim 3833218822Sdim *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd); 3834218822Sdim 3835218822Sdim /* Assert that the relocs have not run into the symbols, and that n 3836218822Sdim the text relocs have not run into the data relocs. */ 3837218822Sdim BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) 3838218822Sdim && (reloff_ptr != &finfo->treloff 3839218822Sdim || (*reloff_ptr 3840218822Sdim <= obj_datasec (finfo->output_bfd)->rel_filepos))); 3841218822Sdim 3842130561Sobrien return TRUE; 384333965Sjdp} 384433965Sjdp 384533965Sjdp/* Get the section corresponding to a reloc index. */ 384633965Sjdp 384733965Sjdpstatic INLINE asection * 3848218822Sdimaout_reloc_index_to_section (bfd *abfd, int indx) 384933965Sjdp{ 385033965Sjdp switch (indx & N_TYPE) 385133965Sjdp { 3852218822Sdim case N_TEXT: return obj_textsec (abfd); 3853218822Sdim case N_DATA: return obj_datasec (abfd); 3854218822Sdim case N_BSS: return obj_bsssec (abfd); 385533965Sjdp case N_ABS: 3856218822Sdim case N_UNDF: return bfd_abs_section_ptr; 3857218822Sdim default: abort (); 385833965Sjdp } 385960484Sobrien return NULL; 386033965Sjdp} 386133965Sjdp 386233965Sjdp/* Relocate an a.out section using standard a.out relocs. */ 386333965Sjdp 3864130561Sobrienstatic bfd_boolean 3865218822Sdimaout_link_input_section_std (struct aout_final_link_info *finfo, 3866218822Sdim bfd *input_bfd, 3867218822Sdim asection *input_section, 3868218822Sdim struct reloc_std_external *relocs, 3869218822Sdim bfd_size_type rel_size, 3870218822Sdim bfd_byte *contents) 387133965Sjdp{ 3872130561Sobrien bfd_boolean (*check_dynamic_reloc) 3873218822Sdim (struct bfd_link_info *, bfd *, asection *, 3874218822Sdim struct aout_link_hash_entry *, void *, bfd_byte *, bfd_boolean *, 3875218822Sdim bfd_vma *); 387633965Sjdp bfd *output_bfd; 3877130561Sobrien bfd_boolean relocatable; 387833965Sjdp struct external_nlist *syms; 387933965Sjdp char *strings; 388033965Sjdp struct aout_link_hash_entry **sym_hashes; 388133965Sjdp int *symbol_map; 388233965Sjdp bfd_size_type reloc_count; 3883218822Sdim struct reloc_std_external *rel; 388433965Sjdp struct reloc_std_external *rel_end; 388533965Sjdp 388633965Sjdp output_bfd = finfo->output_bfd; 388733965Sjdp check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; 388833965Sjdp 388933965Sjdp BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE); 389033965Sjdp BFD_ASSERT (input_bfd->xvec->header_byteorder 389133965Sjdp == output_bfd->xvec->header_byteorder); 389233965Sjdp 3893130561Sobrien relocatable = finfo->info->relocatable; 389433965Sjdp syms = obj_aout_external_syms (input_bfd); 389533965Sjdp strings = obj_aout_external_strings (input_bfd); 389633965Sjdp sym_hashes = obj_aout_sym_hashes (input_bfd); 389733965Sjdp symbol_map = finfo->symbol_map; 389833965Sjdp 389933965Sjdp reloc_count = rel_size / RELOC_STD_SIZE; 390033965Sjdp rel = relocs; 390133965Sjdp rel_end = rel + reloc_count; 390233965Sjdp for (; rel < rel_end; rel++) 390333965Sjdp { 390433965Sjdp bfd_vma r_addr; 390533965Sjdp int r_index; 390633965Sjdp int r_extern; 390733965Sjdp int r_pcrel; 390833965Sjdp int r_baserel = 0; 390933965Sjdp reloc_howto_type *howto; 391033965Sjdp struct aout_link_hash_entry *h = NULL; 391133965Sjdp bfd_vma relocation; 391233965Sjdp bfd_reloc_status_type r; 391333965Sjdp 391433965Sjdp r_addr = GET_SWORD (input_bfd, rel->r_address); 391533965Sjdp 391633965Sjdp#ifdef MY_reloc_howto 391789857Sobrien howto = MY_reloc_howto (input_bfd, rel, r_index, r_extern, r_pcrel); 391877298Sobrien#else 391933965Sjdp { 392033965Sjdp int r_jmptable; 392133965Sjdp int r_relative; 392233965Sjdp int r_length; 392333965Sjdp unsigned int howto_idx; 392433965Sjdp 392533965Sjdp if (bfd_header_big_endian (input_bfd)) 392633965Sjdp { 3927107492Sobrien r_index = (((unsigned int) rel->r_index[0] << 16) 3928107492Sobrien | ((unsigned int) rel->r_index[1] << 8) 392933965Sjdp | rel->r_index[2]); 393033965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); 393133965Sjdp r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 393233965Sjdp r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 393333965Sjdp r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 393433965Sjdp r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); 393533965Sjdp r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) 393633965Sjdp >> RELOC_STD_BITS_LENGTH_SH_BIG); 393733965Sjdp } 393833965Sjdp else 393933965Sjdp { 3940107492Sobrien r_index = (((unsigned int) rel->r_index[2] << 16) 3941107492Sobrien | ((unsigned int) rel->r_index[1] << 8) 394233965Sjdp | rel->r_index[0]); 394333965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); 394433965Sjdp r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 394533965Sjdp r_baserel = (0 != (rel->r_type[0] 394633965Sjdp & RELOC_STD_BITS_BASEREL_LITTLE)); 394733965Sjdp r_jmptable= (0 != (rel->r_type[0] 394833965Sjdp & RELOC_STD_BITS_JMPTABLE_LITTLE)); 394933965Sjdp r_relative= (0 != (rel->r_type[0] 395033965Sjdp & RELOC_STD_BITS_RELATIVE_LITTLE)); 395133965Sjdp r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) 395233965Sjdp >> RELOC_STD_BITS_LENGTH_SH_LITTLE); 395333965Sjdp } 395433965Sjdp 395533965Sjdp howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel 395633965Sjdp + 16 * r_jmptable + 32 * r_relative); 395733965Sjdp BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); 395833965Sjdp howto = howto_table_std + howto_idx; 395933965Sjdp } 396033965Sjdp#endif 396133965Sjdp 3962130561Sobrien if (relocatable) 396333965Sjdp { 3964130561Sobrien /* We are generating a relocatable output file, and must 396533965Sjdp modify the reloc accordingly. */ 396633965Sjdp if (r_extern) 396733965Sjdp { 396833965Sjdp /* If we know the symbol this relocation is against, 396933965Sjdp convert it into a relocation against a section. This 397033965Sjdp is what the native linker does. */ 397133965Sjdp h = sym_hashes[r_index]; 3972218822Sdim if (h != NULL 397333965Sjdp && (h->root.type == bfd_link_hash_defined 397433965Sjdp || h->root.type == bfd_link_hash_defweak)) 397533965Sjdp { 397633965Sjdp asection *output_section; 397733965Sjdp 397833965Sjdp /* Change the r_extern value. */ 397933965Sjdp if (bfd_header_big_endian (output_bfd)) 398033965Sjdp rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; 398133965Sjdp else 398233965Sjdp rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; 398333965Sjdp 398433965Sjdp /* Compute a new r_index. */ 398533965Sjdp output_section = h->root.u.def.section->output_section; 398633965Sjdp if (output_section == obj_textsec (output_bfd)) 398733965Sjdp r_index = N_TEXT; 398833965Sjdp else if (output_section == obj_datasec (output_bfd)) 398933965Sjdp r_index = N_DATA; 399033965Sjdp else if (output_section == obj_bsssec (output_bfd)) 399133965Sjdp r_index = N_BSS; 399233965Sjdp else 399333965Sjdp r_index = N_ABS; 399433965Sjdp 399533965Sjdp /* Add the symbol value and the section VMA to the 399633965Sjdp addend stored in the contents. */ 399733965Sjdp relocation = (h->root.u.def.value 399833965Sjdp + output_section->vma 399933965Sjdp + h->root.u.def.section->output_offset); 400033965Sjdp } 400133965Sjdp else 400233965Sjdp { 400333965Sjdp /* We must change r_index according to the symbol 400433965Sjdp map. */ 400533965Sjdp r_index = symbol_map[r_index]; 400633965Sjdp 400733965Sjdp if (r_index == -1) 400833965Sjdp { 400933965Sjdp if (h != NULL) 401033965Sjdp { 401133965Sjdp /* We decided to strip this symbol, but it 401233965Sjdp turns out that we can't. Note that we 401333965Sjdp lose the other and desc information here. 401433965Sjdp I don't think that will ever matter for a 401533965Sjdp global symbol. */ 401633965Sjdp if (h->indx < 0) 401733965Sjdp { 401833965Sjdp h->indx = -2; 4019130561Sobrien h->written = FALSE; 402033965Sjdp if (! aout_link_write_other_symbol (h, 4021218822Sdim (void *) finfo)) 4022130561Sobrien return FALSE; 402333965Sjdp } 402433965Sjdp r_index = h->indx; 402533965Sjdp } 402633965Sjdp else 402733965Sjdp { 402833965Sjdp const char *name; 402933965Sjdp 403033965Sjdp name = strings + GET_WORD (input_bfd, 403133965Sjdp syms[r_index].e_strx); 403233965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 403333965Sjdp (finfo->info, name, input_bfd, input_section, 403433965Sjdp r_addr))) 4035130561Sobrien return FALSE; 403633965Sjdp r_index = 0; 403733965Sjdp } 403833965Sjdp } 403933965Sjdp 404033965Sjdp relocation = 0; 404133965Sjdp } 404233965Sjdp 404333965Sjdp /* Write out the new r_index value. */ 404433965Sjdp if (bfd_header_big_endian (output_bfd)) 404533965Sjdp { 404633965Sjdp rel->r_index[0] = r_index >> 16; 404733965Sjdp rel->r_index[1] = r_index >> 8; 404833965Sjdp rel->r_index[2] = r_index; 404933965Sjdp } 405033965Sjdp else 405133965Sjdp { 405233965Sjdp rel->r_index[2] = r_index >> 16; 405333965Sjdp rel->r_index[1] = r_index >> 8; 405433965Sjdp rel->r_index[0] = r_index; 405533965Sjdp } 405633965Sjdp } 405733965Sjdp else 405833965Sjdp { 405933965Sjdp asection *section; 406033965Sjdp 406133965Sjdp /* This is a relocation against a section. We must 406233965Sjdp adjust by the amount that the section moved. */ 406333965Sjdp section = aout_reloc_index_to_section (input_bfd, r_index); 406433965Sjdp relocation = (section->output_section->vma 406533965Sjdp + section->output_offset 406633965Sjdp - section->vma); 406733965Sjdp } 406833965Sjdp 406933965Sjdp /* Change the address of the relocation. */ 407033965Sjdp PUT_WORD (output_bfd, 407133965Sjdp r_addr + input_section->output_offset, 407233965Sjdp rel->r_address); 407333965Sjdp 407433965Sjdp /* Adjust a PC relative relocation by removing the reference 407533965Sjdp to the original address in the section and including the 407633965Sjdp reference to the new address. */ 407733965Sjdp if (r_pcrel) 407833965Sjdp relocation -= (input_section->output_section->vma 407933965Sjdp + input_section->output_offset 408033965Sjdp - input_section->vma); 408133965Sjdp 408233965Sjdp#ifdef MY_relocatable_reloc 408333965Sjdp MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr); 408433965Sjdp#endif 408533965Sjdp 408633965Sjdp if (relocation == 0) 408733965Sjdp r = bfd_reloc_ok; 408833965Sjdp else 408933965Sjdp r = MY_relocate_contents (howto, 409033965Sjdp input_bfd, relocation, 409133965Sjdp contents + r_addr); 409233965Sjdp } 409333965Sjdp else 409433965Sjdp { 4095130561Sobrien bfd_boolean hundef; 409633965Sjdp 409733965Sjdp /* We are generating an executable, and must do a full 409833965Sjdp relocation. */ 4099130561Sobrien hundef = FALSE; 410060484Sobrien 410133965Sjdp if (r_extern) 410233965Sjdp { 410333965Sjdp h = sym_hashes[r_index]; 410433965Sjdp 4105218822Sdim if (h != NULL 410633965Sjdp && (h->root.type == bfd_link_hash_defined 410733965Sjdp || h->root.type == bfd_link_hash_defweak)) 410833965Sjdp { 410933965Sjdp relocation = (h->root.u.def.value 411033965Sjdp + h->root.u.def.section->output_section->vma 411133965Sjdp + h->root.u.def.section->output_offset); 411233965Sjdp } 4113218822Sdim else if (h != NULL 411433965Sjdp && h->root.type == bfd_link_hash_undefweak) 411533965Sjdp relocation = 0; 411633965Sjdp else 411733965Sjdp { 4118130561Sobrien hundef = TRUE; 411933965Sjdp relocation = 0; 412033965Sjdp } 412133965Sjdp } 412233965Sjdp else 412333965Sjdp { 412433965Sjdp asection *section; 412533965Sjdp 412633965Sjdp section = aout_reloc_index_to_section (input_bfd, r_index); 412733965Sjdp relocation = (section->output_section->vma 412833965Sjdp + section->output_offset 412933965Sjdp - section->vma); 413033965Sjdp if (r_pcrel) 413133965Sjdp relocation += input_section->vma; 413233965Sjdp } 413333965Sjdp 413433965Sjdp if (check_dynamic_reloc != NULL) 413533965Sjdp { 4136130561Sobrien bfd_boolean skip; 413733965Sjdp 413833965Sjdp if (! ((*check_dynamic_reloc) 413933965Sjdp (finfo->info, input_bfd, input_section, h, 4140218822Sdim (void *) rel, contents, &skip, &relocation))) 4141130561Sobrien return FALSE; 414233965Sjdp if (skip) 414333965Sjdp continue; 414433965Sjdp } 414533965Sjdp 414633965Sjdp /* Now warn if a global symbol is undefined. We could not 414733965Sjdp do this earlier, because check_dynamic_reloc might want 414833965Sjdp to skip this reloc. */ 414933965Sjdp if (hundef && ! finfo->info->shared && ! r_baserel) 415033965Sjdp { 415133965Sjdp const char *name; 415233965Sjdp 415333965Sjdp if (h != NULL) 415433965Sjdp name = h->root.root.string; 415533965Sjdp else 415633965Sjdp name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); 415733965Sjdp if (! ((*finfo->info->callbacks->undefined_symbol) 415860484Sobrien (finfo->info, name, input_bfd, input_section, 4159130561Sobrien r_addr, TRUE))) 4160130561Sobrien return FALSE; 416133965Sjdp } 416233965Sjdp 416333965Sjdp r = MY_final_link_relocate (howto, 416433965Sjdp input_bfd, input_section, 416533965Sjdp contents, r_addr, relocation, 416633965Sjdp (bfd_vma) 0); 416733965Sjdp } 416833965Sjdp 416933965Sjdp if (r != bfd_reloc_ok) 417033965Sjdp { 417133965Sjdp switch (r) 417233965Sjdp { 417333965Sjdp default: 417433965Sjdp case bfd_reloc_outofrange: 417533965Sjdp abort (); 417633965Sjdp case bfd_reloc_overflow: 417733965Sjdp { 417833965Sjdp const char *name; 417933965Sjdp 418033965Sjdp if (h != NULL) 4181218822Sdim name = NULL; 418233965Sjdp else if (r_extern) 418333965Sjdp name = strings + GET_WORD (input_bfd, 418433965Sjdp syms[r_index].e_strx); 418533965Sjdp else 418633965Sjdp { 418733965Sjdp asection *s; 418833965Sjdp 418933965Sjdp s = aout_reloc_index_to_section (input_bfd, r_index); 419033965Sjdp name = bfd_section_name (input_bfd, s); 419133965Sjdp } 419233965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 4193218822Sdim (finfo->info, (h ? &h->root : NULL), name, 4194218822Sdim howto->name, (bfd_vma) 0, input_bfd, 4195218822Sdim input_section, r_addr))) 4196130561Sobrien return FALSE; 419733965Sjdp } 419833965Sjdp break; 419933965Sjdp } 420033965Sjdp } 420133965Sjdp } 420233965Sjdp 4203130561Sobrien return TRUE; 420433965Sjdp} 420533965Sjdp 420633965Sjdp/* Relocate an a.out section using extended a.out relocs. */ 420733965Sjdp 4208130561Sobrienstatic bfd_boolean 4209218822Sdimaout_link_input_section_ext (struct aout_final_link_info *finfo, 4210218822Sdim bfd *input_bfd, 4211218822Sdim asection *input_section, 4212218822Sdim struct reloc_ext_external *relocs, 4213218822Sdim bfd_size_type rel_size, 4214218822Sdim bfd_byte *contents) 421533965Sjdp{ 4216130561Sobrien bfd_boolean (*check_dynamic_reloc) 4217218822Sdim (struct bfd_link_info *, bfd *, asection *, 4218218822Sdim struct aout_link_hash_entry *, void *, bfd_byte *, bfd_boolean *, 4219218822Sdim bfd_vma *); 422033965Sjdp bfd *output_bfd; 4221130561Sobrien bfd_boolean relocatable; 422233965Sjdp struct external_nlist *syms; 422333965Sjdp char *strings; 422433965Sjdp struct aout_link_hash_entry **sym_hashes; 422533965Sjdp int *symbol_map; 422633965Sjdp bfd_size_type reloc_count; 4227218822Sdim struct reloc_ext_external *rel; 422833965Sjdp struct reloc_ext_external *rel_end; 422933965Sjdp 423033965Sjdp output_bfd = finfo->output_bfd; 423133965Sjdp check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; 423233965Sjdp 423333965Sjdp BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE); 423433965Sjdp BFD_ASSERT (input_bfd->xvec->header_byteorder 423533965Sjdp == output_bfd->xvec->header_byteorder); 423633965Sjdp 4237130561Sobrien relocatable = finfo->info->relocatable; 423833965Sjdp syms = obj_aout_external_syms (input_bfd); 423933965Sjdp strings = obj_aout_external_strings (input_bfd); 424033965Sjdp sym_hashes = obj_aout_sym_hashes (input_bfd); 424133965Sjdp symbol_map = finfo->symbol_map; 424233965Sjdp 424333965Sjdp reloc_count = rel_size / RELOC_EXT_SIZE; 424433965Sjdp rel = relocs; 424533965Sjdp rel_end = rel + reloc_count; 424633965Sjdp for (; rel < rel_end; rel++) 424733965Sjdp { 424833965Sjdp bfd_vma r_addr; 424933965Sjdp int r_index; 425033965Sjdp int r_extern; 425133965Sjdp unsigned int r_type; 425233965Sjdp bfd_vma r_addend; 425333965Sjdp struct aout_link_hash_entry *h = NULL; 425433965Sjdp asection *r_section = NULL; 425533965Sjdp bfd_vma relocation; 425633965Sjdp 425733965Sjdp r_addr = GET_SWORD (input_bfd, rel->r_address); 425833965Sjdp 425933965Sjdp if (bfd_header_big_endian (input_bfd)) 426033965Sjdp { 4261107492Sobrien r_index = (((unsigned int) rel->r_index[0] << 16) 4262107492Sobrien | ((unsigned int) rel->r_index[1] << 8) 426333965Sjdp | rel->r_index[2]); 426433965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 426533965Sjdp r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 426633965Sjdp >> RELOC_EXT_BITS_TYPE_SH_BIG); 426733965Sjdp } 426833965Sjdp else 426933965Sjdp { 4270107492Sobrien r_index = (((unsigned int) rel->r_index[2] << 16) 4271107492Sobrien | ((unsigned int) rel->r_index[1] << 8) 427233965Sjdp | rel->r_index[0]); 427333965Sjdp r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 427433965Sjdp r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 427533965Sjdp >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 427633965Sjdp } 427733965Sjdp 427833965Sjdp r_addend = GET_SWORD (input_bfd, rel->r_addend); 427933965Sjdp 428033965Sjdp BFD_ASSERT (r_type < TABLE_SIZE (howto_table_ext)); 428133965Sjdp 4282130561Sobrien if (relocatable) 428333965Sjdp { 4284130561Sobrien /* We are generating a relocatable output file, and must 428533965Sjdp modify the reloc accordingly. */ 428633965Sjdp if (r_extern 4287107492Sobrien || r_type == (unsigned int) RELOC_BASE10 4288107492Sobrien || r_type == (unsigned int) RELOC_BASE13 4289107492Sobrien || r_type == (unsigned int) RELOC_BASE22) 429033965Sjdp { 429133965Sjdp /* If we know the symbol this relocation is against, 429233965Sjdp convert it into a relocation against a section. This 429333965Sjdp is what the native linker does. */ 4294107492Sobrien if (r_type == (unsigned int) RELOC_BASE10 4295107492Sobrien || r_type == (unsigned int) RELOC_BASE13 4296107492Sobrien || r_type == (unsigned int) RELOC_BASE22) 429733965Sjdp h = NULL; 429833965Sjdp else 429933965Sjdp h = sym_hashes[r_index]; 4300218822Sdim if (h != NULL 430133965Sjdp && (h->root.type == bfd_link_hash_defined 430233965Sjdp || h->root.type == bfd_link_hash_defweak)) 430333965Sjdp { 430433965Sjdp asection *output_section; 430533965Sjdp 430633965Sjdp /* Change the r_extern value. */ 430733965Sjdp if (bfd_header_big_endian (output_bfd)) 430833965Sjdp rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; 430933965Sjdp else 431033965Sjdp rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; 431133965Sjdp 431233965Sjdp /* Compute a new r_index. */ 431333965Sjdp output_section = h->root.u.def.section->output_section; 431433965Sjdp if (output_section == obj_textsec (output_bfd)) 431533965Sjdp r_index = N_TEXT; 431633965Sjdp else if (output_section == obj_datasec (output_bfd)) 431733965Sjdp r_index = N_DATA; 431833965Sjdp else if (output_section == obj_bsssec (output_bfd)) 431933965Sjdp r_index = N_BSS; 432033965Sjdp else 432133965Sjdp r_index = N_ABS; 432233965Sjdp 432333965Sjdp /* Add the symbol value and the section VMA to the 432433965Sjdp addend. */ 432533965Sjdp relocation = (h->root.u.def.value 432633965Sjdp + output_section->vma 432733965Sjdp + h->root.u.def.section->output_offset); 432833965Sjdp 432933965Sjdp /* Now RELOCATION is the VMA of the final 433033965Sjdp destination. If this is a PC relative reloc, 433133965Sjdp then ADDEND is the negative of the source VMA. 433233965Sjdp We want to set ADDEND to the difference between 433333965Sjdp the destination VMA and the source VMA, which 433433965Sjdp means we must adjust RELOCATION by the change in 433533965Sjdp the source VMA. This is done below. */ 433633965Sjdp } 433733965Sjdp else 433833965Sjdp { 433933965Sjdp /* We must change r_index according to the symbol 434033965Sjdp map. */ 434133965Sjdp r_index = symbol_map[r_index]; 434233965Sjdp 434333965Sjdp if (r_index == -1) 434433965Sjdp { 434533965Sjdp if (h != NULL) 434633965Sjdp { 434733965Sjdp /* We decided to strip this symbol, but it 434833965Sjdp turns out that we can't. Note that we 434933965Sjdp lose the other and desc information here. 435033965Sjdp I don't think that will ever matter for a 435133965Sjdp global symbol. */ 435233965Sjdp if (h->indx < 0) 435333965Sjdp { 435433965Sjdp h->indx = -2; 4355130561Sobrien h->written = FALSE; 435633965Sjdp if (! aout_link_write_other_symbol (h, 4357218822Sdim (void *) finfo)) 4358130561Sobrien return FALSE; 435933965Sjdp } 436033965Sjdp r_index = h->indx; 436133965Sjdp } 436233965Sjdp else 436333965Sjdp { 436433965Sjdp const char *name; 436533965Sjdp 436633965Sjdp name = strings + GET_WORD (input_bfd, 436733965Sjdp syms[r_index].e_strx); 436833965Sjdp if (! ((*finfo->info->callbacks->unattached_reloc) 436933965Sjdp (finfo->info, name, input_bfd, input_section, 437033965Sjdp r_addr))) 4371130561Sobrien return FALSE; 437233965Sjdp r_index = 0; 437333965Sjdp } 437433965Sjdp } 437533965Sjdp 437633965Sjdp relocation = 0; 437733965Sjdp 437833965Sjdp /* If this is a PC relative reloc, then the addend 437933965Sjdp is the negative of the source VMA. We must 438033965Sjdp adjust it by the change in the source VMA. This 438133965Sjdp is done below. */ 438233965Sjdp } 438333965Sjdp 438433965Sjdp /* Write out the new r_index value. */ 438533965Sjdp if (bfd_header_big_endian (output_bfd)) 438633965Sjdp { 438733965Sjdp rel->r_index[0] = r_index >> 16; 438833965Sjdp rel->r_index[1] = r_index >> 8; 438933965Sjdp rel->r_index[2] = r_index; 439033965Sjdp } 439133965Sjdp else 439233965Sjdp { 439333965Sjdp rel->r_index[2] = r_index >> 16; 439433965Sjdp rel->r_index[1] = r_index >> 8; 439533965Sjdp rel->r_index[0] = r_index; 439633965Sjdp } 439733965Sjdp } 439833965Sjdp else 439933965Sjdp { 440033965Sjdp /* This is a relocation against a section. We must 440133965Sjdp adjust by the amount that the section moved. */ 440233965Sjdp r_section = aout_reloc_index_to_section (input_bfd, r_index); 440333965Sjdp relocation = (r_section->output_section->vma 440433965Sjdp + r_section->output_offset 440533965Sjdp - r_section->vma); 440633965Sjdp 440733965Sjdp /* If this is a PC relative reloc, then the addend is 440833965Sjdp the difference in VMA between the destination and the 440933965Sjdp source. We have just adjusted for the change in VMA 441033965Sjdp of the destination, so we must also adjust by the 441133965Sjdp change in VMA of the source. This is done below. */ 441233965Sjdp } 441333965Sjdp 441433965Sjdp /* As described above, we must always adjust a PC relative 441533965Sjdp reloc by the change in VMA of the source. However, if 441633965Sjdp pcrel_offset is set, then the addend does not include the 441733965Sjdp location within the section, in which case we don't need 441833965Sjdp to adjust anything. */ 441933965Sjdp if (howto_table_ext[r_type].pc_relative 442033965Sjdp && ! howto_table_ext[r_type].pcrel_offset) 442133965Sjdp relocation -= (input_section->output_section->vma 442233965Sjdp + input_section->output_offset 442333965Sjdp - input_section->vma); 442433965Sjdp 442533965Sjdp /* Change the addend if necessary. */ 442633965Sjdp if (relocation != 0) 442733965Sjdp PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend); 442833965Sjdp 442933965Sjdp /* Change the address of the relocation. */ 443033965Sjdp PUT_WORD (output_bfd, 443133965Sjdp r_addr + input_section->output_offset, 443233965Sjdp rel->r_address); 443333965Sjdp } 443433965Sjdp else 443533965Sjdp { 4436130561Sobrien bfd_boolean hundef; 443733965Sjdp bfd_reloc_status_type r; 443833965Sjdp 443933965Sjdp /* We are generating an executable, and must do a full 444033965Sjdp relocation. */ 4441130561Sobrien hundef = FALSE; 444260484Sobrien 444333965Sjdp if (r_extern) 444433965Sjdp { 444533965Sjdp h = sym_hashes[r_index]; 444633965Sjdp 4447218822Sdim if (h != NULL 444833965Sjdp && (h->root.type == bfd_link_hash_defined 444933965Sjdp || h->root.type == bfd_link_hash_defweak)) 445033965Sjdp { 445133965Sjdp relocation = (h->root.u.def.value 445233965Sjdp + h->root.u.def.section->output_section->vma 445333965Sjdp + h->root.u.def.section->output_offset); 445433965Sjdp } 4455218822Sdim else if (h != NULL 445633965Sjdp && h->root.type == bfd_link_hash_undefweak) 445733965Sjdp relocation = 0; 445833965Sjdp else 445933965Sjdp { 4460130561Sobrien hundef = TRUE; 446133965Sjdp relocation = 0; 446233965Sjdp } 446333965Sjdp } 4464107492Sobrien else if (r_type == (unsigned int) RELOC_BASE10 4465107492Sobrien || r_type == (unsigned int) RELOC_BASE13 4466107492Sobrien || r_type == (unsigned int) RELOC_BASE22) 446733965Sjdp { 446833965Sjdp struct external_nlist *sym; 446933965Sjdp int type; 447033965Sjdp 447133965Sjdp /* For base relative relocs, r_index is always an index 447233965Sjdp into the symbol table, even if r_extern is 0. */ 447333965Sjdp sym = syms + r_index; 447489857Sobrien type = H_GET_8 (input_bfd, sym->e_type); 447533965Sjdp if ((type & N_TYPE) == N_TEXT 447633965Sjdp || type == N_WEAKT) 447733965Sjdp r_section = obj_textsec (input_bfd); 447833965Sjdp else if ((type & N_TYPE) == N_DATA 447933965Sjdp || type == N_WEAKD) 448033965Sjdp r_section = obj_datasec (input_bfd); 448133965Sjdp else if ((type & N_TYPE) == N_BSS 448233965Sjdp || type == N_WEAKB) 448333965Sjdp r_section = obj_bsssec (input_bfd); 448433965Sjdp else if ((type & N_TYPE) == N_ABS 448533965Sjdp || type == N_WEAKA) 448633965Sjdp r_section = bfd_abs_section_ptr; 448733965Sjdp else 448833965Sjdp abort (); 448933965Sjdp relocation = (r_section->output_section->vma 449033965Sjdp + r_section->output_offset 449133965Sjdp + (GET_WORD (input_bfd, sym->e_value) 449233965Sjdp - r_section->vma)); 449333965Sjdp } 449433965Sjdp else 449533965Sjdp { 449633965Sjdp r_section = aout_reloc_index_to_section (input_bfd, r_index); 449733965Sjdp 449833965Sjdp /* If this is a PC relative reloc, then R_ADDEND is the 449933965Sjdp difference between the two vmas, or 450033965Sjdp old_dest_sec + old_dest_off - (old_src_sec + old_src_off) 450133965Sjdp where 450233965Sjdp old_dest_sec == section->vma 450333965Sjdp and 450433965Sjdp old_src_sec == input_section->vma 450533965Sjdp and 450633965Sjdp old_src_off == r_addr 450733965Sjdp 450833965Sjdp _bfd_final_link_relocate expects RELOCATION + 450933965Sjdp R_ADDEND to be the VMA of the destination minus 451033965Sjdp r_addr (the minus r_addr is because this relocation 451133965Sjdp is not pcrel_offset, which is a bit confusing and 451233965Sjdp should, perhaps, be changed), or 451333965Sjdp new_dest_sec 451433965Sjdp where 451533965Sjdp new_dest_sec == output_section->vma + output_offset 451633965Sjdp We arrange for this to happen by setting RELOCATION to 451733965Sjdp new_dest_sec + old_src_sec - old_dest_sec 451833965Sjdp 451933965Sjdp If this is not a PC relative reloc, then R_ADDEND is 452033965Sjdp simply the VMA of the destination, so we set 452133965Sjdp RELOCATION to the change in the destination VMA, or 452233965Sjdp new_dest_sec - old_dest_sec 452333965Sjdp */ 452433965Sjdp relocation = (r_section->output_section->vma 452533965Sjdp + r_section->output_offset 452633965Sjdp - r_section->vma); 452733965Sjdp if (howto_table_ext[r_type].pc_relative) 452833965Sjdp relocation += input_section->vma; 452933965Sjdp } 453033965Sjdp 453133965Sjdp if (check_dynamic_reloc != NULL) 453233965Sjdp { 4533130561Sobrien bfd_boolean skip; 453433965Sjdp 453533965Sjdp if (! ((*check_dynamic_reloc) 453633965Sjdp (finfo->info, input_bfd, input_section, h, 4537218822Sdim (void *) rel, contents, &skip, &relocation))) 4538130561Sobrien return FALSE; 453933965Sjdp if (skip) 454033965Sjdp continue; 454133965Sjdp } 454233965Sjdp 454333965Sjdp /* Now warn if a global symbol is undefined. We could not 454433965Sjdp do this earlier, because check_dynamic_reloc might want 454533965Sjdp to skip this reloc. */ 454633965Sjdp if (hundef 454733965Sjdp && ! finfo->info->shared 4548107492Sobrien && r_type != (unsigned int) RELOC_BASE10 4549107492Sobrien && r_type != (unsigned int) RELOC_BASE13 4550107492Sobrien && r_type != (unsigned int) RELOC_BASE22) 455133965Sjdp { 455233965Sjdp const char *name; 455333965Sjdp 455433965Sjdp if (h != NULL) 455533965Sjdp name = h->root.root.string; 455633965Sjdp else 455733965Sjdp name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); 455833965Sjdp if (! ((*finfo->info->callbacks->undefined_symbol) 455960484Sobrien (finfo->info, name, input_bfd, input_section, 4560130561Sobrien r_addr, TRUE))) 4561130561Sobrien return FALSE; 456233965Sjdp } 456333965Sjdp 4564107492Sobrien if (r_type != (unsigned int) RELOC_SPARC_REV32) 456560484Sobrien r = MY_final_link_relocate (howto_table_ext + r_type, 456660484Sobrien input_bfd, input_section, 456760484Sobrien contents, r_addr, relocation, 456860484Sobrien r_addend); 456960484Sobrien else 457060484Sobrien { 457160484Sobrien bfd_vma x; 457260484Sobrien 457360484Sobrien x = bfd_get_32 (input_bfd, contents + r_addr); 457460484Sobrien x = x + relocation + r_addend; 457560484Sobrien bfd_putl32 (/*input_bfd,*/ x, contents + r_addr); 457660484Sobrien r = bfd_reloc_ok; 457760484Sobrien } 457860484Sobrien 457933965Sjdp if (r != bfd_reloc_ok) 458033965Sjdp { 458133965Sjdp switch (r) 458233965Sjdp { 458333965Sjdp default: 458433965Sjdp case bfd_reloc_outofrange: 458533965Sjdp abort (); 458633965Sjdp case bfd_reloc_overflow: 458733965Sjdp { 458833965Sjdp const char *name; 458933965Sjdp 459033965Sjdp if (h != NULL) 4591218822Sdim name = NULL; 459233965Sjdp else if (r_extern 4593107492Sobrien || r_type == (unsigned int) RELOC_BASE10 4594107492Sobrien || r_type == (unsigned int) RELOC_BASE13 4595107492Sobrien || r_type == (unsigned int) RELOC_BASE22) 459633965Sjdp name = strings + GET_WORD (input_bfd, 459733965Sjdp syms[r_index].e_strx); 459833965Sjdp else 459933965Sjdp { 460033965Sjdp asection *s; 460133965Sjdp 460233965Sjdp s = aout_reloc_index_to_section (input_bfd, r_index); 460333965Sjdp name = bfd_section_name (input_bfd, s); 460433965Sjdp } 460533965Sjdp if (! ((*finfo->info->callbacks->reloc_overflow) 4606218822Sdim (finfo->info, (h ? &h->root : NULL), name, 4607218822Sdim howto_table_ext[r_type].name, 460833965Sjdp r_addend, input_bfd, input_section, r_addr))) 4609130561Sobrien return FALSE; 461033965Sjdp } 461133965Sjdp break; 461233965Sjdp } 461333965Sjdp } 461433965Sjdp } 461533965Sjdp } 461633965Sjdp 4617130561Sobrien return TRUE; 461833965Sjdp} 461933965Sjdp 4620218822Sdim/* Link an a.out section into the output file. */ 462133965Sjdp 4622130561Sobrienstatic bfd_boolean 4623218822Sdimaout_link_input_section (struct aout_final_link_info *finfo, 4624218822Sdim bfd *input_bfd, 4625218822Sdim asection *input_section, 4626218822Sdim file_ptr *reloff_ptr, 4627218822Sdim bfd_size_type rel_size) 462833965Sjdp{ 4629218822Sdim bfd_size_type input_size; 4630218822Sdim void * relocs; 463133965Sjdp 4632218822Sdim /* Get the section contents. */ 4633218822Sdim input_size = input_section->size; 4634218822Sdim if (! bfd_get_section_contents (input_bfd, input_section, 4635218822Sdim (void *) finfo->contents, 4636218822Sdim (file_ptr) 0, input_size)) 4637218822Sdim return FALSE; 463833965Sjdp 4639218822Sdim /* Read in the relocs if we haven't already done it. */ 4640218822Sdim if (aout_section_data (input_section) != NULL 4641218822Sdim && aout_section_data (input_section)->relocs != NULL) 4642218822Sdim relocs = aout_section_data (input_section)->relocs; 4643218822Sdim else 464433965Sjdp { 4645218822Sdim relocs = finfo->relocs; 4646218822Sdim if (rel_size > 0) 464733965Sjdp { 4648218822Sdim if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 4649218822Sdim || bfd_bread (relocs, rel_size, input_bfd) != rel_size) 4650218822Sdim return FALSE; 465133965Sjdp } 465233965Sjdp } 4653218822Sdim 4654218822Sdim /* Relocate the section contents. */ 4655218822Sdim if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) 4656218822Sdim { 4657218822Sdim if (! aout_link_input_section_std (finfo, input_bfd, input_section, 4658218822Sdim (struct reloc_std_external *) relocs, 4659218822Sdim rel_size, finfo->contents)) 4660218822Sdim return FALSE; 4661218822Sdim } 466233965Sjdp else 466333965Sjdp { 4664218822Sdim if (! aout_link_input_section_ext (finfo, input_bfd, input_section, 4665218822Sdim (struct reloc_ext_external *) relocs, 4666218822Sdim rel_size, finfo->contents)) 4667218822Sdim return FALSE; 4668218822Sdim } 4669218822Sdim 4670218822Sdim /* Write out the section contents. */ 4671218822Sdim if (! bfd_set_section_contents (finfo->output_bfd, 4672218822Sdim input_section->output_section, 4673218822Sdim (void *) finfo->contents, 4674218822Sdim (file_ptr) input_section->output_offset, 4675218822Sdim input_size)) 4676218822Sdim return FALSE; 4677218822Sdim 4678218822Sdim /* If we are producing relocatable output, the relocs were 4679218822Sdim modified, and we now write them out. */ 4680218822Sdim if (finfo->info->relocatable && rel_size > 0) 4681218822Sdim { 4682218822Sdim if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0) 4683218822Sdim return FALSE; 4684218822Sdim if (bfd_bwrite (relocs, rel_size, finfo->output_bfd) != rel_size) 4685218822Sdim return FALSE; 4686218822Sdim *reloff_ptr += rel_size; 4687218822Sdim 4688218822Sdim /* Assert that the relocs have not run into the symbols, and 4689218822Sdim that if these are the text relocs they have not run into the 4690218822Sdim data relocs. */ 4691218822Sdim BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) 4692218822Sdim && (reloff_ptr != &finfo->treloff 4693218822Sdim || (*reloff_ptr 4694218822Sdim <= obj_datasec (finfo->output_bfd)->rel_filepos))); 4695218822Sdim } 4696218822Sdim 4697218822Sdim return TRUE; 4698218822Sdim} 4699218822Sdim 4700218822Sdim/* Adjust and write out the symbols for an a.out file. Set the new 4701218822Sdim symbol indices into a symbol_map. */ 4702218822Sdim 4703218822Sdimstatic bfd_boolean 4704218822Sdimaout_link_write_symbols (struct aout_final_link_info *finfo, bfd *input_bfd) 4705218822Sdim{ 4706218822Sdim bfd *output_bfd; 4707218822Sdim bfd_size_type sym_count; 4708218822Sdim char *strings; 4709218822Sdim enum bfd_link_strip strip; 4710218822Sdim enum bfd_link_discard discard; 4711218822Sdim struct external_nlist *outsym; 4712218822Sdim bfd_size_type strtab_index; 4713218822Sdim struct external_nlist *sym; 4714218822Sdim struct external_nlist *sym_end; 4715218822Sdim struct aout_link_hash_entry **sym_hash; 4716218822Sdim int *symbol_map; 4717218822Sdim bfd_boolean pass; 4718218822Sdim bfd_boolean skip_next; 4719218822Sdim 4720218822Sdim output_bfd = finfo->output_bfd; 4721218822Sdim sym_count = obj_aout_external_sym_count (input_bfd); 4722218822Sdim strings = obj_aout_external_strings (input_bfd); 4723218822Sdim strip = finfo->info->strip; 4724218822Sdim discard = finfo->info->discard; 4725218822Sdim outsym = finfo->output_syms; 4726218822Sdim 4727218822Sdim /* First write out a symbol for this object file, unless we are 4728218822Sdim discarding such symbols. */ 4729218822Sdim if (strip != strip_all 4730218822Sdim && (strip != strip_some 4731218822Sdim || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename, 4732218822Sdim FALSE, FALSE) != NULL) 4733218822Sdim && discard != discard_all) 4734218822Sdim { 4735218822Sdim H_PUT_8 (output_bfd, N_TEXT, outsym->e_type); 4736218822Sdim H_PUT_8 (output_bfd, 0, outsym->e_other); 4737218822Sdim H_PUT_16 (output_bfd, 0, outsym->e_desc); 4738218822Sdim strtab_index = add_to_stringtab (output_bfd, finfo->strtab, 4739218822Sdim input_bfd->filename, FALSE); 4740218822Sdim if (strtab_index == (bfd_size_type) -1) 4741218822Sdim return FALSE; 4742218822Sdim PUT_WORD (output_bfd, strtab_index, outsym->e_strx); 4743218822Sdim PUT_WORD (output_bfd, 4744218822Sdim (bfd_get_section_vma (output_bfd, 4745218822Sdim obj_textsec (input_bfd)->output_section) 4746218822Sdim + obj_textsec (input_bfd)->output_offset), 4747218822Sdim outsym->e_value); 4748218822Sdim ++obj_aout_external_sym_count (output_bfd); 4749218822Sdim ++outsym; 4750218822Sdim } 4751218822Sdim 4752218822Sdim pass = FALSE; 4753218822Sdim skip_next = FALSE; 4754218822Sdim sym = obj_aout_external_syms (input_bfd); 4755218822Sdim sym_end = sym + sym_count; 4756218822Sdim sym_hash = obj_aout_sym_hashes (input_bfd); 4757218822Sdim symbol_map = finfo->symbol_map; 4758218822Sdim memset (symbol_map, 0, (size_t) sym_count * sizeof *symbol_map); 4759218822Sdim for (; sym < sym_end; sym++, sym_hash++, symbol_map++) 4760218822Sdim { 4761218822Sdim const char *name; 4762218822Sdim int type; 476333965Sjdp struct aout_link_hash_entry *h; 4764218822Sdim bfd_boolean skip; 4765218822Sdim asection *symsec; 4766218822Sdim bfd_vma val = 0; 4767218822Sdim bfd_boolean copy; 476833965Sjdp 4769218822Sdim /* We set *symbol_map to 0 above for all symbols. If it has 4770218822Sdim already been set to -1 for this symbol, it means that we are 4771218822Sdim discarding it because it appears in a duplicate header file. 4772218822Sdim See the N_BINCL code below. */ 4773218822Sdim if (*symbol_map == -1) 4774218822Sdim continue; 4775218822Sdim 4776218822Sdim /* Initialize *symbol_map to -1, which means that the symbol was 4777218822Sdim not copied into the output file. We will change it later if 4778218822Sdim we do copy the symbol over. */ 4779218822Sdim *symbol_map = -1; 4780218822Sdim 4781218822Sdim type = H_GET_8 (input_bfd, sym->e_type); 4782218822Sdim name = strings + GET_WORD (input_bfd, sym->e_strx); 4783218822Sdim 4784218822Sdim h = NULL; 4785218822Sdim 4786218822Sdim if (pass) 478733965Sjdp { 4788218822Sdim /* Pass this symbol through. It is the target of an 4789218822Sdim indirect or warning symbol. */ 4790218822Sdim val = GET_WORD (input_bfd, sym->e_value); 4791218822Sdim pass = FALSE; 4792218822Sdim } 4793218822Sdim else if (skip_next) 4794218822Sdim { 4795218822Sdim /* Skip this symbol, which is the target of an indirect 4796218822Sdim symbol that we have changed to no longer be an indirect 479733965Sjdp symbol. */ 4798218822Sdim skip_next = FALSE; 4799218822Sdim continue; 480033965Sjdp } 480133965Sjdp else 480233965Sjdp { 4803218822Sdim struct aout_link_hash_entry *hresolve; 4804218822Sdim 4805218822Sdim /* We have saved the hash table entry for this symbol, if 4806218822Sdim there is one. Note that we could just look it up again 4807218822Sdim in the hash table, provided we first check that it is an 4808218822Sdim external symbol. */ 4809218822Sdim h = *sym_hash; 4810218822Sdim 4811218822Sdim /* Use the name from the hash table, in case the symbol was 4812218822Sdim wrapped. */ 4813218822Sdim if (h != NULL 4814218822Sdim && h->root.type != bfd_link_hash_warning) 4815218822Sdim name = h->root.root.string; 4816218822Sdim 4817218822Sdim /* If this is an indirect or warning symbol, then change 4818218822Sdim hresolve to the base symbol. We also change *sym_hash so 4819218822Sdim that the relocation routines relocate against the real 4820218822Sdim symbol. */ 4821218822Sdim hresolve = h; 4822218822Sdim if (h != (struct aout_link_hash_entry *) NULL 4823218822Sdim && (h->root.type == bfd_link_hash_indirect 4824218822Sdim || h->root.type == bfd_link_hash_warning)) 4825218822Sdim { 4826218822Sdim hresolve = (struct aout_link_hash_entry *) h->root.u.i.link; 4827218822Sdim while (hresolve->root.type == bfd_link_hash_indirect 4828218822Sdim || hresolve->root.type == bfd_link_hash_warning) 4829218822Sdim hresolve = ((struct aout_link_hash_entry *) 4830218822Sdim hresolve->root.u.i.link); 4831218822Sdim *sym_hash = hresolve; 4832218822Sdim } 4833218822Sdim 4834218822Sdim /* If the symbol has already been written out, skip it. */ 4835218822Sdim if (h != NULL 4836218822Sdim && h->written) 4837218822Sdim { 4838218822Sdim if ((type & N_TYPE) == N_INDR 4839218822Sdim || type == N_WARNING) 4840218822Sdim skip_next = TRUE; 4841218822Sdim *symbol_map = h->indx; 4842218822Sdim continue; 4843218822Sdim } 4844218822Sdim 4845218822Sdim /* See if we are stripping this symbol. */ 4846218822Sdim skip = FALSE; 4847218822Sdim switch (strip) 4848218822Sdim { 4849218822Sdim case strip_none: 4850218822Sdim break; 4851218822Sdim case strip_debugger: 4852218822Sdim if ((type & N_STAB) != 0) 4853218822Sdim skip = TRUE; 4854218822Sdim break; 4855218822Sdim case strip_some: 4856218822Sdim if (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE) 4857218822Sdim == NULL) 4858218822Sdim skip = TRUE; 4859218822Sdim break; 4860218822Sdim case strip_all: 4861218822Sdim skip = TRUE; 4862218822Sdim break; 4863218822Sdim } 4864218822Sdim if (skip) 4865218822Sdim { 4866218822Sdim if (h != NULL) 4867218822Sdim h->written = TRUE; 4868218822Sdim continue; 4869218822Sdim } 4870218822Sdim 4871218822Sdim /* Get the value of the symbol. */ 4872218822Sdim if ((type & N_TYPE) == N_TEXT 4873218822Sdim || type == N_WEAKT) 4874218822Sdim symsec = obj_textsec (input_bfd); 4875218822Sdim else if ((type & N_TYPE) == N_DATA 4876218822Sdim || type == N_WEAKD) 4877218822Sdim symsec = obj_datasec (input_bfd); 4878218822Sdim else if ((type & N_TYPE) == N_BSS 4879218822Sdim || type == N_WEAKB) 4880218822Sdim symsec = obj_bsssec (input_bfd); 4881218822Sdim else if ((type & N_TYPE) == N_ABS 4882218822Sdim || type == N_WEAKA) 4883218822Sdim symsec = bfd_abs_section_ptr; 4884218822Sdim else if (((type & N_TYPE) == N_INDR 4885218822Sdim && (hresolve == NULL 4886218822Sdim || (hresolve->root.type != bfd_link_hash_defined 4887218822Sdim && hresolve->root.type != bfd_link_hash_defweak 4888218822Sdim && hresolve->root.type != bfd_link_hash_common))) 4889218822Sdim || type == N_WARNING) 4890218822Sdim { 4891218822Sdim /* Pass the next symbol through unchanged. The 4892218822Sdim condition above for indirect symbols is so that if 4893218822Sdim the indirect symbol was defined, we output it with 4894218822Sdim the correct definition so the debugger will 4895218822Sdim understand it. */ 4896218822Sdim pass = TRUE; 4897218822Sdim val = GET_WORD (input_bfd, sym->e_value); 4898218822Sdim symsec = NULL; 4899218822Sdim } 4900218822Sdim else if ((type & N_STAB) != 0) 4901218822Sdim { 4902218822Sdim val = GET_WORD (input_bfd, sym->e_value); 4903218822Sdim symsec = NULL; 4904218822Sdim } 4905218822Sdim else 4906218822Sdim { 4907218822Sdim /* If we get here with an indirect symbol, it means that 4908218822Sdim we are outputting it with a real definition. In such 4909218822Sdim a case we do not want to output the next symbol, 4910218822Sdim which is the target of the indirection. */ 4911218822Sdim if ((type & N_TYPE) == N_INDR) 4912218822Sdim skip_next = TRUE; 4913218822Sdim 4914218822Sdim symsec = NULL; 4915218822Sdim 4916218822Sdim /* We need to get the value from the hash table. We use 4917218822Sdim hresolve so that if we have defined an indirect 4918218822Sdim symbol we output the final definition. */ 4919218822Sdim if (h == NULL) 4920218822Sdim { 4921218822Sdim switch (type & N_TYPE) 4922218822Sdim { 4923218822Sdim case N_SETT: 4924218822Sdim symsec = obj_textsec (input_bfd); 4925218822Sdim break; 4926218822Sdim case N_SETD: 4927218822Sdim symsec = obj_datasec (input_bfd); 4928218822Sdim break; 4929218822Sdim case N_SETB: 4930218822Sdim symsec = obj_bsssec (input_bfd); 4931218822Sdim break; 4932218822Sdim case N_SETA: 4933218822Sdim symsec = bfd_abs_section_ptr; 4934218822Sdim break; 4935218822Sdim default: 4936218822Sdim val = 0; 4937218822Sdim break; 4938218822Sdim } 4939218822Sdim } 4940218822Sdim else if (hresolve->root.type == bfd_link_hash_defined 4941218822Sdim || hresolve->root.type == bfd_link_hash_defweak) 4942218822Sdim { 4943218822Sdim asection *input_section; 4944218822Sdim asection *output_section; 4945218822Sdim 4946218822Sdim /* This case usually means a common symbol which was 4947218822Sdim turned into a defined symbol. */ 4948218822Sdim input_section = hresolve->root.u.def.section; 4949218822Sdim output_section = input_section->output_section; 4950218822Sdim BFD_ASSERT (bfd_is_abs_section (output_section) 4951218822Sdim || output_section->owner == output_bfd); 4952218822Sdim val = (hresolve->root.u.def.value 4953218822Sdim + bfd_get_section_vma (output_bfd, output_section) 4954218822Sdim + input_section->output_offset); 4955218822Sdim 4956218822Sdim /* Get the correct type based on the section. If 4957218822Sdim this is a constructed set, force it to be 4958218822Sdim globally visible. */ 4959218822Sdim if (type == N_SETT 4960218822Sdim || type == N_SETD 4961218822Sdim || type == N_SETB 4962218822Sdim || type == N_SETA) 4963218822Sdim type |= N_EXT; 4964218822Sdim 4965218822Sdim type &=~ N_TYPE; 4966218822Sdim 4967218822Sdim if (output_section == obj_textsec (output_bfd)) 4968218822Sdim type |= (hresolve->root.type == bfd_link_hash_defined 4969218822Sdim ? N_TEXT 4970218822Sdim : N_WEAKT); 4971218822Sdim else if (output_section == obj_datasec (output_bfd)) 4972218822Sdim type |= (hresolve->root.type == bfd_link_hash_defined 4973218822Sdim ? N_DATA 4974218822Sdim : N_WEAKD); 4975218822Sdim else if (output_section == obj_bsssec (output_bfd)) 4976218822Sdim type |= (hresolve->root.type == bfd_link_hash_defined 4977218822Sdim ? N_BSS 4978218822Sdim : N_WEAKB); 4979218822Sdim else 4980218822Sdim type |= (hresolve->root.type == bfd_link_hash_defined 4981218822Sdim ? N_ABS 4982218822Sdim : N_WEAKA); 4983218822Sdim } 4984218822Sdim else if (hresolve->root.type == bfd_link_hash_common) 4985218822Sdim val = hresolve->root.u.c.size; 4986218822Sdim else if (hresolve->root.type == bfd_link_hash_undefweak) 4987218822Sdim { 4988218822Sdim val = 0; 4989218822Sdim type = N_WEAKU; 4990218822Sdim } 4991218822Sdim else 4992218822Sdim val = 0; 4993218822Sdim } 4994218822Sdim if (symsec != NULL) 4995218822Sdim val = (symsec->output_section->vma 4996218822Sdim + symsec->output_offset 4997218822Sdim + (GET_WORD (input_bfd, sym->e_value) 4998218822Sdim - symsec->vma)); 4999218822Sdim 5000218822Sdim /* If this is a global symbol set the written flag, and if 5001218822Sdim it is a local symbol see if we should discard it. */ 5002218822Sdim if (h != NULL) 5003218822Sdim { 5004218822Sdim h->written = TRUE; 5005218822Sdim h->indx = obj_aout_external_sym_count (output_bfd); 5006218822Sdim } 5007218822Sdim else if ((type & N_TYPE) != N_SETT 5008218822Sdim && (type & N_TYPE) != N_SETD 5009218822Sdim && (type & N_TYPE) != N_SETB 5010218822Sdim && (type & N_TYPE) != N_SETA) 5011218822Sdim { 5012218822Sdim switch (discard) 5013218822Sdim { 5014218822Sdim case discard_none: 5015218822Sdim case discard_sec_merge: 5016218822Sdim break; 5017218822Sdim case discard_l: 5018218822Sdim if ((type & N_STAB) == 0 5019218822Sdim && bfd_is_local_label_name (input_bfd, name)) 5020218822Sdim skip = TRUE; 5021218822Sdim break; 5022218822Sdim case discard_all: 5023218822Sdim skip = TRUE; 5024218822Sdim break; 5025218822Sdim } 5026218822Sdim if (skip) 5027218822Sdim { 5028218822Sdim pass = FALSE; 5029218822Sdim continue; 5030218822Sdim } 5031218822Sdim } 5032218822Sdim 5033218822Sdim /* An N_BINCL symbol indicates the start of the stabs 5034218822Sdim entries for a header file. We need to scan ahead to the 5035218822Sdim next N_EINCL symbol, ignoring nesting, adding up all the 5036218822Sdim characters in the symbol names, not including the file 5037218822Sdim numbers in types (the first number after an open 5038218822Sdim parenthesis). */ 5039218822Sdim if (type == (int) N_BINCL) 5040218822Sdim { 5041218822Sdim struct external_nlist *incl_sym; 5042218822Sdim int nest; 5043218822Sdim struct aout_link_includes_entry *incl_entry; 5044218822Sdim struct aout_link_includes_totals *t; 5045218822Sdim 5046218822Sdim val = 0; 5047218822Sdim nest = 0; 5048218822Sdim for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++) 5049218822Sdim { 5050218822Sdim int incl_type; 5051218822Sdim 5052218822Sdim incl_type = H_GET_8 (input_bfd, incl_sym->e_type); 5053218822Sdim if (incl_type == (int) N_EINCL) 5054218822Sdim { 5055218822Sdim if (nest == 0) 5056218822Sdim break; 5057218822Sdim --nest; 5058218822Sdim } 5059218822Sdim else if (incl_type == (int) N_BINCL) 5060218822Sdim ++nest; 5061218822Sdim else if (nest == 0) 5062218822Sdim { 5063218822Sdim const char *s; 5064218822Sdim 5065218822Sdim s = strings + GET_WORD (input_bfd, incl_sym->e_strx); 5066218822Sdim for (; *s != '\0'; s++) 5067218822Sdim { 5068218822Sdim val += *s; 5069218822Sdim if (*s == '(') 5070218822Sdim { 5071218822Sdim /* Skip the file number. */ 5072218822Sdim ++s; 5073218822Sdim while (ISDIGIT (*s)) 5074218822Sdim ++s; 5075218822Sdim --s; 5076218822Sdim } 5077218822Sdim } 5078218822Sdim } 5079218822Sdim } 5080218822Sdim 5081218822Sdim /* If we have already included a header file with the 5082218822Sdim same value, then replace this one with an N_EXCL 5083218822Sdim symbol. */ 5084218822Sdim copy = (bfd_boolean) (! finfo->info->keep_memory); 5085218822Sdim incl_entry = aout_link_includes_lookup (&finfo->includes, 5086218822Sdim name, TRUE, copy); 5087218822Sdim if (incl_entry == NULL) 5088218822Sdim return FALSE; 5089218822Sdim for (t = incl_entry->totals; t != NULL; t = t->next) 5090218822Sdim if (t->total == val) 5091218822Sdim break; 5092218822Sdim if (t == NULL) 5093218822Sdim { 5094218822Sdim /* This is the first time we have seen this header 5095218822Sdim file with this set of stabs strings. */ 5096218822Sdim t = bfd_hash_allocate (&finfo->includes.root, 5097218822Sdim sizeof *t); 5098218822Sdim if (t == NULL) 5099218822Sdim return FALSE; 5100218822Sdim t->total = val; 5101218822Sdim t->next = incl_entry->totals; 5102218822Sdim incl_entry->totals = t; 5103218822Sdim } 5104218822Sdim else 5105218822Sdim { 5106218822Sdim int *incl_map; 5107218822Sdim 5108218822Sdim /* This is a duplicate header file. We must change 5109218822Sdim it to be an N_EXCL entry, and mark all the 5110218822Sdim included symbols to prevent outputting them. */ 5111218822Sdim type = (int) N_EXCL; 5112218822Sdim 5113218822Sdim nest = 0; 5114218822Sdim for (incl_sym = sym + 1, incl_map = symbol_map + 1; 5115218822Sdim incl_sym < sym_end; 5116218822Sdim incl_sym++, incl_map++) 5117218822Sdim { 5118218822Sdim int incl_type; 5119218822Sdim 5120218822Sdim incl_type = H_GET_8 (input_bfd, incl_sym->e_type); 5121218822Sdim if (incl_type == (int) N_EINCL) 5122218822Sdim { 5123218822Sdim if (nest == 0) 5124218822Sdim { 5125218822Sdim *incl_map = -1; 5126218822Sdim break; 5127218822Sdim } 5128218822Sdim --nest; 5129218822Sdim } 5130218822Sdim else if (incl_type == (int) N_BINCL) 5131218822Sdim ++nest; 5132218822Sdim else if (nest == 0) 5133218822Sdim *incl_map = -1; 5134218822Sdim } 5135218822Sdim } 5136218822Sdim } 513733965Sjdp } 5138218822Sdim 5139218822Sdim /* Copy this symbol into the list of symbols we are going to 5140218822Sdim write out. */ 5141218822Sdim H_PUT_8 (output_bfd, type, outsym->e_type); 5142218822Sdim H_PUT_8 (output_bfd, H_GET_8 (input_bfd, sym->e_other), outsym->e_other); 5143218822Sdim H_PUT_16 (output_bfd, H_GET_16 (input_bfd, sym->e_desc), outsym->e_desc); 5144218822Sdim copy = FALSE; 5145218822Sdim if (! finfo->info->keep_memory) 5146218822Sdim { 5147218822Sdim /* name points into a string table which we are going to 5148218822Sdim free. If there is a hash table entry, use that string. 5149218822Sdim Otherwise, copy name into memory. */ 5150218822Sdim if (h != NULL) 5151218822Sdim name = h->root.root.string; 5152218822Sdim else 5153218822Sdim copy = TRUE; 5154218822Sdim } 5155218822Sdim strtab_index = add_to_stringtab (output_bfd, finfo->strtab, 5156218822Sdim name, copy); 5157218822Sdim if (strtab_index == (bfd_size_type) -1) 5158218822Sdim return FALSE; 5159218822Sdim PUT_WORD (output_bfd, strtab_index, outsym->e_strx); 5160218822Sdim PUT_WORD (output_bfd, val, outsym->e_value); 5161218822Sdim *symbol_map = obj_aout_external_sym_count (output_bfd); 5162218822Sdim ++obj_aout_external_sym_count (output_bfd); 5163218822Sdim ++outsym; 516433965Sjdp } 516533965Sjdp 5166218822Sdim /* Write out the output symbols we have just constructed. */ 5167218822Sdim if (outsym > finfo->output_syms) 516833965Sjdp { 5169218822Sdim bfd_size_type outsym_size; 5170218822Sdim 5171218822Sdim if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0) 5172218822Sdim return FALSE; 5173218822Sdim outsym_size = outsym - finfo->output_syms; 5174218822Sdim outsym_size *= EXTERNAL_NLIST_SIZE; 5175218822Sdim if (bfd_bwrite ((void *) finfo->output_syms, outsym_size, output_bfd) 5176218822Sdim != outsym_size) 5177218822Sdim return FALSE; 5178218822Sdim finfo->symoff += outsym_size; 517933965Sjdp } 518033965Sjdp 5181218822Sdim return TRUE; 5182218822Sdim} 518333965Sjdp 5184218822Sdim/* Link an a.out input BFD into the output file. */ 5185218822Sdim 5186218822Sdimstatic bfd_boolean 5187218822Sdimaout_link_input_bfd (struct aout_final_link_info *finfo, bfd *input_bfd) 5188218822Sdim{ 5189218822Sdim bfd_size_type sym_count; 5190218822Sdim 5191218822Sdim BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object); 5192218822Sdim 5193218822Sdim /* If this is a dynamic object, it may need special handling. */ 5194218822Sdim if ((input_bfd->flags & DYNAMIC) != 0 5195218822Sdim && aout_backend_info (input_bfd)->link_dynamic_object != NULL) 5196218822Sdim return ((*aout_backend_info (input_bfd)->link_dynamic_object) 5197218822Sdim (finfo->info, input_bfd)); 5198218822Sdim 5199218822Sdim /* Get the symbols. We probably have them already, unless 5200218822Sdim finfo->info->keep_memory is FALSE. */ 5201218822Sdim if (! aout_get_external_symbols (input_bfd)) 5202218822Sdim return FALSE; 5203218822Sdim 5204218822Sdim sym_count = obj_aout_external_sym_count (input_bfd); 5205218822Sdim 5206218822Sdim /* Write out the symbols and get a map of the new indices. The map 5207218822Sdim is placed into finfo->symbol_map. */ 5208218822Sdim if (! aout_link_write_symbols (finfo, input_bfd)) 5209218822Sdim return FALSE; 5210218822Sdim 5211218822Sdim /* Relocate and write out the sections. These functions use the 5212218822Sdim symbol map created by aout_link_write_symbols. The linker_mark 5213218822Sdim field will be set if these sections are to be included in the 5214218822Sdim link, which will normally be the case. */ 5215218822Sdim if (obj_textsec (input_bfd)->linker_mark) 521633965Sjdp { 5217218822Sdim if (! aout_link_input_section (finfo, input_bfd, 5218218822Sdim obj_textsec (input_bfd), 5219218822Sdim &finfo->treloff, 5220218822Sdim exec_hdr (input_bfd)->a_trsize)) 5221218822Sdim return FALSE; 5222218822Sdim } 5223218822Sdim if (obj_datasec (input_bfd)->linker_mark) 5224218822Sdim { 5225218822Sdim if (! aout_link_input_section (finfo, input_bfd, 5226218822Sdim obj_datasec (input_bfd), 5227218822Sdim &finfo->dreloff, 5228218822Sdim exec_hdr (input_bfd)->a_drsize)) 5229218822Sdim return FALSE; 5230218822Sdim } 523133965Sjdp 5232218822Sdim /* If we are not keeping memory, we don't need the symbols any 5233218822Sdim longer. We still need them if we are keeping memory, because the 5234218822Sdim strings in the hash table point into them. */ 5235218822Sdim if (! finfo->info->keep_memory) 5236218822Sdim { 5237218822Sdim if (! aout_link_free_symbols (input_bfd)) 5238218822Sdim return FALSE; 5239218822Sdim } 524033965Sjdp 5241218822Sdim return TRUE; 5242218822Sdim} 524333965Sjdp 5244218822Sdim/* Do the final link step. This is called on the output BFD. The 5245218822Sdim INFO structure should point to a list of BFDs linked through the 5246218822Sdim link_next field which can be used to find each BFD which takes part 5247218822Sdim in the output. Also, each section in ABFD should point to a list 5248218822Sdim of bfd_link_order structures which list all the input sections for 5249218822Sdim the output section. */ 5250218822Sdim 5251218822Sdimbfd_boolean 5252218822SdimNAME (aout, final_link) (bfd *abfd, 5253218822Sdim struct bfd_link_info *info, 5254218822Sdim void (*callback) (bfd *, file_ptr *, file_ptr *, file_ptr *)) 5255218822Sdim{ 5256218822Sdim struct aout_final_link_info aout_info; 5257218822Sdim bfd_boolean includes_hash_initialized = FALSE; 5258218822Sdim bfd *sub; 5259218822Sdim bfd_size_type trsize, drsize; 5260218822Sdim bfd_size_type max_contents_size; 5261218822Sdim bfd_size_type max_relocs_size; 5262218822Sdim bfd_size_type max_sym_count; 5263218822Sdim bfd_size_type text_size; 5264218822Sdim file_ptr text_end; 5265218822Sdim struct bfd_link_order *p; 5266218822Sdim asection *o; 5267218822Sdim bfd_boolean have_link_order_relocs; 5268218822Sdim 5269218822Sdim if (info->shared) 5270218822Sdim abfd->flags |= DYNAMIC; 5271218822Sdim 5272218822Sdim aout_info.info = info; 5273218822Sdim aout_info.output_bfd = abfd; 5274218822Sdim aout_info.contents = NULL; 5275218822Sdim aout_info.relocs = NULL; 5276218822Sdim aout_info.symbol_map = NULL; 5277218822Sdim aout_info.output_syms = NULL; 5278218822Sdim 5279218822Sdim if (!bfd_hash_table_init_n (&aout_info.includes.root, 5280218822Sdim aout_link_includes_newfunc, 5281218822Sdim sizeof (struct aout_link_includes_entry), 5282218822Sdim 251)) 5283218822Sdim goto error_return; 5284218822Sdim includes_hash_initialized = TRUE; 5285218822Sdim 5286218822Sdim /* Figure out the largest section size. Also, if generating 5287218822Sdim relocatable output, count the relocs. */ 5288218822Sdim trsize = 0; 5289218822Sdim drsize = 0; 5290218822Sdim max_contents_size = 0; 5291218822Sdim max_relocs_size = 0; 5292218822Sdim max_sym_count = 0; 5293218822Sdim for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) 5294218822Sdim { 5295218822Sdim bfd_size_type sz; 5296218822Sdim 5297218822Sdim if (info->relocatable) 529833965Sjdp { 5299218822Sdim if (bfd_get_flavour (sub) == bfd_target_aout_flavour) 5300218822Sdim { 5301218822Sdim trsize += exec_hdr (sub)->a_trsize; 5302218822Sdim drsize += exec_hdr (sub)->a_drsize; 5303218822Sdim } 5304218822Sdim else 5305218822Sdim { 5306218822Sdim /* FIXME: We need to identify the .text and .data sections 5307218822Sdim and call get_reloc_upper_bound and canonicalize_reloc to 5308218822Sdim work out the number of relocs needed, and then multiply 5309218822Sdim by the reloc size. */ 5310218822Sdim (*_bfd_error_handler) 5311218822Sdim (_("%s: relocatable link from %s to %s not supported"), 5312218822Sdim bfd_get_filename (abfd), 5313218822Sdim sub->xvec->name, abfd->xvec->name); 5314218822Sdim bfd_set_error (bfd_error_invalid_operation); 5315218822Sdim goto error_return; 5316218822Sdim } 5317218822Sdim } 531833965Sjdp 5319218822Sdim if (bfd_get_flavour (sub) == bfd_target_aout_flavour) 5320218822Sdim { 5321218822Sdim sz = obj_textsec (sub)->size; 5322218822Sdim if (sz > max_contents_size) 5323218822Sdim max_contents_size = sz; 5324218822Sdim sz = obj_datasec (sub)->size; 5325218822Sdim if (sz > max_contents_size) 5326218822Sdim max_contents_size = sz; 5327218822Sdim 5328218822Sdim sz = exec_hdr (sub)->a_trsize; 5329218822Sdim if (sz > max_relocs_size) 5330218822Sdim max_relocs_size = sz; 5331218822Sdim sz = exec_hdr (sub)->a_drsize; 5332218822Sdim if (sz > max_relocs_size) 5333218822Sdim max_relocs_size = sz; 5334218822Sdim 5335218822Sdim sz = obj_aout_external_sym_count (sub); 5336218822Sdim if (sz > max_sym_count) 5337218822Sdim max_sym_count = sz; 5338218822Sdim } 5339218822Sdim } 5340218822Sdim 5341218822Sdim if (info->relocatable) 5342218822Sdim { 5343218822Sdim if (obj_textsec (abfd) != NULL) 5344218822Sdim trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd) 5345218822Sdim ->map_head.link_order) 5346218822Sdim * obj_reloc_entry_size (abfd)); 5347218822Sdim if (obj_datasec (abfd) != NULL) 5348218822Sdim drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd) 5349218822Sdim ->map_head.link_order) 5350218822Sdim * obj_reloc_entry_size (abfd)); 5351218822Sdim } 5352218822Sdim 5353218822Sdim exec_hdr (abfd)->a_trsize = trsize; 5354218822Sdim exec_hdr (abfd)->a_drsize = drsize; 5355218822Sdim 5356218822Sdim exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd); 5357218822Sdim 5358218822Sdim /* Adjust the section sizes and vmas according to the magic number. 5359218822Sdim This sets a_text, a_data and a_bss in the exec_hdr and sets the 5360218822Sdim filepos for each section. */ 5361218822Sdim if (! NAME (aout, adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) 5362218822Sdim goto error_return; 5363218822Sdim 5364218822Sdim /* The relocation and symbol file positions differ among a.out 5365218822Sdim targets. We are passed a callback routine from the backend 5366218822Sdim specific code to handle this. 5367218822Sdim FIXME: At this point we do not know how much space the symbol 5368218822Sdim table will require. This will not work for any (nonstandard) 5369218822Sdim a.out target that needs to know the symbol table size before it 5370218822Sdim can compute the relocation file positions. This may or may not 5371218822Sdim be the case for the hp300hpux target, for example. */ 5372218822Sdim (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff, 5373218822Sdim &aout_info.symoff); 5374218822Sdim obj_textsec (abfd)->rel_filepos = aout_info.treloff; 5375218822Sdim obj_datasec (abfd)->rel_filepos = aout_info.dreloff; 5376218822Sdim obj_sym_filepos (abfd) = aout_info.symoff; 5377218822Sdim 5378218822Sdim /* We keep a count of the symbols as we output them. */ 5379218822Sdim obj_aout_external_sym_count (abfd) = 0; 5380218822Sdim 5381218822Sdim /* We accumulate the string table as we write out the symbols. */ 5382218822Sdim aout_info.strtab = _bfd_stringtab_init (); 5383218822Sdim if (aout_info.strtab == NULL) 5384218822Sdim goto error_return; 5385218822Sdim 5386218822Sdim /* Allocate buffers to hold section contents and relocs. */ 5387218822Sdim aout_info.contents = bfd_malloc (max_contents_size); 5388218822Sdim aout_info.relocs = bfd_malloc (max_relocs_size); 5389218822Sdim aout_info.symbol_map = bfd_malloc (max_sym_count * sizeof (int *)); 5390218822Sdim aout_info.output_syms = bfd_malloc ((max_sym_count + 1) 5391218822Sdim * sizeof (struct external_nlist)); 5392218822Sdim if ((aout_info.contents == NULL && max_contents_size != 0) 5393218822Sdim || (aout_info.relocs == NULL && max_relocs_size != 0) 5394218822Sdim || (aout_info.symbol_map == NULL && max_sym_count != 0) 5395218822Sdim || aout_info.output_syms == NULL) 5396218822Sdim goto error_return; 5397218822Sdim 5398218822Sdim /* If we have a symbol named __DYNAMIC, force it out now. This is 5399218822Sdim required by SunOS. Doing this here rather than in sunos.c is a 5400218822Sdim hack, but it's easier than exporting everything which would be 5401218822Sdim needed. */ 5402218822Sdim { 5403218822Sdim struct aout_link_hash_entry *h; 5404218822Sdim 5405218822Sdim h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC", 5406218822Sdim FALSE, FALSE, FALSE); 5407218822Sdim if (h != NULL) 5408218822Sdim aout_link_write_other_symbol (h, &aout_info); 5409218822Sdim } 5410218822Sdim 5411218822Sdim /* The most time efficient way to do the link would be to read all 5412218822Sdim the input object files into memory and then sort out the 5413218822Sdim information into the output file. Unfortunately, that will 5414218822Sdim probably use too much memory. Another method would be to step 5415218822Sdim through everything that composes the text section and write it 5416218822Sdim out, and then everything that composes the data section and write 5417218822Sdim it out, and then write out the relocs, and then write out the 5418218822Sdim symbols. Unfortunately, that requires reading stuff from each 5419218822Sdim input file several times, and we will not be able to keep all the 5420218822Sdim input files open simultaneously, and reopening them will be slow. 5421218822Sdim 5422218822Sdim What we do is basically process one input file at a time. We do 5423218822Sdim everything we need to do with an input file once--copy over the 5424218822Sdim section contents, handle the relocation information, and write 5425218822Sdim out the symbols--and then we throw away the information we read 5426218822Sdim from it. This approach requires a lot of lseeks of the output 5427218822Sdim file, which is unfortunate but still faster than reopening a lot 5428218822Sdim of files. 5429218822Sdim 5430218822Sdim We use the output_has_begun field of the input BFDs to see 5431218822Sdim whether we have already handled it. */ 5432218822Sdim for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) 5433218822Sdim sub->output_has_begun = FALSE; 5434218822Sdim 5435218822Sdim /* Mark all sections which are to be included in the link. This 5436218822Sdim will normally be every section. We need to do this so that we 5437218822Sdim can identify any sections which the linker has decided to not 5438218822Sdim include. */ 5439218822Sdim for (o = abfd->sections; o != NULL; o = o->next) 5440218822Sdim { 5441218822Sdim for (p = o->map_head.link_order; p != NULL; p = p->next) 5442218822Sdim if (p->type == bfd_indirect_link_order) 5443218822Sdim p->u.indirect.section->linker_mark = TRUE; 5444218822Sdim } 5445218822Sdim 5446218822Sdim have_link_order_relocs = FALSE; 5447218822Sdim for (o = abfd->sections; o != NULL; o = o->next) 5448218822Sdim { 5449218822Sdim for (p = o->map_head.link_order; 5450218822Sdim p != NULL; 5451218822Sdim p = p->next) 5452218822Sdim { 5453218822Sdim if (p->type == bfd_indirect_link_order 5454218822Sdim && (bfd_get_flavour (p->u.indirect.section->owner) 5455218822Sdim == bfd_target_aout_flavour)) 545633965Sjdp { 5457218822Sdim bfd *input_bfd; 5458218822Sdim 5459218822Sdim input_bfd = p->u.indirect.section->owner; 5460218822Sdim if (! input_bfd->output_has_begun) 546133965Sjdp { 5462218822Sdim if (! aout_link_input_bfd (&aout_info, input_bfd)) 5463218822Sdim goto error_return; 5464218822Sdim input_bfd->output_has_begun = TRUE; 546533965Sjdp } 546633965Sjdp } 5467218822Sdim else if (p->type == bfd_section_reloc_link_order 5468218822Sdim || p->type == bfd_symbol_reloc_link_order) 5469218822Sdim { 5470218822Sdim /* These are handled below. */ 5471218822Sdim have_link_order_relocs = TRUE; 5472218822Sdim } 5473218822Sdim else 5474218822Sdim { 5475218822Sdim if (! _bfd_default_link_order (abfd, info, o, p)) 5476218822Sdim goto error_return; 5477218822Sdim } 547833965Sjdp } 547933965Sjdp } 5480218822Sdim 5481218822Sdim /* Write out any symbols that we have not already written out. */ 5482218822Sdim aout_link_hash_traverse (aout_hash_table (info), 5483218822Sdim aout_link_write_other_symbol, 5484218822Sdim (void *) &aout_info); 5485218822Sdim 5486218822Sdim /* Now handle any relocs we were asked to create by the linker. 5487218822Sdim These did not come from any input file. We must do these after 5488218822Sdim we have written out all the symbols, so that we know the symbol 5489218822Sdim indices to use. */ 5490218822Sdim if (have_link_order_relocs) 549133965Sjdp { 5492218822Sdim for (o = abfd->sections; o != NULL; o = o->next) 549333965Sjdp { 5494218822Sdim for (p = o->map_head.link_order; 5495218822Sdim p != NULL; 5496218822Sdim p = p->next) 5497218822Sdim { 5498218822Sdim if (p->type == bfd_section_reloc_link_order 5499218822Sdim || p->type == bfd_symbol_reloc_link_order) 5500218822Sdim { 5501218822Sdim if (! aout_link_reloc_link_order (&aout_info, o, p)) 5502218822Sdim goto error_return; 5503218822Sdim } 5504218822Sdim } 550533965Sjdp } 5506218822Sdim } 550733965Sjdp 5508218822Sdim if (aout_info.contents != NULL) 5509218822Sdim { 5510218822Sdim free (aout_info.contents); 5511218822Sdim aout_info.contents = NULL; 5512218822Sdim } 5513218822Sdim if (aout_info.relocs != NULL) 5514218822Sdim { 5515218822Sdim free (aout_info.relocs); 5516218822Sdim aout_info.relocs = NULL; 5517218822Sdim } 5518218822Sdim if (aout_info.symbol_map != NULL) 5519218822Sdim { 5520218822Sdim free (aout_info.symbol_map); 5521218822Sdim aout_info.symbol_map = NULL; 5522218822Sdim } 5523218822Sdim if (aout_info.output_syms != NULL) 5524218822Sdim { 5525218822Sdim free (aout_info.output_syms); 5526218822Sdim aout_info.output_syms = NULL; 5527218822Sdim } 5528218822Sdim if (includes_hash_initialized) 5529218822Sdim { 5530218822Sdim bfd_hash_table_free (&aout_info.includes.root); 5531218822Sdim includes_hash_initialized = FALSE; 5532218822Sdim } 553333965Sjdp 5534218822Sdim /* Finish up any dynamic linking we may be doing. */ 5535218822Sdim if (aout_backend_info (abfd)->finish_dynamic_link != NULL) 5536218822Sdim { 5537218822Sdim if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info)) 5538218822Sdim goto error_return; 553933965Sjdp } 554033965Sjdp 5541218822Sdim /* Update the header information. */ 5542218822Sdim abfd->symcount = obj_aout_external_sym_count (abfd); 5543218822Sdim exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE; 5544218822Sdim obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms; 5545218822Sdim obj_textsec (abfd)->reloc_count = 5546218822Sdim exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); 5547218822Sdim obj_datasec (abfd)->reloc_count = 5548218822Sdim exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); 554933965Sjdp 5550218822Sdim /* Write out the string table, unless there are no symbols. */ 5551218822Sdim if (abfd->symcount > 0) 5552218822Sdim { 5553218822Sdim if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 5554218822Sdim || ! emit_stringtab (abfd, aout_info.strtab)) 5555218822Sdim goto error_return; 5556218822Sdim } 5557218822Sdim else if (obj_textsec (abfd)->reloc_count == 0 5558218822Sdim && obj_datasec (abfd)->reloc_count == 0) 5559218822Sdim { 5560218822Sdim bfd_byte b; 5561218822Sdim file_ptr pos; 556233965Sjdp 5563218822Sdim b = 0; 5564218822Sdim pos = obj_datasec (abfd)->filepos + exec_hdr (abfd)->a_data - 1; 5565218822Sdim if (bfd_seek (abfd, pos, SEEK_SET) != 0 5566218822Sdim || bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1) 5567218822Sdim goto error_return; 5568218822Sdim } 556933965Sjdp 5570130561Sobrien return TRUE; 5571218822Sdim 5572218822Sdim error_return: 5573218822Sdim if (aout_info.contents != NULL) 5574218822Sdim free (aout_info.contents); 5575218822Sdim if (aout_info.relocs != NULL) 5576218822Sdim free (aout_info.relocs); 5577218822Sdim if (aout_info.symbol_map != NULL) 5578218822Sdim free (aout_info.symbol_map); 5579218822Sdim if (aout_info.output_syms != NULL) 5580218822Sdim free (aout_info.output_syms); 5581218822Sdim if (includes_hash_initialized) 5582218822Sdim bfd_hash_table_free (&aout_info.includes.root); 5583218822Sdim return FALSE; 558433965Sjdp} 5585