133965Sjdp/* Routines to link ECOFF debugging information. 2218822Sdim Copyright 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 3218822Sdim 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 433965Sjdp Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>. 533965Sjdp 6130561Sobrien This file is part of BFD, the Binary File Descriptor library. 733965Sjdp 8130561Sobrien This program is free software; you can redistribute it and/or modify 9130561Sobrien it under the terms of the GNU General Public License as published by 10130561Sobrien the Free Software Foundation; either version 2 of the License, or 11130561Sobrien (at your option) any later version. 1233965Sjdp 13130561Sobrien This program is distributed in the hope that it will be useful, 14130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130561Sobrien GNU General Public License for more details. 1733965Sjdp 18130561Sobrien You should have received a copy of the GNU General Public License 19130561Sobrien along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2133965Sjdp 22218822Sdim#include "sysdep.h" 2333965Sjdp#include "bfd.h" 2433965Sjdp#include "bfdlink.h" 2533965Sjdp#include "libbfd.h" 2633965Sjdp#include "objalloc.h" 2733965Sjdp#include "aout/stab_gnu.h" 2833965Sjdp#include "coff/internal.h" 2933965Sjdp#include "coff/sym.h" 3033965Sjdp#include "coff/symconst.h" 3133965Sjdp#include "coff/ecoff.h" 3233965Sjdp#include "libcoff.h" 3333965Sjdp#include "libecoff.h" 3433965Sjdp 35130561Sobrienstatic bfd_boolean ecoff_add_bytes 36130561Sobrien PARAMS ((char **buf, char **bufend, size_t need)); 3733965Sjdpstatic struct bfd_hash_entry *string_hash_newfunc 3833965Sjdp PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, 3933965Sjdp const char *)); 40130561Sobrienstatic void ecoff_align_debug 41130561Sobrien PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, 42130561Sobrien const struct ecoff_debug_swap *swap)); 43130561Sobrienstatic bfd_boolean ecoff_write_symhdr 44130561Sobrien PARAMS ((bfd *, struct ecoff_debug_info *, const struct ecoff_debug_swap *, 45130561Sobrien file_ptr where)); 46130561Sobrienstatic int cmp_fdrtab_entry 47130561Sobrien PARAMS ((const PTR, const PTR)); 48130561Sobrienstatic bfd_boolean mk_fdrtab 4933965Sjdp PARAMS ((bfd *, struct ecoff_debug_info * const, 5033965Sjdp const struct ecoff_debug_swap * const, struct ecoff_find_line *)); 51130561Sobrienstatic long fdrtab_lookup 52130561Sobrien PARAMS ((struct ecoff_find_line *, bfd_vma)); 53130561Sobrienstatic bfd_boolean lookup_line 54130561Sobrien PARAMS ((bfd *, struct ecoff_debug_info * const, 55130561Sobrien const struct ecoff_debug_swap * const, struct ecoff_find_line *)); 5633965Sjdp 5733965Sjdp/* Routines to swap auxiliary information in and out. I am assuming 5833965Sjdp that the auxiliary information format is always going to be target 5933965Sjdp independent. */ 6033965Sjdp 6133965Sjdp/* Swap in a type information record. 6233965Sjdp BIGEND says whether AUX symbols are big-endian or little-endian; this 6333965Sjdp info comes from the file header record (fh-fBigendian). */ 6433965Sjdp 6533965Sjdpvoid 6633965Sjdp_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern) 6733965Sjdp int bigend; 6833965Sjdp const struct tir_ext *ext_copy; 6933965Sjdp TIR *intern; 7033965Sjdp{ 7133965Sjdp struct tir_ext ext[1]; 7233965Sjdp 7333965Sjdp *ext = *ext_copy; /* Make it reasonable to do in-place. */ 7477298Sobrien 7577298Sobrien /* now the fun stuff... */ 7633965Sjdp if (bigend) { 7733965Sjdp intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG); 7833965Sjdp intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG); 7933965Sjdp intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_BIG) 8033965Sjdp >> TIR_BITS1_BT_SH_BIG; 8133965Sjdp intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG) 8233965Sjdp >> TIR_BITS_TQ4_SH_BIG; 8333965Sjdp intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG) 8433965Sjdp >> TIR_BITS_TQ5_SH_BIG; 8533965Sjdp intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG) 8633965Sjdp >> TIR_BITS_TQ0_SH_BIG; 8733965Sjdp intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG) 8833965Sjdp >> TIR_BITS_TQ1_SH_BIG; 8933965Sjdp intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG) 9033965Sjdp >> TIR_BITS_TQ2_SH_BIG; 9133965Sjdp intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG) 9233965Sjdp >> TIR_BITS_TQ3_SH_BIG; 9333965Sjdp } else { 9433965Sjdp intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE); 9533965Sjdp intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE); 9633965Sjdp intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE) 9733965Sjdp >> TIR_BITS1_BT_SH_LITTLE; 9833965Sjdp intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE) 9933965Sjdp >> TIR_BITS_TQ4_SH_LITTLE; 10033965Sjdp intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE) 10133965Sjdp >> TIR_BITS_TQ5_SH_LITTLE; 10233965Sjdp intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE) 10333965Sjdp >> TIR_BITS_TQ0_SH_LITTLE; 10433965Sjdp intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE) 10533965Sjdp >> TIR_BITS_TQ1_SH_LITTLE; 10633965Sjdp intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE) 10733965Sjdp >> TIR_BITS_TQ2_SH_LITTLE; 10833965Sjdp intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE) 10933965Sjdp >> TIR_BITS_TQ3_SH_LITTLE; 11033965Sjdp } 11133965Sjdp 11233965Sjdp#ifdef TEST 11333965Sjdp if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) 11477298Sobrien abort (); 11533965Sjdp#endif 11633965Sjdp} 11733965Sjdp 11833965Sjdp/* Swap out a type information record. 11933965Sjdp BIGEND says whether AUX symbols are big-endian or little-endian; this 12033965Sjdp info comes from the file header record (fh-fBigendian). */ 12133965Sjdp 12233965Sjdpvoid 12333965Sjdp_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext) 12433965Sjdp int bigend; 12533965Sjdp const TIR *intern_copy; 12633965Sjdp struct tir_ext *ext; 12733965Sjdp{ 12833965Sjdp TIR intern[1]; 12933965Sjdp 13033965Sjdp *intern = *intern_copy; /* Make it reasonable to do in-place. */ 13177298Sobrien 13277298Sobrien /* now the fun stuff... */ 13333965Sjdp if (bigend) { 13433965Sjdp ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0) 13533965Sjdp | (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0) 13633965Sjdp | ((intern->bt << TIR_BITS1_BT_SH_BIG) 13733965Sjdp & TIR_BITS1_BT_BIG)); 13833965Sjdp ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG) 13933965Sjdp & TIR_BITS_TQ4_BIG) 14033965Sjdp | ((intern->tq5 << TIR_BITS_TQ5_SH_BIG) 14133965Sjdp & TIR_BITS_TQ5_BIG)); 14233965Sjdp ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG) 14333965Sjdp & TIR_BITS_TQ0_BIG) 14433965Sjdp | ((intern->tq1 << TIR_BITS_TQ1_SH_BIG) 14533965Sjdp & TIR_BITS_TQ1_BIG)); 14633965Sjdp ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG) 14733965Sjdp & TIR_BITS_TQ2_BIG) 14833965Sjdp | ((intern->tq3 << TIR_BITS_TQ3_SH_BIG) 14933965Sjdp & TIR_BITS_TQ3_BIG)); 15033965Sjdp } else { 15133965Sjdp ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0) 15233965Sjdp | (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0) 15333965Sjdp | ((intern->bt << TIR_BITS1_BT_SH_LITTLE) 15433965Sjdp & TIR_BITS1_BT_LITTLE)); 15533965Sjdp ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE) 15633965Sjdp & TIR_BITS_TQ4_LITTLE) 15733965Sjdp | ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE) 15833965Sjdp & TIR_BITS_TQ5_LITTLE)); 15933965Sjdp ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE) 16033965Sjdp & TIR_BITS_TQ0_LITTLE) 16133965Sjdp | ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE) 16233965Sjdp & TIR_BITS_TQ1_LITTLE)); 16333965Sjdp ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE) 16433965Sjdp & TIR_BITS_TQ2_LITTLE) 16533965Sjdp | ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE) 16633965Sjdp & TIR_BITS_TQ3_LITTLE)); 16733965Sjdp } 16833965Sjdp 16933965Sjdp#ifdef TEST 17033965Sjdp if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) 17177298Sobrien abort (); 17233965Sjdp#endif 17333965Sjdp} 17433965Sjdp 17533965Sjdp/* Swap in a relative symbol record. BIGEND says whether it is in 17633965Sjdp big-endian or little-endian format.*/ 17733965Sjdp 17833965Sjdpvoid 17933965Sjdp_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern) 18033965Sjdp int bigend; 18133965Sjdp const struct rndx_ext *ext_copy; 18233965Sjdp RNDXR *intern; 18333965Sjdp{ 18433965Sjdp struct rndx_ext ext[1]; 18533965Sjdp 18633965Sjdp *ext = *ext_copy; /* Make it reasonable to do in-place. */ 18777298Sobrien 18877298Sobrien /* now the fun stuff... */ 18933965Sjdp if (bigend) { 19033965Sjdp intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG) 19133965Sjdp | ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG) 19233965Sjdp >> RNDX_BITS1_RFD_SH_BIG); 19333965Sjdp intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG) 19433965Sjdp << RNDX_BITS1_INDEX_SH_LEFT_BIG) 19533965Sjdp | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG) 19633965Sjdp | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG); 19733965Sjdp } else { 19833965Sjdp intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE) 19933965Sjdp | ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE) 20033965Sjdp << RNDX_BITS1_RFD_SH_LEFT_LITTLE); 20133965Sjdp intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE) 20233965Sjdp >> RNDX_BITS1_INDEX_SH_LITTLE) 20333965Sjdp | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE) 20433965Sjdp | ((unsigned int) ext->r_bits[3] 20533965Sjdp << RNDX_BITS3_INDEX_SH_LEFT_LITTLE); 20633965Sjdp } 20733965Sjdp 20833965Sjdp#ifdef TEST 20933965Sjdp if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) 21077298Sobrien abort (); 21133965Sjdp#endif 21233965Sjdp} 21333965Sjdp 21433965Sjdp/* Swap out a relative symbol record. BIGEND says whether it is in 21533965Sjdp big-endian or little-endian format.*/ 21633965Sjdp 21733965Sjdpvoid 21833965Sjdp_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext) 21933965Sjdp int bigend; 22033965Sjdp const RNDXR *intern_copy; 22133965Sjdp struct rndx_ext *ext; 22233965Sjdp{ 22333965Sjdp RNDXR intern[1]; 22433965Sjdp 22533965Sjdp *intern = *intern_copy; /* Make it reasonable to do in-place. */ 22677298Sobrien 22777298Sobrien /* now the fun stuff... */ 22833965Sjdp if (bigend) { 22933965Sjdp ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG; 23033965Sjdp ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG) 23133965Sjdp & RNDX_BITS1_RFD_BIG) 23233965Sjdp | ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG) 23333965Sjdp & RNDX_BITS1_INDEX_BIG)); 23433965Sjdp ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG; 23533965Sjdp ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG; 23633965Sjdp } else { 23733965Sjdp ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE; 23833965Sjdp ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE) 23933965Sjdp & RNDX_BITS1_RFD_LITTLE) 24033965Sjdp | ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE) 24133965Sjdp & RNDX_BITS1_INDEX_LITTLE)); 24233965Sjdp ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE; 24333965Sjdp ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE; 24433965Sjdp } 24533965Sjdp 24633965Sjdp#ifdef TEST 24733965Sjdp if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) 24877298Sobrien abort (); 24933965Sjdp#endif 25033965Sjdp} 25133965Sjdp 25233965Sjdp/* The minimum amount of data to allocate. */ 25333965Sjdp#define ALLOC_SIZE (4064) 25433965Sjdp 25533965Sjdp/* Add bytes to a buffer. Return success. */ 25633965Sjdp 257130561Sobrienstatic bfd_boolean 25833965Sjdpecoff_add_bytes (buf, bufend, need) 25933965Sjdp char **buf; 26033965Sjdp char **bufend; 26133965Sjdp size_t need; 26233965Sjdp{ 26333965Sjdp size_t have; 26433965Sjdp size_t want; 26533965Sjdp char *newbuf; 26633965Sjdp 26733965Sjdp have = *bufend - *buf; 26833965Sjdp if (have > need) 26933965Sjdp want = ALLOC_SIZE; 27033965Sjdp else 27133965Sjdp { 27233965Sjdp want = need - have; 27333965Sjdp if (want < ALLOC_SIZE) 27433965Sjdp want = ALLOC_SIZE; 27533965Sjdp } 27689857Sobrien newbuf = (char *) bfd_realloc (*buf, (bfd_size_type) have + want); 27733965Sjdp if (newbuf == NULL) 278130561Sobrien return FALSE; 27933965Sjdp *buf = newbuf; 28033965Sjdp *bufend = *buf + have + want; 281130561Sobrien return TRUE; 28233965Sjdp} 28333965Sjdp 28433965Sjdp/* We keep a hash table which maps strings to numbers. We use it to 28533965Sjdp map FDR names to indices in the output file, and to map local 28633965Sjdp strings when combining stabs debugging information. */ 28733965Sjdp 28833965Sjdpstruct string_hash_entry 28933965Sjdp{ 29033965Sjdp struct bfd_hash_entry root; 29133965Sjdp /* FDR index or string table offset. */ 29233965Sjdp long val; 29333965Sjdp /* Next entry in string table. */ 29433965Sjdp struct string_hash_entry *next; 29533965Sjdp}; 29633965Sjdp 29733965Sjdpstruct string_hash_table 29833965Sjdp{ 29933965Sjdp struct bfd_hash_table table; 30033965Sjdp}; 30133965Sjdp 30233965Sjdp/* Routine to create an entry in a string hash table. */ 30333965Sjdp 30433965Sjdpstatic struct bfd_hash_entry * 30533965Sjdpstring_hash_newfunc (entry, table, string) 30633965Sjdp struct bfd_hash_entry *entry; 30733965Sjdp struct bfd_hash_table *table; 30833965Sjdp const char *string; 30933965Sjdp{ 31033965Sjdp struct string_hash_entry *ret = (struct string_hash_entry *) entry; 31133965Sjdp 31233965Sjdp /* Allocate the structure if it has not already been allocated by a 31333965Sjdp subclass. */ 31433965Sjdp if (ret == (struct string_hash_entry *) NULL) 31533965Sjdp ret = ((struct string_hash_entry *) 31633965Sjdp bfd_hash_allocate (table, sizeof (struct string_hash_entry))); 31733965Sjdp if (ret == (struct string_hash_entry *) NULL) 31833965Sjdp return NULL; 31933965Sjdp 32033965Sjdp /* Call the allocation method of the superclass. */ 32133965Sjdp ret = ((struct string_hash_entry *) 32233965Sjdp bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); 32333965Sjdp 32433965Sjdp if (ret) 32533965Sjdp { 32633965Sjdp /* Initialize the local fields. */ 32733965Sjdp ret->val = -1; 32833965Sjdp ret->next = NULL; 32933965Sjdp } 33033965Sjdp 33133965Sjdp return (struct bfd_hash_entry *) ret; 33233965Sjdp} 33333965Sjdp 33433965Sjdp/* Look up an entry in an string hash table. */ 33533965Sjdp 33633965Sjdp#define string_hash_lookup(t, string, create, copy) \ 33733965Sjdp ((struct string_hash_entry *) \ 33833965Sjdp bfd_hash_lookup (&(t)->table, (string), (create), (copy))) 33933965Sjdp 34033965Sjdp/* We can't afford to read in all the debugging information when we do 34133965Sjdp a link. Instead, we build a list of these structures to show how 34233965Sjdp different parts of the input file map to the output file. */ 34333965Sjdp 34433965Sjdpstruct shuffle 34533965Sjdp{ 34633965Sjdp /* The next entry in this linked list. */ 34733965Sjdp struct shuffle *next; 34833965Sjdp /* The length of the information. */ 34933965Sjdp unsigned long size; 35033965Sjdp /* Whether this information comes from a file or not. */ 351130561Sobrien bfd_boolean filep; 35233965Sjdp union 35333965Sjdp { 35433965Sjdp struct 35533965Sjdp { 35633965Sjdp /* The BFD the data comes from. */ 35733965Sjdp bfd *input_bfd; 35833965Sjdp /* The offset within input_bfd. */ 35933965Sjdp file_ptr offset; 36033965Sjdp } file; 36133965Sjdp /* The data to be written out. */ 36233965Sjdp PTR memory; 36333965Sjdp } u; 36433965Sjdp}; 36533965Sjdp 36633965Sjdp/* This structure holds information across calls to 36733965Sjdp bfd_ecoff_debug_accumulate. */ 36833965Sjdp 36933965Sjdpstruct accumulate 37033965Sjdp{ 37133965Sjdp /* The FDR hash table. */ 37233965Sjdp struct string_hash_table fdr_hash; 37333965Sjdp /* The strings hash table. */ 37433965Sjdp struct string_hash_table str_hash; 37533965Sjdp /* Linked lists describing how to shuffle the input debug 37633965Sjdp information into the output file. We keep a pointer to both the 37733965Sjdp head and the tail. */ 37833965Sjdp struct shuffle *line; 37933965Sjdp struct shuffle *line_end; 38033965Sjdp struct shuffle *pdr; 38133965Sjdp struct shuffle *pdr_end; 38233965Sjdp struct shuffle *sym; 38333965Sjdp struct shuffle *sym_end; 38433965Sjdp struct shuffle *opt; 38533965Sjdp struct shuffle *opt_end; 38633965Sjdp struct shuffle *aux; 38733965Sjdp struct shuffle *aux_end; 38833965Sjdp struct shuffle *ss; 38933965Sjdp struct shuffle *ss_end; 39033965Sjdp struct string_hash_entry *ss_hash; 39133965Sjdp struct string_hash_entry *ss_hash_end; 39233965Sjdp struct shuffle *fdr; 39333965Sjdp struct shuffle *fdr_end; 39433965Sjdp struct shuffle *rfd; 39533965Sjdp struct shuffle *rfd_end; 39633965Sjdp /* The size of the largest file shuffle. */ 39733965Sjdp unsigned long largest_file_shuffle; 39833965Sjdp /* An objalloc for debugging information. */ 39933965Sjdp struct objalloc *memory; 40033965Sjdp}; 40133965Sjdp 40233965Sjdp/* Add a file entry to a shuffle list. */ 40333965Sjdp 404130561Sobrienstatic bfd_boolean add_file_shuffle 405130561Sobrien PARAMS ((struct accumulate *, struct shuffle **, struct shuffle **, 406130561Sobrien bfd *, file_ptr, unsigned long)); 40733965Sjdp 408130561Sobrienstatic bfd_boolean 40933965Sjdpadd_file_shuffle (ainfo, head, tail, input_bfd, offset, size) 41033965Sjdp struct accumulate *ainfo; 41133965Sjdp struct shuffle **head; 41233965Sjdp struct shuffle **tail; 41333965Sjdp bfd *input_bfd; 41433965Sjdp file_ptr offset; 41533965Sjdp unsigned long size; 41633965Sjdp{ 41733965Sjdp struct shuffle *n; 41833965Sjdp 41933965Sjdp if (*tail != (struct shuffle *) NULL 42033965Sjdp && (*tail)->filep 42133965Sjdp && (*tail)->u.file.input_bfd == input_bfd 42233965Sjdp && (*tail)->u.file.offset + (*tail)->size == (unsigned long) offset) 42333965Sjdp { 42433965Sjdp /* Just merge this entry onto the existing one. */ 42533965Sjdp (*tail)->size += size; 42633965Sjdp if ((*tail)->size > ainfo->largest_file_shuffle) 42733965Sjdp ainfo->largest_file_shuffle = (*tail)->size; 428130561Sobrien return TRUE; 42933965Sjdp } 43033965Sjdp 43133965Sjdp n = (struct shuffle *) objalloc_alloc (ainfo->memory, 43233965Sjdp sizeof (struct shuffle)); 43333965Sjdp if (!n) 43433965Sjdp { 43533965Sjdp bfd_set_error (bfd_error_no_memory); 436130561Sobrien return FALSE; 43733965Sjdp } 43833965Sjdp n->next = NULL; 43933965Sjdp n->size = size; 440130561Sobrien n->filep = TRUE; 44133965Sjdp n->u.file.input_bfd = input_bfd; 44233965Sjdp n->u.file.offset = offset; 44333965Sjdp if (*head == (struct shuffle *) NULL) 44433965Sjdp *head = n; 44533965Sjdp if (*tail != (struct shuffle *) NULL) 44633965Sjdp (*tail)->next = n; 44733965Sjdp *tail = n; 44833965Sjdp if (size > ainfo->largest_file_shuffle) 44933965Sjdp ainfo->largest_file_shuffle = size; 450130561Sobrien return TRUE; 45133965Sjdp} 45233965Sjdp 45333965Sjdp/* Add a memory entry to a shuffle list. */ 45433965Sjdp 455130561Sobrienstatic bfd_boolean add_memory_shuffle 456130561Sobrien PARAMS ((struct accumulate *, struct shuffle **head, struct shuffle **tail, 457130561Sobrien bfd_byte *data, unsigned long size)); 45833965Sjdp 459130561Sobrienstatic bfd_boolean 46033965Sjdpadd_memory_shuffle (ainfo, head, tail, data, size) 46133965Sjdp struct accumulate *ainfo; 46233965Sjdp struct shuffle **head; 46333965Sjdp struct shuffle **tail; 46433965Sjdp bfd_byte *data; 46533965Sjdp unsigned long size; 46633965Sjdp{ 46733965Sjdp struct shuffle *n; 46877298Sobrien 46933965Sjdp n = (struct shuffle *) objalloc_alloc (ainfo->memory, 47033965Sjdp sizeof (struct shuffle)); 47133965Sjdp if (!n) 47233965Sjdp { 47333965Sjdp bfd_set_error (bfd_error_no_memory); 474130561Sobrien return FALSE; 47533965Sjdp } 47633965Sjdp n->next = NULL; 47733965Sjdp n->size = size; 478130561Sobrien n->filep = FALSE; 47933965Sjdp n->u.memory = (PTR) data; 48033965Sjdp if (*head == (struct shuffle *) NULL) 48133965Sjdp *head = n; 48233965Sjdp if (*tail != (struct shuffle *) NULL) 48333965Sjdp (*tail)->next = n; 48433965Sjdp *tail = n; 485130561Sobrien return TRUE; 48633965Sjdp} 48733965Sjdp 48833965Sjdp/* Initialize the FDR hash table. This returns a handle which is then 48933965Sjdp passed in to bfd_ecoff_debug_accumulate, et. al. */ 49033965Sjdp 49133965SjdpPTR 49233965Sjdpbfd_ecoff_debug_init (output_bfd, output_debug, output_swap, info) 49360484Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 49433965Sjdp struct ecoff_debug_info *output_debug; 49560484Sobrien const struct ecoff_debug_swap *output_swap ATTRIBUTE_UNUSED; 49633965Sjdp struct bfd_link_info *info; 49733965Sjdp{ 49833965Sjdp struct accumulate *ainfo; 49989857Sobrien bfd_size_type amt = sizeof (struct accumulate); 50033965Sjdp 50189857Sobrien ainfo = (struct accumulate *) bfd_malloc (amt); 50233965Sjdp if (!ainfo) 50333965Sjdp return NULL; 504218822Sdim if (!bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc, 505218822Sdim sizeof (struct string_hash_entry), 1021)) 50633965Sjdp return NULL; 50733965Sjdp 50833965Sjdp ainfo->line = NULL; 50933965Sjdp ainfo->line_end = NULL; 51033965Sjdp ainfo->pdr = NULL; 51133965Sjdp ainfo->pdr_end = NULL; 51233965Sjdp ainfo->sym = NULL; 51333965Sjdp ainfo->sym_end = NULL; 51433965Sjdp ainfo->opt = NULL; 51533965Sjdp ainfo->opt_end = NULL; 51633965Sjdp ainfo->aux = NULL; 51733965Sjdp ainfo->aux_end = NULL; 51833965Sjdp ainfo->ss = NULL; 51933965Sjdp ainfo->ss_end = NULL; 52033965Sjdp ainfo->ss_hash = NULL; 52133965Sjdp ainfo->ss_hash_end = NULL; 52233965Sjdp ainfo->fdr = NULL; 52333965Sjdp ainfo->fdr_end = NULL; 52433965Sjdp ainfo->rfd = NULL; 52533965Sjdp ainfo->rfd_end = NULL; 52633965Sjdp 52733965Sjdp ainfo->largest_file_shuffle = 0; 52833965Sjdp 529130561Sobrien if (! info->relocatable) 53033965Sjdp { 531218822Sdim if (!bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc, 532218822Sdim sizeof (struct string_hash_entry))) 53333965Sjdp return NULL; 53433965Sjdp 53533965Sjdp /* The first entry in the string table is the empty string. */ 53633965Sjdp output_debug->symbolic_header.issMax = 1; 53733965Sjdp } 53833965Sjdp 53933965Sjdp ainfo->memory = objalloc_create (); 54033965Sjdp if (ainfo->memory == NULL) 54133965Sjdp { 54233965Sjdp bfd_set_error (bfd_error_no_memory); 54333965Sjdp return NULL; 54433965Sjdp } 54533965Sjdp 54633965Sjdp return (PTR) ainfo; 54733965Sjdp} 54833965Sjdp 54933965Sjdp/* Free the accumulated debugging information. */ 55033965Sjdp 55133965Sjdpvoid 55233965Sjdpbfd_ecoff_debug_free (handle, output_bfd, output_debug, output_swap, info) 55333965Sjdp PTR handle; 55460484Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 55560484Sobrien struct ecoff_debug_info *output_debug ATTRIBUTE_UNUSED; 55660484Sobrien const struct ecoff_debug_swap *output_swap ATTRIBUTE_UNUSED; 55733965Sjdp struct bfd_link_info *info; 55833965Sjdp{ 55933965Sjdp struct accumulate *ainfo = (struct accumulate *) handle; 56077298Sobrien 56133965Sjdp bfd_hash_table_free (&ainfo->fdr_hash.table); 56233965Sjdp 563130561Sobrien if (! info->relocatable) 56433965Sjdp bfd_hash_table_free (&ainfo->str_hash.table); 56533965Sjdp 56633965Sjdp objalloc_free (ainfo->memory); 56733965Sjdp 56833965Sjdp free (ainfo); 56933965Sjdp} 57033965Sjdp 57133965Sjdp/* Accumulate the debugging information from INPUT_BFD into 57233965Sjdp OUTPUT_BFD. The INPUT_DEBUG argument points to some ECOFF 57333965Sjdp debugging information which we want to link into the information 57433965Sjdp pointed to by the OUTPUT_DEBUG argument. OUTPUT_SWAP and 57533965Sjdp INPUT_SWAP point to the swapping information needed. INFO is the 57633965Sjdp linker information structure. HANDLE is returned by 57733965Sjdp bfd_ecoff_debug_init. */ 57833965Sjdp 579130561Sobrienbfd_boolean 58033965Sjdpbfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap, 58133965Sjdp input_bfd, input_debug, input_swap, 58233965Sjdp info) 58333965Sjdp PTR handle; 58433965Sjdp bfd *output_bfd; 58533965Sjdp struct ecoff_debug_info *output_debug; 58633965Sjdp const struct ecoff_debug_swap *output_swap; 58733965Sjdp bfd *input_bfd; 58833965Sjdp struct ecoff_debug_info *input_debug; 58933965Sjdp const struct ecoff_debug_swap *input_swap; 59033965Sjdp struct bfd_link_info *info; 59133965Sjdp{ 59233965Sjdp struct accumulate *ainfo = (struct accumulate *) handle; 59333965Sjdp void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) 59433965Sjdp = input_swap->swap_sym_in; 59533965Sjdp void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)) 59633965Sjdp = input_swap->swap_rfd_in; 59733965Sjdp void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)) 59833965Sjdp = output_swap->swap_sym_out; 59933965Sjdp void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)) 60033965Sjdp = output_swap->swap_fdr_out; 60133965Sjdp void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)) 60233965Sjdp = output_swap->swap_rfd_out; 60333965Sjdp bfd_size_type external_pdr_size = output_swap->external_pdr_size; 60433965Sjdp bfd_size_type external_sym_size = output_swap->external_sym_size; 60533965Sjdp bfd_size_type external_opt_size = output_swap->external_opt_size; 60633965Sjdp bfd_size_type external_fdr_size = output_swap->external_fdr_size; 60733965Sjdp bfd_size_type external_rfd_size = output_swap->external_rfd_size; 60833965Sjdp HDRR * const output_symhdr = &output_debug->symbolic_header; 60933965Sjdp HDRR * const input_symhdr = &input_debug->symbolic_header; 61033965Sjdp bfd_vma section_adjust[scMax]; 61133965Sjdp asection *sec; 61233965Sjdp bfd_byte *fdr_start; 61333965Sjdp bfd_byte *fdr_ptr; 61433965Sjdp bfd_byte *fdr_end; 61533965Sjdp bfd_size_type fdr_add; 61633965Sjdp unsigned int copied; 61733965Sjdp RFDT i; 61833965Sjdp unsigned long sz; 61933965Sjdp bfd_byte *rfd_out; 62033965Sjdp bfd_byte *rfd_in; 62133965Sjdp bfd_byte *rfd_end; 62233965Sjdp long newrfdbase = 0; 62333965Sjdp long oldrfdbase = 0; 62433965Sjdp bfd_byte *fdr_out; 62589857Sobrien bfd_size_type amt; 62633965Sjdp 62733965Sjdp /* Use section_adjust to hold the value to add to a symbol in a 62833965Sjdp particular section. */ 62933965Sjdp memset ((PTR) section_adjust, 0, sizeof section_adjust); 63033965Sjdp 63133965Sjdp#define SET(name, indx) \ 63233965Sjdp sec = bfd_get_section_by_name (input_bfd, name); \ 63333965Sjdp if (sec != NULL) \ 63433965Sjdp section_adjust[indx] = (sec->output_section->vma \ 63533965Sjdp + sec->output_offset \ 63633965Sjdp - sec->vma); 63733965Sjdp 63833965Sjdp SET (".text", scText); 63933965Sjdp SET (".data", scData); 64033965Sjdp SET (".bss", scBss); 64133965Sjdp SET (".sdata", scSData); 64233965Sjdp SET (".sbss", scSBss); 64333965Sjdp /* scRdata section may be either .rdata or .rodata. */ 64433965Sjdp SET (".rdata", scRData); 64533965Sjdp SET (".rodata", scRData); 64633965Sjdp SET (".init", scInit); 64733965Sjdp SET (".fini", scFini); 64833965Sjdp SET (".rconst", scRConst); 64933965Sjdp 65033965Sjdp#undef SET 65133965Sjdp 65233965Sjdp /* Find all the debugging information based on the FDR's. We need 65333965Sjdp to handle them whether they are swapped or not. */ 65433965Sjdp if (input_debug->fdr != (FDR *) NULL) 65533965Sjdp { 65633965Sjdp fdr_start = (bfd_byte *) input_debug->fdr; 65733965Sjdp fdr_add = sizeof (FDR); 65833965Sjdp } 65933965Sjdp else 66033965Sjdp { 66133965Sjdp fdr_start = (bfd_byte *) input_debug->external_fdr; 66233965Sjdp fdr_add = input_swap->external_fdr_size; 66333965Sjdp } 66433965Sjdp fdr_end = fdr_start + input_symhdr->ifdMax * fdr_add; 66533965Sjdp 66689857Sobrien amt = input_symhdr->ifdMax; 66789857Sobrien amt *= sizeof (RFDT); 66889857Sobrien input_debug->ifdmap = (RFDT *) bfd_alloc (input_bfd, amt); 66933965Sjdp 67033965Sjdp sz = (input_symhdr->crfd + input_symhdr->ifdMax) * external_rfd_size; 67133965Sjdp rfd_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); 67233965Sjdp if (!input_debug->ifdmap || !rfd_out) 67333965Sjdp { 67433965Sjdp bfd_set_error (bfd_error_no_memory); 675130561Sobrien return FALSE; 67633965Sjdp } 67733965Sjdp if (!add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz)) 678130561Sobrien return FALSE; 67933965Sjdp 68033965Sjdp copied = 0; 68133965Sjdp 68233965Sjdp /* Look through the FDR's to see which ones we are going to include 68333965Sjdp in the final output. We do not want duplicate FDR information 68433965Sjdp for header files, because ECOFF debugging is often very large. 68533965Sjdp When we find an FDR with no line information which can be merged, 68633965Sjdp we look it up in a hash table to ensure that we only include it 68733965Sjdp once. We keep a table mapping FDR numbers to the final number 68833965Sjdp they get with the BFD, so that we can refer to it when we write 68933965Sjdp out the external symbols. */ 69033965Sjdp for (fdr_ptr = fdr_start, i = 0; 69133965Sjdp fdr_ptr < fdr_end; 69233965Sjdp fdr_ptr += fdr_add, i++, rfd_out += external_rfd_size) 69333965Sjdp { 69433965Sjdp FDR fdr; 69533965Sjdp 69633965Sjdp if (input_debug->fdr != (FDR *) NULL) 69733965Sjdp fdr = *(FDR *) fdr_ptr; 69833965Sjdp else 69933965Sjdp (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr); 70033965Sjdp 70133965Sjdp /* See if this FDR can be merged with an existing one. */ 70233965Sjdp if (fdr.cbLine == 0 && fdr.rss != -1 && fdr.fMerge) 70333965Sjdp { 70433965Sjdp const char *name; 70533965Sjdp char *lookup; 70633965Sjdp struct string_hash_entry *fh; 70733965Sjdp 70833965Sjdp /* We look up a string formed from the file name and the 70938889Sjdp number of symbols and aux entries. Sometimes an include 71038889Sjdp file will conditionally define a typedef or something 71138889Sjdp based on the order of include files. Using the number of 71238889Sjdp symbols and aux entries as a hash reduces the chance that 71338889Sjdp we will merge symbol information that should not be 71438889Sjdp merged. */ 71533965Sjdp name = input_debug->ss + fdr.issBase + fdr.rss; 71633965Sjdp 71789857Sobrien lookup = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 20); 71833965Sjdp if (lookup == NULL) 719130561Sobrien return FALSE; 72038889Sjdp sprintf (lookup, "%s %lx %lx", name, fdr.csym, fdr.caux); 72133965Sjdp 722130561Sobrien fh = string_hash_lookup (&ainfo->fdr_hash, lookup, TRUE, TRUE); 72333965Sjdp free (lookup); 72433965Sjdp if (fh == (struct string_hash_entry *) NULL) 725130561Sobrien return FALSE; 72633965Sjdp 72733965Sjdp if (fh->val != -1) 72833965Sjdp { 72933965Sjdp input_debug->ifdmap[i] = fh->val; 73033965Sjdp (*swap_rfd_out) (output_bfd, input_debug->ifdmap + i, 73133965Sjdp (PTR) rfd_out); 73233965Sjdp 73333965Sjdp /* Don't copy this FDR. */ 73433965Sjdp continue; 73533965Sjdp } 73633965Sjdp 73733965Sjdp fh->val = output_symhdr->ifdMax + copied; 73833965Sjdp } 73933965Sjdp 74033965Sjdp input_debug->ifdmap[i] = output_symhdr->ifdMax + copied; 74133965Sjdp (*swap_rfd_out) (output_bfd, input_debug->ifdmap + i, (PTR) rfd_out); 74233965Sjdp ++copied; 74333965Sjdp } 74433965Sjdp 74533965Sjdp newrfdbase = output_symhdr->crfd; 74633965Sjdp output_symhdr->crfd += input_symhdr->ifdMax; 74733965Sjdp 74833965Sjdp /* Copy over any existing RFD's. RFD's are only created by the 74933965Sjdp linker, so this will only happen for input files which are the 75033965Sjdp result of a partial link. */ 75133965Sjdp rfd_in = (bfd_byte *) input_debug->external_rfd; 75233965Sjdp rfd_end = rfd_in + input_symhdr->crfd * input_swap->external_rfd_size; 75333965Sjdp for (; 75433965Sjdp rfd_in < rfd_end; 75533965Sjdp rfd_in += input_swap->external_rfd_size) 75633965Sjdp { 75733965Sjdp RFDT rfd; 75833965Sjdp 75933965Sjdp (*swap_rfd_in) (input_bfd, (PTR) rfd_in, &rfd); 76033965Sjdp BFD_ASSERT (rfd >= 0 && rfd < input_symhdr->ifdMax); 76133965Sjdp rfd = input_debug->ifdmap[rfd]; 76233965Sjdp (*swap_rfd_out) (output_bfd, &rfd, (PTR) rfd_out); 76333965Sjdp rfd_out += external_rfd_size; 76433965Sjdp } 76533965Sjdp 76633965Sjdp oldrfdbase = output_symhdr->crfd; 76733965Sjdp output_symhdr->crfd += input_symhdr->crfd; 76833965Sjdp 76933965Sjdp /* Look through the FDR's and copy over all associated debugging 77033965Sjdp information. */ 77133965Sjdp sz = copied * external_fdr_size; 77233965Sjdp fdr_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); 77333965Sjdp if (!fdr_out) 77433965Sjdp { 77533965Sjdp bfd_set_error (bfd_error_no_memory); 776130561Sobrien return FALSE; 77733965Sjdp } 77833965Sjdp if (!add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz)) 779130561Sobrien return FALSE; 78033965Sjdp for (fdr_ptr = fdr_start, i = 0; 78133965Sjdp fdr_ptr < fdr_end; 78233965Sjdp fdr_ptr += fdr_add, i++) 78333965Sjdp { 78433965Sjdp FDR fdr; 78533965Sjdp bfd_byte *sym_out; 78633965Sjdp bfd_byte *lraw_src; 78733965Sjdp bfd_byte *lraw_end; 788130561Sobrien bfd_boolean fgotfilename; 78933965Sjdp 79033965Sjdp if (input_debug->ifdmap[i] < output_symhdr->ifdMax) 79133965Sjdp { 79233965Sjdp /* We are not copying this FDR. */ 79333965Sjdp continue; 79433965Sjdp } 79533965Sjdp 79633965Sjdp if (input_debug->fdr != (FDR *) NULL) 79733965Sjdp fdr = *(FDR *) fdr_ptr; 79833965Sjdp else 79933965Sjdp (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr); 80033965Sjdp 80133965Sjdp /* FIXME: It is conceivable that this FDR points to the .init or 80233965Sjdp .fini section, in which case this will not do the right 80333965Sjdp thing. */ 80433965Sjdp fdr.adr += section_adjust[scText]; 80533965Sjdp 80633965Sjdp /* Swap in the local symbols, adjust their values, and swap them 80733965Sjdp out again. */ 808130561Sobrien fgotfilename = FALSE; 80933965Sjdp sz = fdr.csym * external_sym_size; 81033965Sjdp sym_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); 81133965Sjdp if (!sym_out) 81233965Sjdp { 81333965Sjdp bfd_set_error (bfd_error_no_memory); 814130561Sobrien return FALSE; 81533965Sjdp } 81633965Sjdp if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out, 81733965Sjdp sz)) 818130561Sobrien return FALSE; 81933965Sjdp lraw_src = ((bfd_byte *) input_debug->external_sym 82033965Sjdp + fdr.isymBase * input_swap->external_sym_size); 82133965Sjdp lraw_end = lraw_src + fdr.csym * input_swap->external_sym_size; 82233965Sjdp for (; lraw_src < lraw_end; lraw_src += input_swap->external_sym_size) 82333965Sjdp { 82433965Sjdp SYMR internal_sym; 82533965Sjdp 82633965Sjdp (*swap_sym_in) (input_bfd, (PTR) lraw_src, &internal_sym); 82733965Sjdp 82833965Sjdp BFD_ASSERT (internal_sym.sc != scCommon 82933965Sjdp && internal_sym.sc != scSCommon); 83033965Sjdp 83133965Sjdp /* Adjust the symbol value if appropriate. */ 83233965Sjdp switch (internal_sym.st) 83333965Sjdp { 83433965Sjdp case stNil: 83533965Sjdp if (ECOFF_IS_STAB (&internal_sym)) 83633965Sjdp break; 83733965Sjdp /* Fall through. */ 83833965Sjdp case stGlobal: 83933965Sjdp case stStatic: 84033965Sjdp case stLabel: 84133965Sjdp case stProc: 84233965Sjdp case stStaticProc: 84333965Sjdp internal_sym.value += section_adjust[internal_sym.sc]; 84433965Sjdp break; 84533965Sjdp 84633965Sjdp default: 84733965Sjdp break; 84833965Sjdp } 84933965Sjdp 85033965Sjdp /* If we are doing a final link, we hash all the strings in 85133965Sjdp the local symbol table together. This reduces the amount 85233965Sjdp of space required by debugging information. We don't do 853130561Sobrien this when performing a relocatable link because it would 85433965Sjdp prevent us from easily merging different FDR's. */ 855130561Sobrien if (! info->relocatable) 85633965Sjdp { 857130561Sobrien bfd_boolean ffilename; 85833965Sjdp const char *name; 85933965Sjdp 86033965Sjdp if (! fgotfilename && internal_sym.iss == fdr.rss) 861130561Sobrien ffilename = TRUE; 86233965Sjdp else 863130561Sobrien ffilename = FALSE; 86433965Sjdp 86533965Sjdp /* Hash the name into the string table. */ 86633965Sjdp name = input_debug->ss + fdr.issBase + internal_sym.iss; 86733965Sjdp if (*name == '\0') 86833965Sjdp internal_sym.iss = 0; 86933965Sjdp else 87033965Sjdp { 87133965Sjdp struct string_hash_entry *sh; 87233965Sjdp 873130561Sobrien sh = string_hash_lookup (&ainfo->str_hash, name, TRUE, TRUE); 87433965Sjdp if (sh == (struct string_hash_entry *) NULL) 875130561Sobrien return FALSE; 87633965Sjdp if (sh->val == -1) 87733965Sjdp { 87833965Sjdp sh->val = output_symhdr->issMax; 87933965Sjdp output_symhdr->issMax += strlen (name) + 1; 88033965Sjdp if (ainfo->ss_hash == (struct string_hash_entry *) NULL) 88133965Sjdp ainfo->ss_hash = sh; 88233965Sjdp if (ainfo->ss_hash_end 88333965Sjdp != (struct string_hash_entry *) NULL) 88433965Sjdp ainfo->ss_hash_end->next = sh; 88533965Sjdp ainfo->ss_hash_end = sh; 88633965Sjdp } 88733965Sjdp internal_sym.iss = sh->val; 88833965Sjdp } 88933965Sjdp 89033965Sjdp if (ffilename) 89133965Sjdp { 89233965Sjdp fdr.rss = internal_sym.iss; 893130561Sobrien fgotfilename = TRUE; 89433965Sjdp } 89533965Sjdp } 89633965Sjdp 89733965Sjdp (*swap_sym_out) (output_bfd, &internal_sym, sym_out); 89833965Sjdp sym_out += external_sym_size; 89933965Sjdp } 90033965Sjdp 90133965Sjdp fdr.isymBase = output_symhdr->isymMax; 90233965Sjdp output_symhdr->isymMax += fdr.csym; 90333965Sjdp 90433965Sjdp /* Copy the information that does not need swapping. */ 90533965Sjdp 90633965Sjdp /* FIXME: If we are relaxing, we need to adjust the line 90733965Sjdp numbers. Frankly, forget it. Anybody using stabs debugging 90833965Sjdp information will not use this line number information, and 90933965Sjdp stabs are adjusted correctly. */ 91033965Sjdp if (fdr.cbLine > 0) 91133965Sjdp { 91289857Sobrien file_ptr pos = input_symhdr->cbLineOffset + fdr.cbLineOffset; 91333965Sjdp if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end, 91489857Sobrien input_bfd, pos, (unsigned long) fdr.cbLine)) 915130561Sobrien return FALSE; 91633965Sjdp fdr.ilineBase = output_symhdr->ilineMax; 91733965Sjdp fdr.cbLineOffset = output_symhdr->cbLine; 91833965Sjdp output_symhdr->ilineMax += fdr.cline; 91933965Sjdp output_symhdr->cbLine += fdr.cbLine; 92033965Sjdp } 92133965Sjdp if (fdr.caux > 0) 92233965Sjdp { 92389857Sobrien file_ptr pos = (input_symhdr->cbAuxOffset 92489857Sobrien + fdr.iauxBase * sizeof (union aux_ext)); 92533965Sjdp if (!add_file_shuffle (ainfo, &ainfo->aux, &ainfo->aux_end, 92689857Sobrien input_bfd, pos, 92733965Sjdp fdr.caux * sizeof (union aux_ext))) 928130561Sobrien return FALSE; 92933965Sjdp fdr.iauxBase = output_symhdr->iauxMax; 93033965Sjdp output_symhdr->iauxMax += fdr.caux; 93133965Sjdp } 932130561Sobrien if (! info->relocatable) 93333965Sjdp { 93433965Sjdp 93533965Sjdp /* When are are hashing strings, we lie about the number of 93633965Sjdp strings attached to each FDR. We need to set cbSs 93733965Sjdp because some versions of dbx apparently use it to decide 93833965Sjdp how much of the string table to read in. */ 93933965Sjdp fdr.issBase = 0; 94033965Sjdp fdr.cbSs = output_symhdr->issMax; 94133965Sjdp } 94233965Sjdp else if (fdr.cbSs > 0) 94333965Sjdp { 94489857Sobrien file_ptr pos = input_symhdr->cbSsOffset + fdr.issBase; 94533965Sjdp if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, 94689857Sobrien input_bfd, pos, (unsigned long) fdr.cbSs)) 947130561Sobrien return FALSE; 94833965Sjdp fdr.issBase = output_symhdr->issMax; 94933965Sjdp output_symhdr->issMax += fdr.cbSs; 95033965Sjdp } 95133965Sjdp 952218822Sdim if (output_bfd->xvec->header_byteorder 953218822Sdim == input_bfd->xvec->header_byteorder) 95433965Sjdp { 95533965Sjdp /* The two BFD's have the same endianness, and we don't have 95633965Sjdp to adjust the PDR addresses, so simply copying the 95733965Sjdp information will suffice. */ 95833965Sjdp BFD_ASSERT (external_pdr_size == input_swap->external_pdr_size); 95933965Sjdp if (fdr.cpd > 0) 96033965Sjdp { 96189857Sobrien file_ptr pos = (input_symhdr->cbPdOffset 96289857Sobrien + fdr.ipdFirst * external_pdr_size); 96389857Sobrien unsigned long size = fdr.cpd * external_pdr_size; 96433965Sjdp if (!add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, 96589857Sobrien input_bfd, pos, size)) 966130561Sobrien return FALSE; 96733965Sjdp } 96833965Sjdp BFD_ASSERT (external_opt_size == input_swap->external_opt_size); 96933965Sjdp if (fdr.copt > 0) 97033965Sjdp { 97189857Sobrien file_ptr pos = (input_symhdr->cbOptOffset 97289857Sobrien + fdr.ioptBase * external_opt_size); 97389857Sobrien unsigned long size = fdr.copt * external_opt_size; 97433965Sjdp if (!add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, 97589857Sobrien input_bfd, pos, size)) 976130561Sobrien return FALSE; 97733965Sjdp } 97833965Sjdp } 97933965Sjdp else 98033965Sjdp { 98133965Sjdp bfd_size_type outsz, insz; 98233965Sjdp bfd_byte *in; 98333965Sjdp bfd_byte *end; 98433965Sjdp bfd_byte *out; 98533965Sjdp 98633965Sjdp /* The two BFD's have different endianness, so we must swap 98733965Sjdp everything in and out. This code would always work, but 98833965Sjdp it would be unnecessarily slow in the normal case. */ 98933965Sjdp outsz = external_pdr_size; 99033965Sjdp insz = input_swap->external_pdr_size; 99133965Sjdp in = ((bfd_byte *) input_debug->external_pdr 99233965Sjdp + fdr.ipdFirst * insz); 99333965Sjdp end = in + fdr.cpd * insz; 99433965Sjdp sz = fdr.cpd * outsz; 99533965Sjdp out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); 99633965Sjdp if (!out) 99733965Sjdp { 99833965Sjdp bfd_set_error (bfd_error_no_memory); 999130561Sobrien return FALSE; 100033965Sjdp } 100133965Sjdp if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out, 100233965Sjdp sz)) 1003130561Sobrien return FALSE; 100433965Sjdp for (; in < end; in += insz, out += outsz) 100533965Sjdp { 100633965Sjdp PDR pdr; 100733965Sjdp 100833965Sjdp (*input_swap->swap_pdr_in) (input_bfd, (PTR) in, &pdr); 100933965Sjdp (*output_swap->swap_pdr_out) (output_bfd, &pdr, (PTR) out); 101033965Sjdp } 101133965Sjdp 101233965Sjdp /* Swap over the optimization information. */ 101333965Sjdp outsz = external_opt_size; 101433965Sjdp insz = input_swap->external_opt_size; 101533965Sjdp in = ((bfd_byte *) input_debug->external_opt 101633965Sjdp + fdr.ioptBase * insz); 101733965Sjdp end = in + fdr.copt * insz; 101833965Sjdp sz = fdr.copt * outsz; 101933965Sjdp out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); 102033965Sjdp if (!out) 102133965Sjdp { 102233965Sjdp bfd_set_error (bfd_error_no_memory); 1023130561Sobrien return FALSE; 102433965Sjdp } 102533965Sjdp if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out, 102633965Sjdp sz)) 1027130561Sobrien return FALSE; 102833965Sjdp for (; in < end; in += insz, out += outsz) 102933965Sjdp { 103033965Sjdp OPTR opt; 103133965Sjdp 103233965Sjdp (*input_swap->swap_opt_in) (input_bfd, (PTR) in, &opt); 103333965Sjdp (*output_swap->swap_opt_out) (output_bfd, &opt, (PTR) out); 103433965Sjdp } 103533965Sjdp } 103633965Sjdp 103733965Sjdp fdr.ipdFirst = output_symhdr->ipdMax; 103833965Sjdp output_symhdr->ipdMax += fdr.cpd; 103933965Sjdp fdr.ioptBase = output_symhdr->ioptMax; 104033965Sjdp output_symhdr->ioptMax += fdr.copt; 104133965Sjdp 104233965Sjdp if (fdr.crfd <= 0) 104333965Sjdp { 104433965Sjdp /* Point this FDR at the table of RFD's we created. */ 104533965Sjdp fdr.rfdBase = newrfdbase; 104633965Sjdp fdr.crfd = input_symhdr->ifdMax; 104733965Sjdp } 104833965Sjdp else 104933965Sjdp { 105033965Sjdp /* Point this FDR at the remapped RFD's. */ 105133965Sjdp fdr.rfdBase += oldrfdbase; 105233965Sjdp } 105333965Sjdp 105433965Sjdp (*swap_fdr_out) (output_bfd, &fdr, fdr_out); 105533965Sjdp fdr_out += external_fdr_size; 105633965Sjdp ++output_symhdr->ifdMax; 105733965Sjdp } 105833965Sjdp 1059130561Sobrien return TRUE; 106033965Sjdp} 106133965Sjdp 106233965Sjdp/* Add a string to the debugging information we are accumulating. 106333965Sjdp Return the offset from the fdr string base. */ 106433965Sjdp 1065130561Sobrienstatic long ecoff_add_string 1066130561Sobrien PARAMS ((struct accumulate *, struct bfd_link_info *, 1067130561Sobrien struct ecoff_debug_info *, FDR *fdr, const char *string)); 106833965Sjdp 106933965Sjdpstatic long 107033965Sjdpecoff_add_string (ainfo, info, debug, fdr, string) 107133965Sjdp struct accumulate *ainfo; 107233965Sjdp struct bfd_link_info *info; 107333965Sjdp struct ecoff_debug_info *debug; 107433965Sjdp FDR *fdr; 107533965Sjdp const char *string; 107633965Sjdp{ 107733965Sjdp HDRR *symhdr; 107833965Sjdp size_t len; 107933965Sjdp bfd_size_type ret; 108033965Sjdp 108133965Sjdp symhdr = &debug->symbolic_header; 108233965Sjdp len = strlen (string); 1083130561Sobrien if (info->relocatable) 108433965Sjdp { 108533965Sjdp if (!add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string, 108633965Sjdp len + 1)) 108733965Sjdp return -1; 108833965Sjdp ret = symhdr->issMax; 108933965Sjdp symhdr->issMax += len + 1; 109033965Sjdp fdr->cbSs += len + 1; 109133965Sjdp } 109233965Sjdp else 109333965Sjdp { 109433965Sjdp struct string_hash_entry *sh; 109533965Sjdp 1096130561Sobrien sh = string_hash_lookup (&ainfo->str_hash, string, TRUE, TRUE); 109733965Sjdp if (sh == (struct string_hash_entry *) NULL) 109833965Sjdp return -1; 109933965Sjdp if (sh->val == -1) 110033965Sjdp { 110133965Sjdp sh->val = symhdr->issMax; 110233965Sjdp symhdr->issMax += len + 1; 110333965Sjdp if (ainfo->ss_hash == (struct string_hash_entry *) NULL) 110433965Sjdp ainfo->ss_hash = sh; 110533965Sjdp if (ainfo->ss_hash_end 110633965Sjdp != (struct string_hash_entry *) NULL) 110733965Sjdp ainfo->ss_hash_end->next = sh; 110833965Sjdp ainfo->ss_hash_end = sh; 110933965Sjdp } 111033965Sjdp ret = sh->val; 111133965Sjdp } 111233965Sjdp 111333965Sjdp return ret; 111433965Sjdp} 111533965Sjdp 111633965Sjdp/* Add debugging information from a non-ECOFF file. */ 111733965Sjdp 1118130561Sobrienbfd_boolean 111933965Sjdpbfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug, 112033965Sjdp output_swap, input_bfd, info) 112133965Sjdp PTR handle; 112233965Sjdp bfd *output_bfd; 112333965Sjdp struct ecoff_debug_info *output_debug; 112433965Sjdp const struct ecoff_debug_swap *output_swap; 112533965Sjdp bfd *input_bfd; 112633965Sjdp struct bfd_link_info *info; 112733965Sjdp{ 112833965Sjdp struct accumulate *ainfo = (struct accumulate *) handle; 112933965Sjdp void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)) 113033965Sjdp = output_swap->swap_sym_out; 113133965Sjdp HDRR *output_symhdr = &output_debug->symbolic_header; 113233965Sjdp FDR fdr; 113333965Sjdp asection *sec; 113433965Sjdp asymbol **symbols; 113533965Sjdp asymbol **sym_ptr; 113633965Sjdp asymbol **sym_end; 113733965Sjdp long symsize; 113833965Sjdp long symcount; 113933965Sjdp PTR external_fdr; 114033965Sjdp 114133965Sjdp memset ((PTR) &fdr, 0, sizeof fdr); 114233965Sjdp 114333965Sjdp sec = bfd_get_section_by_name (input_bfd, ".text"); 114433965Sjdp if (sec != NULL) 114533965Sjdp fdr.adr = sec->output_section->vma + sec->output_offset; 114633965Sjdp else 114733965Sjdp { 114833965Sjdp /* FIXME: What about .init or .fini? */ 114933965Sjdp fdr.adr = 0; 115033965Sjdp } 115133965Sjdp 115233965Sjdp fdr.issBase = output_symhdr->issMax; 115333965Sjdp fdr.cbSs = 0; 115433965Sjdp fdr.rss = ecoff_add_string (ainfo, info, output_debug, &fdr, 1155218822Sdim input_bfd->filename); 115633965Sjdp if (fdr.rss == -1) 1157130561Sobrien return FALSE; 115833965Sjdp fdr.isymBase = output_symhdr->isymMax; 115933965Sjdp 116033965Sjdp /* Get the local symbols from the input BFD. */ 116133965Sjdp symsize = bfd_get_symtab_upper_bound (input_bfd); 116233965Sjdp if (symsize < 0) 1163130561Sobrien return FALSE; 116489857Sobrien symbols = (asymbol **) bfd_alloc (output_bfd, (bfd_size_type) symsize); 116533965Sjdp if (symbols == (asymbol **) NULL) 1166130561Sobrien return FALSE; 116733965Sjdp symcount = bfd_canonicalize_symtab (input_bfd, symbols); 116833965Sjdp if (symcount < 0) 1169130561Sobrien return FALSE; 117033965Sjdp sym_end = symbols + symcount; 117133965Sjdp 117233965Sjdp /* Handle the local symbols. Any external symbols are handled 117333965Sjdp separately. */ 117433965Sjdp fdr.csym = 0; 117533965Sjdp for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++) 117633965Sjdp { 117733965Sjdp SYMR internal_sym; 117833965Sjdp PTR external_sym; 117933965Sjdp 118033965Sjdp if (((*sym_ptr)->flags & BSF_EXPORT) != 0) 118133965Sjdp continue; 118233965Sjdp memset ((PTR) &internal_sym, 0, sizeof internal_sym); 118333965Sjdp internal_sym.iss = ecoff_add_string (ainfo, info, output_debug, &fdr, 118433965Sjdp (*sym_ptr)->name); 118533965Sjdp 118633965Sjdp if (internal_sym.iss == -1) 1187130561Sobrien return FALSE; 118833965Sjdp if (bfd_is_com_section ((*sym_ptr)->section) 118933965Sjdp || bfd_is_und_section ((*sym_ptr)->section)) 119033965Sjdp internal_sym.value = (*sym_ptr)->value; 119133965Sjdp else 119233965Sjdp internal_sym.value = ((*sym_ptr)->value 119333965Sjdp + (*sym_ptr)->section->output_offset 119433965Sjdp + (*sym_ptr)->section->output_section->vma); 119533965Sjdp internal_sym.st = stNil; 119633965Sjdp internal_sym.sc = scUndefined; 119733965Sjdp internal_sym.index = indexNil; 119833965Sjdp 119933965Sjdp external_sym = (PTR) objalloc_alloc (ainfo->memory, 120033965Sjdp output_swap->external_sym_size); 120133965Sjdp if (!external_sym) 120233965Sjdp { 120333965Sjdp bfd_set_error (bfd_error_no_memory); 1204130561Sobrien return FALSE; 120533965Sjdp } 120633965Sjdp (*swap_sym_out) (output_bfd, &internal_sym, external_sym); 120733965Sjdp add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, 120889857Sobrien external_sym, 120989857Sobrien (unsigned long) output_swap->external_sym_size); 121033965Sjdp ++fdr.csym; 121133965Sjdp ++output_symhdr->isymMax; 121233965Sjdp } 121333965Sjdp 121433965Sjdp bfd_release (output_bfd, (PTR) symbols); 121533965Sjdp 121633965Sjdp /* Leave everything else in the FDR zeroed out. This will cause 121733965Sjdp the lang field to be langC. The fBigendian field will 121833965Sjdp indicate little endian format, but it doesn't matter because 121933965Sjdp it only applies to aux fields and there are none. */ 122033965Sjdp external_fdr = (PTR) objalloc_alloc (ainfo->memory, 122133965Sjdp output_swap->external_fdr_size); 122233965Sjdp if (!external_fdr) 122333965Sjdp { 122433965Sjdp bfd_set_error (bfd_error_no_memory); 1225130561Sobrien return FALSE; 122633965Sjdp } 122733965Sjdp (*output_swap->swap_fdr_out) (output_bfd, &fdr, external_fdr); 122833965Sjdp add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, 122989857Sobrien external_fdr, 123089857Sobrien (unsigned long) output_swap->external_fdr_size); 123133965Sjdp 123233965Sjdp ++output_symhdr->ifdMax; 123333965Sjdp 1234130561Sobrien return TRUE; 123533965Sjdp} 123633965Sjdp 123733965Sjdp/* Set up ECOFF debugging information for the external symbols. 123833965Sjdp FIXME: This is done using a memory buffer, but it should be 123933965Sjdp probably be changed to use a shuffle structure. The assembler uses 124033965Sjdp this interface, so that must be changed to do something else. */ 124133965Sjdp 1242130561Sobrienbfd_boolean 1243130561Sobrienbfd_ecoff_debug_externals (abfd, debug, swap, relocatable, get_extr, 124433965Sjdp set_index) 124533965Sjdp bfd *abfd; 124633965Sjdp struct ecoff_debug_info *debug; 124733965Sjdp const struct ecoff_debug_swap *swap; 1248130561Sobrien bfd_boolean relocatable; 1249130561Sobrien bfd_boolean (*get_extr) PARAMS ((asymbol *, EXTR *)); 125033965Sjdp void (*set_index) PARAMS ((asymbol *, bfd_size_type)); 125133965Sjdp{ 125233965Sjdp HDRR * const symhdr = &debug->symbolic_header; 125333965Sjdp asymbol **sym_ptr_ptr; 125433965Sjdp size_t c; 125533965Sjdp 125633965Sjdp sym_ptr_ptr = bfd_get_outsymbols (abfd); 125733965Sjdp if (sym_ptr_ptr == NULL) 1258130561Sobrien return TRUE; 125933965Sjdp 126033965Sjdp for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++) 126133965Sjdp { 126233965Sjdp asymbol *sym_ptr; 126333965Sjdp EXTR esym; 126433965Sjdp 126533965Sjdp sym_ptr = *sym_ptr_ptr; 126633965Sjdp 126733965Sjdp /* Get the external symbol information. */ 1268104834Sobrien if (! (*get_extr) (sym_ptr, &esym)) 126933965Sjdp continue; 127033965Sjdp 127133965Sjdp /* If we're producing an executable, move common symbols into 127233965Sjdp bss. */ 1273130561Sobrien if (! relocatable) 127433965Sjdp { 127533965Sjdp if (esym.asym.sc == scCommon) 127633965Sjdp esym.asym.sc = scBss; 127733965Sjdp else if (esym.asym.sc == scSCommon) 127833965Sjdp esym.asym.sc = scSBss; 127933965Sjdp } 128033965Sjdp 128133965Sjdp if (bfd_is_com_section (sym_ptr->section) 128233965Sjdp || bfd_is_und_section (sym_ptr->section) 128333965Sjdp || sym_ptr->section->output_section == (asection *) NULL) 128433965Sjdp { 128533965Sjdp /* FIXME: gas does not keep the value of a small undefined 128633965Sjdp symbol in the symbol itself, because of relocation 128733965Sjdp problems. */ 128833965Sjdp if (esym.asym.sc != scSUndefined 128933965Sjdp || esym.asym.value == 0 129033965Sjdp || sym_ptr->value != 0) 129133965Sjdp esym.asym.value = sym_ptr->value; 129233965Sjdp } 129333965Sjdp else 129433965Sjdp esym.asym.value = (sym_ptr->value 129533965Sjdp + sym_ptr->section->output_offset 129633965Sjdp + sym_ptr->section->output_section->vma); 129733965Sjdp 129833965Sjdp if (set_index) 129933965Sjdp (*set_index) (sym_ptr, (bfd_size_type) symhdr->iextMax); 130033965Sjdp 130133965Sjdp if (! bfd_ecoff_debug_one_external (abfd, debug, swap, 130233965Sjdp sym_ptr->name, &esym)) 1303130561Sobrien return FALSE; 130433965Sjdp } 130533965Sjdp 1306130561Sobrien return TRUE; 130733965Sjdp} 130833965Sjdp 130933965Sjdp/* Add a single external symbol to the debugging information. */ 131033965Sjdp 1311130561Sobrienbfd_boolean 131233965Sjdpbfd_ecoff_debug_one_external (abfd, debug, swap, name, esym) 131333965Sjdp bfd *abfd; 131433965Sjdp struct ecoff_debug_info *debug; 131533965Sjdp const struct ecoff_debug_swap *swap; 131633965Sjdp const char *name; 131733965Sjdp EXTR *esym; 131833965Sjdp{ 131933965Sjdp const bfd_size_type external_ext_size = swap->external_ext_size; 132033965Sjdp void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR)) 132133965Sjdp = swap->swap_ext_out; 132233965Sjdp HDRR * const symhdr = &debug->symbolic_header; 132333965Sjdp size_t namelen; 132433965Sjdp 132533965Sjdp namelen = strlen (name); 132633965Sjdp 132733965Sjdp if ((size_t) (debug->ssext_end - debug->ssext) 132833965Sjdp < symhdr->issExtMax + namelen + 1) 132933965Sjdp { 1330104834Sobrien if (! ecoff_add_bytes ((char **) &debug->ssext, 1331104834Sobrien (char **) &debug->ssext_end, 1332104834Sobrien symhdr->issExtMax + namelen + 1)) 1333130561Sobrien return FALSE; 133433965Sjdp } 133533965Sjdp if ((size_t) ((char *) debug->external_ext_end 133633965Sjdp - (char *) debug->external_ext) 133733965Sjdp < (symhdr->iextMax + 1) * external_ext_size) 133833965Sjdp { 1339218822Sdim char *external_ext = debug->external_ext; 1340218822Sdim char *external_ext_end = debug->external_ext_end; 1341218822Sdim if (! ecoff_add_bytes ((char **) &external_ext, 1342218822Sdim (char **) &external_ext_end, 1343104834Sobrien (symhdr->iextMax + 1) * (size_t) external_ext_size)) 1344130561Sobrien return FALSE; 1345218822Sdim debug->external_ext = external_ext; 1346218822Sdim debug->external_ext_end = external_ext_end; 134733965Sjdp } 134833965Sjdp 134933965Sjdp esym->asym.iss = symhdr->issExtMax; 135033965Sjdp 135133965Sjdp (*swap_ext_out) (abfd, esym, 135233965Sjdp ((char *) debug->external_ext 135333965Sjdp + symhdr->iextMax * swap->external_ext_size)); 135433965Sjdp 135533965Sjdp ++symhdr->iextMax; 135633965Sjdp 135733965Sjdp strcpy (debug->ssext + symhdr->issExtMax, name); 135833965Sjdp symhdr->issExtMax += namelen + 1; 135933965Sjdp 1360130561Sobrien return TRUE; 136133965Sjdp} 136233965Sjdp 136333965Sjdp/* Align the ECOFF debugging information. */ 136433965Sjdp 136533965Sjdpstatic void 136633965Sjdpecoff_align_debug (abfd, debug, swap) 136760484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 136833965Sjdp struct ecoff_debug_info *debug; 136933965Sjdp const struct ecoff_debug_swap *swap; 137033965Sjdp{ 137133965Sjdp HDRR * const symhdr = &debug->symbolic_header; 137233965Sjdp bfd_size_type debug_align, aux_align, rfd_align; 137333965Sjdp size_t add; 137433965Sjdp 137533965Sjdp /* Adjust the counts so that structures are aligned. */ 137633965Sjdp debug_align = swap->debug_align; 137733965Sjdp aux_align = debug_align / sizeof (union aux_ext); 137833965Sjdp rfd_align = debug_align / swap->external_rfd_size; 137933965Sjdp 138033965Sjdp add = debug_align - (symhdr->cbLine & (debug_align - 1)); 138133965Sjdp if (add != debug_align) 138233965Sjdp { 138333965Sjdp if (debug->line != (unsigned char *) NULL) 138433965Sjdp memset ((PTR) (debug->line + symhdr->cbLine), 0, add); 138533965Sjdp symhdr->cbLine += add; 138633965Sjdp } 138733965Sjdp 138833965Sjdp add = debug_align - (symhdr->issMax & (debug_align - 1)); 138933965Sjdp if (add != debug_align) 139033965Sjdp { 139133965Sjdp if (debug->ss != (char *) NULL) 139233965Sjdp memset ((PTR) (debug->ss + symhdr->issMax), 0, add); 139333965Sjdp symhdr->issMax += add; 139433965Sjdp } 139533965Sjdp 139633965Sjdp add = debug_align - (symhdr->issExtMax & (debug_align - 1)); 139733965Sjdp if (add != debug_align) 139833965Sjdp { 139933965Sjdp if (debug->ssext != (char *) NULL) 140033965Sjdp memset ((PTR) (debug->ssext + symhdr->issExtMax), 0, add); 140133965Sjdp symhdr->issExtMax += add; 140233965Sjdp } 140333965Sjdp 140433965Sjdp add = aux_align - (symhdr->iauxMax & (aux_align - 1)); 140533965Sjdp if (add != aux_align) 140633965Sjdp { 140733965Sjdp if (debug->external_aux != (union aux_ext *) NULL) 140833965Sjdp memset ((PTR) (debug->external_aux + symhdr->iauxMax), 0, 140933965Sjdp add * sizeof (union aux_ext)); 141033965Sjdp symhdr->iauxMax += add; 141133965Sjdp } 141233965Sjdp 141333965Sjdp add = rfd_align - (symhdr->crfd & (rfd_align - 1)); 141433965Sjdp if (add != rfd_align) 141533965Sjdp { 141633965Sjdp if (debug->external_rfd != (PTR) NULL) 141733965Sjdp memset ((PTR) ((char *) debug->external_rfd 141833965Sjdp + symhdr->crfd * swap->external_rfd_size), 141933965Sjdp 0, (size_t) (add * swap->external_rfd_size)); 142033965Sjdp symhdr->crfd += add; 142133965Sjdp } 142233965Sjdp} 142333965Sjdp 142433965Sjdp/* Return the size required by the ECOFF debugging information. */ 142533965Sjdp 142633965Sjdpbfd_size_type 142733965Sjdpbfd_ecoff_debug_size (abfd, debug, swap) 142833965Sjdp bfd *abfd; 142933965Sjdp struct ecoff_debug_info *debug; 143033965Sjdp const struct ecoff_debug_swap *swap; 143133965Sjdp{ 143233965Sjdp bfd_size_type tot; 143333965Sjdp 143433965Sjdp ecoff_align_debug (abfd, debug, swap); 143533965Sjdp tot = swap->external_hdr_size; 143633965Sjdp 143733965Sjdp#define ADD(count, size) \ 143833965Sjdp tot += debug->symbolic_header.count * size 143933965Sjdp 144033965Sjdp ADD (cbLine, sizeof (unsigned char)); 144133965Sjdp ADD (idnMax, swap->external_dnr_size); 144233965Sjdp ADD (ipdMax, swap->external_pdr_size); 144333965Sjdp ADD (isymMax, swap->external_sym_size); 144433965Sjdp ADD (ioptMax, swap->external_opt_size); 144533965Sjdp ADD (iauxMax, sizeof (union aux_ext)); 144633965Sjdp ADD (issMax, sizeof (char)); 144733965Sjdp ADD (issExtMax, sizeof (char)); 144833965Sjdp ADD (ifdMax, swap->external_fdr_size); 144933965Sjdp ADD (crfd, swap->external_rfd_size); 145033965Sjdp ADD (iextMax, swap->external_ext_size); 145133965Sjdp 145233965Sjdp#undef ADD 145333965Sjdp 145433965Sjdp return tot; 145533965Sjdp} 145633965Sjdp 145733965Sjdp/* Write out the ECOFF symbolic header, given the file position it is 145833965Sjdp going to be placed at. This assumes that the counts are set 145933965Sjdp correctly. */ 146033965Sjdp 1461130561Sobrienstatic bfd_boolean 146233965Sjdpecoff_write_symhdr (abfd, debug, swap, where) 146333965Sjdp bfd *abfd; 146433965Sjdp struct ecoff_debug_info *debug; 146533965Sjdp const struct ecoff_debug_swap *swap; 146633965Sjdp file_ptr where; 146733965Sjdp{ 146833965Sjdp HDRR * const symhdr = &debug->symbolic_header; 146933965Sjdp char *buff = NULL; 147033965Sjdp 147133965Sjdp ecoff_align_debug (abfd, debug, swap); 147233965Sjdp 147333965Sjdp /* Go to the right location in the file. */ 147433965Sjdp if (bfd_seek (abfd, where, SEEK_SET) != 0) 1475130561Sobrien return FALSE; 147633965Sjdp 147733965Sjdp where += swap->external_hdr_size; 147833965Sjdp 147933965Sjdp symhdr->magic = swap->sym_magic; 148033965Sjdp 148133965Sjdp /* Fill in the file offsets. */ 148233965Sjdp#define SET(offset, count, size) \ 148333965Sjdp if (symhdr->count == 0) \ 148433965Sjdp symhdr->offset = 0; \ 148533965Sjdp else \ 148633965Sjdp { \ 148733965Sjdp symhdr->offset = where; \ 148833965Sjdp where += symhdr->count * size; \ 148933965Sjdp } 149033965Sjdp 149133965Sjdp SET (cbLineOffset, cbLine, sizeof (unsigned char)); 149233965Sjdp SET (cbDnOffset, idnMax, swap->external_dnr_size); 149333965Sjdp SET (cbPdOffset, ipdMax, swap->external_pdr_size); 149433965Sjdp SET (cbSymOffset, isymMax, swap->external_sym_size); 149533965Sjdp SET (cbOptOffset, ioptMax, swap->external_opt_size); 149633965Sjdp SET (cbAuxOffset, iauxMax, sizeof (union aux_ext)); 149733965Sjdp SET (cbSsOffset, issMax, sizeof (char)); 149833965Sjdp SET (cbSsExtOffset, issExtMax, sizeof (char)); 149933965Sjdp SET (cbFdOffset, ifdMax, swap->external_fdr_size); 150033965Sjdp SET (cbRfdOffset, crfd, swap->external_rfd_size); 150133965Sjdp SET (cbExtOffset, iextMax, swap->external_ext_size); 150233965Sjdp#undef SET 150333965Sjdp 150489857Sobrien buff = (PTR) bfd_malloc (swap->external_hdr_size); 150533965Sjdp if (buff == NULL && swap->external_hdr_size != 0) 150633965Sjdp goto error_return; 150733965Sjdp 150833965Sjdp (*swap->swap_hdr_out) (abfd, symhdr, buff); 150989857Sobrien if (bfd_bwrite (buff, swap->external_hdr_size, abfd) 151033965Sjdp != swap->external_hdr_size) 151133965Sjdp goto error_return; 151233965Sjdp 151333965Sjdp if (buff != NULL) 151433965Sjdp free (buff); 1515130561Sobrien return TRUE; 151633965Sjdp error_return: 151733965Sjdp if (buff != NULL) 151833965Sjdp free (buff); 1519130561Sobrien return FALSE; 152033965Sjdp} 152133965Sjdp 152233965Sjdp/* Write out the ECOFF debugging information. This function assumes 152333965Sjdp that the information (the pointers and counts) in *DEBUG have been 152433965Sjdp set correctly. WHERE is the position in the file to write the 152533965Sjdp information to. This function fills in the file offsets in the 152633965Sjdp symbolic header. */ 152733965Sjdp 1528130561Sobrienbfd_boolean 152933965Sjdpbfd_ecoff_write_debug (abfd, debug, swap, where) 153033965Sjdp bfd *abfd; 153133965Sjdp struct ecoff_debug_info *debug; 153233965Sjdp const struct ecoff_debug_swap *swap; 153333965Sjdp file_ptr where; 153433965Sjdp{ 153533965Sjdp HDRR * const symhdr = &debug->symbolic_header; 153633965Sjdp 153733965Sjdp if (! ecoff_write_symhdr (abfd, debug, swap, where)) 1538130561Sobrien return FALSE; 153933965Sjdp 154033965Sjdp#define WRITE(ptr, count, size, offset) \ 154133965Sjdp BFD_ASSERT (symhdr->offset == 0 \ 154233965Sjdp || (bfd_vma) bfd_tell (abfd) == symhdr->offset); \ 154389857Sobrien if (bfd_bwrite ((PTR) debug->ptr, (bfd_size_type) size * symhdr->count, abfd)\ 154433965Sjdp != size * symhdr->count) \ 1545130561Sobrien return FALSE; 154633965Sjdp 154733965Sjdp WRITE (line, cbLine, sizeof (unsigned char), cbLineOffset); 154833965Sjdp WRITE (external_dnr, idnMax, swap->external_dnr_size, cbDnOffset); 154933965Sjdp WRITE (external_pdr, ipdMax, swap->external_pdr_size, cbPdOffset); 155033965Sjdp WRITE (external_sym, isymMax, swap->external_sym_size, cbSymOffset); 155133965Sjdp WRITE (external_opt, ioptMax, swap->external_opt_size, cbOptOffset); 155289857Sobrien WRITE (external_aux, iauxMax, (bfd_size_type) sizeof (union aux_ext), 155389857Sobrien cbAuxOffset); 155433965Sjdp WRITE (ss, issMax, sizeof (char), cbSsOffset); 155533965Sjdp WRITE (ssext, issExtMax, sizeof (char), cbSsExtOffset); 155633965Sjdp WRITE (external_fdr, ifdMax, swap->external_fdr_size, cbFdOffset); 155733965Sjdp WRITE (external_rfd, crfd, swap->external_rfd_size, cbRfdOffset); 155833965Sjdp WRITE (external_ext, iextMax, swap->external_ext_size, cbExtOffset); 155933965Sjdp#undef WRITE 156033965Sjdp 1561130561Sobrien return TRUE; 156233965Sjdp} 156333965Sjdp 156433965Sjdp/* Write out a shuffle list. */ 156533965Sjdp 1566130561Sobrienstatic bfd_boolean ecoff_write_shuffle 1567130561Sobrien PARAMS ((bfd *, const struct ecoff_debug_swap *, struct shuffle *, 1568130561Sobrien PTR space)); 156933965Sjdp 1570130561Sobrienstatic bfd_boolean 157133965Sjdpecoff_write_shuffle (abfd, swap, shuffle, space) 157233965Sjdp bfd *abfd; 157333965Sjdp const struct ecoff_debug_swap *swap; 157433965Sjdp struct shuffle *shuffle; 157533965Sjdp PTR space; 157633965Sjdp{ 157733965Sjdp register struct shuffle *l; 157833965Sjdp unsigned long total; 157933965Sjdp 158033965Sjdp total = 0; 158133965Sjdp for (l = shuffle; l != (struct shuffle *) NULL; l = l->next) 158233965Sjdp { 158333965Sjdp if (! l->filep) 158433965Sjdp { 158589857Sobrien if (bfd_bwrite (l->u.memory, (bfd_size_type) l->size, abfd) 158689857Sobrien != l->size) 1587130561Sobrien return FALSE; 158833965Sjdp } 158933965Sjdp else 159033965Sjdp { 159133965Sjdp if (bfd_seek (l->u.file.input_bfd, l->u.file.offset, SEEK_SET) != 0 159289857Sobrien || bfd_bread (space, (bfd_size_type) l->size, 159389857Sobrien l->u.file.input_bfd) != l->size 159489857Sobrien || bfd_bwrite (space, (bfd_size_type) l->size, abfd) != l->size) 1595130561Sobrien return FALSE; 159633965Sjdp } 159733965Sjdp total += l->size; 159833965Sjdp } 159933965Sjdp 160033965Sjdp if ((total & (swap->debug_align - 1)) != 0) 160133965Sjdp { 160233965Sjdp unsigned int i; 160333965Sjdp bfd_byte *s; 160433965Sjdp 160533965Sjdp i = swap->debug_align - (total & (swap->debug_align - 1)); 1606104834Sobrien s = (bfd_byte *) bfd_zmalloc ((bfd_size_type) i); 160733965Sjdp if (s == NULL && i != 0) 1608130561Sobrien return FALSE; 160933965Sjdp 161089857Sobrien if (bfd_bwrite ((PTR) s, (bfd_size_type) i, abfd) != i) 161133965Sjdp { 161233965Sjdp free (s); 1613130561Sobrien return FALSE; 161433965Sjdp } 161533965Sjdp free (s); 161633965Sjdp } 161733965Sjdp 1618130561Sobrien return TRUE; 161933965Sjdp} 162033965Sjdp 162133965Sjdp/* Write out debugging information using accumulated linker 162233965Sjdp information. */ 162333965Sjdp 1624130561Sobrienbfd_boolean 162533965Sjdpbfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where) 162633965Sjdp PTR handle; 162733965Sjdp bfd *abfd; 162833965Sjdp struct ecoff_debug_info *debug; 162933965Sjdp const struct ecoff_debug_swap *swap; 163033965Sjdp struct bfd_link_info *info; 163133965Sjdp file_ptr where; 163233965Sjdp{ 163333965Sjdp struct accumulate *ainfo = (struct accumulate *) handle; 163433965Sjdp PTR space = NULL; 163589857Sobrien bfd_size_type amt; 163633965Sjdp 163733965Sjdp if (! ecoff_write_symhdr (abfd, debug, swap, where)) 163833965Sjdp goto error_return; 163933965Sjdp 164089857Sobrien amt = ainfo->largest_file_shuffle; 164189857Sobrien space = (PTR) bfd_malloc (amt); 164233965Sjdp if (space == NULL && ainfo->largest_file_shuffle != 0) 164333965Sjdp goto error_return; 164433965Sjdp 164533965Sjdp if (! ecoff_write_shuffle (abfd, swap, ainfo->line, space) 164633965Sjdp || ! ecoff_write_shuffle (abfd, swap, ainfo->pdr, space) 164733965Sjdp || ! ecoff_write_shuffle (abfd, swap, ainfo->sym, space) 164833965Sjdp || ! ecoff_write_shuffle (abfd, swap, ainfo->opt, space) 164933965Sjdp || ! ecoff_write_shuffle (abfd, swap, ainfo->aux, space)) 165033965Sjdp goto error_return; 165133965Sjdp 165233965Sjdp /* The string table is written out from the hash table if this is a 165333965Sjdp final link. */ 1654130561Sobrien if (info->relocatable) 165533965Sjdp { 165633965Sjdp BFD_ASSERT (ainfo->ss_hash == (struct string_hash_entry *) NULL); 165733965Sjdp if (! ecoff_write_shuffle (abfd, swap, ainfo->ss, space)) 165833965Sjdp goto error_return; 165933965Sjdp } 166033965Sjdp else 166133965Sjdp { 166233965Sjdp unsigned long total; 166333965Sjdp bfd_byte null; 166433965Sjdp struct string_hash_entry *sh; 166533965Sjdp 166633965Sjdp BFD_ASSERT (ainfo->ss == (struct shuffle *) NULL); 166733965Sjdp null = 0; 166889857Sobrien if (bfd_bwrite ((PTR) &null, (bfd_size_type) 1, abfd) != 1) 166933965Sjdp goto error_return; 167033965Sjdp total = 1; 167133965Sjdp BFD_ASSERT (ainfo->ss_hash == NULL || ainfo->ss_hash->val == 1); 167233965Sjdp for (sh = ainfo->ss_hash; 167333965Sjdp sh != (struct string_hash_entry *) NULL; 167433965Sjdp sh = sh->next) 167533965Sjdp { 167633965Sjdp size_t len; 167733965Sjdp 167833965Sjdp len = strlen (sh->root.string); 167989857Sobrien amt = len + 1; 168089857Sobrien if (bfd_bwrite ((PTR) sh->root.string, amt, abfd) != amt) 168133965Sjdp goto error_return; 168233965Sjdp total += len + 1; 168333965Sjdp } 168433965Sjdp 168533965Sjdp if ((total & (swap->debug_align - 1)) != 0) 168633965Sjdp { 168733965Sjdp unsigned int i; 168833965Sjdp bfd_byte *s; 168933965Sjdp 169033965Sjdp i = swap->debug_align - (total & (swap->debug_align - 1)); 1691104834Sobrien s = (bfd_byte *) bfd_zmalloc ((bfd_size_type) i); 169233965Sjdp if (s == NULL && i != 0) 169333965Sjdp goto error_return; 1694104834Sobrien 169589857Sobrien if (bfd_bwrite ((PTR) s, (bfd_size_type) i, abfd) != i) 169633965Sjdp { 169733965Sjdp free (s); 169833965Sjdp goto error_return; 169933965Sjdp } 170033965Sjdp free (s); 170133965Sjdp } 170233965Sjdp } 170333965Sjdp 170433965Sjdp /* The external strings and symbol are not converted over to using 170533965Sjdp shuffles. FIXME: They probably should be. */ 170689857Sobrien amt = debug->symbolic_header.issExtMax; 170789857Sobrien if (bfd_bwrite (debug->ssext, amt, abfd) != amt) 170833965Sjdp goto error_return; 170933965Sjdp if ((debug->symbolic_header.issExtMax & (swap->debug_align - 1)) != 0) 171033965Sjdp { 171133965Sjdp unsigned int i; 171233965Sjdp bfd_byte *s; 171333965Sjdp 171433965Sjdp i = (swap->debug_align 171533965Sjdp - (debug->symbolic_header.issExtMax & (swap->debug_align - 1))); 1716104834Sobrien s = (bfd_byte *) bfd_zmalloc ((bfd_size_type) i); 171733965Sjdp if (s == NULL && i != 0) 171833965Sjdp goto error_return; 1719104834Sobrien 172089857Sobrien if (bfd_bwrite ((PTR) s, (bfd_size_type) i, abfd) != i) 172133965Sjdp { 172233965Sjdp free (s); 172333965Sjdp goto error_return; 172433965Sjdp } 172533965Sjdp free (s); 172633965Sjdp } 172733965Sjdp 172833965Sjdp if (! ecoff_write_shuffle (abfd, swap, ainfo->fdr, space) 172933965Sjdp || ! ecoff_write_shuffle (abfd, swap, ainfo->rfd, space)) 173033965Sjdp goto error_return; 173133965Sjdp 173233965Sjdp BFD_ASSERT (debug->symbolic_header.cbExtOffset == 0 173333965Sjdp || (debug->symbolic_header.cbExtOffset 173433965Sjdp == (bfd_vma) bfd_tell (abfd))); 173533965Sjdp 173689857Sobrien amt = debug->symbolic_header.iextMax * swap->external_ext_size; 173789857Sobrien if (bfd_bwrite (debug->external_ext, amt, abfd) != amt) 173833965Sjdp goto error_return; 173933965Sjdp 174033965Sjdp if (space != NULL) 174133965Sjdp free (space); 1742130561Sobrien return TRUE; 174333965Sjdp 174433965Sjdp error_return: 174533965Sjdp if (space != NULL) 174633965Sjdp free (space); 1747130561Sobrien return FALSE; 174833965Sjdp} 174933965Sjdp 175033965Sjdp/* Handle the find_nearest_line function for both ECOFF and MIPS ELF 175133965Sjdp files. */ 175233965Sjdp 175333965Sjdp/* Compare FDR entries. This is called via qsort. */ 175433965Sjdp 175533965Sjdpstatic int 175633965Sjdpcmp_fdrtab_entry (leftp, rightp) 175733965Sjdp const PTR leftp; 175833965Sjdp const PTR rightp; 175933965Sjdp{ 176033965Sjdp const struct ecoff_fdrtab_entry *lp = 176133965Sjdp (const struct ecoff_fdrtab_entry *) leftp; 176233965Sjdp const struct ecoff_fdrtab_entry *rp = 176333965Sjdp (const struct ecoff_fdrtab_entry *) rightp; 176433965Sjdp 176533965Sjdp if (lp->base_addr < rp->base_addr) 176633965Sjdp return -1; 176733965Sjdp if (lp->base_addr > rp->base_addr) 176833965Sjdp return 1; 176933965Sjdp return 0; 177033965Sjdp} 177133965Sjdp 177233965Sjdp/* Each file descriptor (FDR) has a memory address, to simplify 177333965Sjdp looking up an FDR by address, we build a table covering all FDRs 177433965Sjdp that have a least one procedure descriptor in them. The final 177533965Sjdp table will be sorted by address so we can look it up via binary 177633965Sjdp search. */ 177733965Sjdp 1778130561Sobrienstatic bfd_boolean 177933965Sjdpmk_fdrtab (abfd, debug_info, debug_swap, line_info) 178033965Sjdp bfd *abfd; 178133965Sjdp struct ecoff_debug_info * const debug_info; 178233965Sjdp const struct ecoff_debug_swap * const debug_swap; 178333965Sjdp struct ecoff_find_line *line_info; 178433965Sjdp{ 178533965Sjdp struct ecoff_fdrtab_entry *tab; 178633965Sjdp FDR *fdr_ptr; 178733965Sjdp FDR *fdr_start; 178833965Sjdp FDR *fdr_end; 1789130561Sobrien bfd_boolean stabs; 179033965Sjdp long len; 179189857Sobrien bfd_size_type amt; 179233965Sjdp 179333965Sjdp fdr_start = debug_info->fdr; 179433965Sjdp fdr_end = fdr_start + debug_info->symbolic_header.ifdMax; 179533965Sjdp 1796130561Sobrien /* First, let's see how long the table needs to be. */ 179733965Sjdp for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) 179833965Sjdp { 1799130561Sobrien if (fdr_ptr->cpd == 0) /* Skip FDRs that have no PDRs. */ 180033965Sjdp continue; 180133965Sjdp ++len; 180233965Sjdp } 180333965Sjdp 1804130561Sobrien /* Now, create and fill in the table. */ 180589857Sobrien amt = (bfd_size_type) len * sizeof (struct ecoff_fdrtab_entry); 180689857Sobrien line_info->fdrtab = (struct ecoff_fdrtab_entry*) bfd_zalloc (abfd, amt); 180733965Sjdp if (line_info->fdrtab == NULL) 1808130561Sobrien return FALSE; 180933965Sjdp line_info->fdrtab_len = len; 181033965Sjdp 181133965Sjdp tab = line_info->fdrtab; 181233965Sjdp for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) 181333965Sjdp { 181433965Sjdp if (fdr_ptr->cpd == 0) 181533965Sjdp continue; 181633965Sjdp 181733965Sjdp /* Check whether this file has stabs debugging information. In 181833965Sjdp a file with stabs debugging information, the second local 181933965Sjdp symbol is named @stabs. */ 1820130561Sobrien stabs = FALSE; 182133965Sjdp if (fdr_ptr->csym >= 2) 182233965Sjdp { 182333965Sjdp char *sym_ptr; 182433965Sjdp SYMR sym; 182533965Sjdp 182633965Sjdp sym_ptr = ((char *) debug_info->external_sym 1827130561Sobrien + (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size); 182833965Sjdp (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); 182933965Sjdp if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, 183033965Sjdp STABS_SYMBOL) == 0) 1831130561Sobrien stabs = TRUE; 183233965Sjdp } 183333965Sjdp 183433965Sjdp if (!stabs) 183533965Sjdp { 1836130561Sobrien /* eraxxon: There are at least two problems with this computation: 1837130561Sobrien 1) PDRs do *not* contain offsets but full vma's; and typically the 1838130561Sobrien address of the first PDR is the address of the FDR, which will 1839130561Sobrien make (most) of the results of the original computation 0! 1840130561Sobrien 2) Once in a wacky while, the Compaq compiler generated PDR 1841130561Sobrien addresses do not equal the FDR vma, but they (the PDR address) 1842130561Sobrien are still vma's and not offsets. Cf. comments in 1843130561Sobrien 'lookup_line'. */ 184433965Sjdp /* The address of the first PDR is the offset of that 184533965Sjdp procedure relative to the beginning of file FDR. */ 1846130561Sobrien tab->base_addr = fdr_ptr->adr; 184733965Sjdp } 184833965Sjdp else 184933965Sjdp { 185033965Sjdp /* XXX I don't know about stabs, so this is a guess 1851130561Sobrien (davidm@cs.arizona.edu). */ 185233965Sjdp tab->base_addr = fdr_ptr->adr; 185333965Sjdp } 185433965Sjdp tab->fdr = fdr_ptr; 185533965Sjdp ++tab; 185633965Sjdp } 185733965Sjdp 185833965Sjdp /* Finally, the table is sorted in increasing memory-address order. 185933965Sjdp The table is mostly sorted already, but there are cases (e.g., 186033965Sjdp static functions in include files), where this does not hold. 186133965Sjdp Use "odump -PFv" to verify... */ 186289857Sobrien qsort ((PTR) line_info->fdrtab, (size_t) len, 186333965Sjdp sizeof (struct ecoff_fdrtab_entry), cmp_fdrtab_entry); 186433965Sjdp 1865130561Sobrien return TRUE; 186633965Sjdp} 186733965Sjdp 186833965Sjdp/* Return index of first FDR that covers to OFFSET. */ 186933965Sjdp 187033965Sjdpstatic long 187133965Sjdpfdrtab_lookup (line_info, offset) 187233965Sjdp struct ecoff_find_line *line_info; 187333965Sjdp bfd_vma offset; 187433965Sjdp{ 187533965Sjdp long low, high, len; 187633965Sjdp long mid = -1; 187733965Sjdp struct ecoff_fdrtab_entry *tab; 187833965Sjdp 187933965Sjdp len = line_info->fdrtab_len; 188033965Sjdp if (len == 0) 188133965Sjdp return -1; 188233965Sjdp 188333965Sjdp tab = line_info->fdrtab; 188433965Sjdp for (low = 0, high = len - 1 ; low != high ;) 188533965Sjdp { 188633965Sjdp mid = (high + low) / 2; 188733965Sjdp if (offset >= tab[mid].base_addr && offset < tab[mid + 1].base_addr) 188833965Sjdp goto find_min; 188933965Sjdp 189033965Sjdp if (tab[mid].base_addr > offset) 189133965Sjdp high = mid; 189233965Sjdp else 189333965Sjdp low = mid + 1; 189433965Sjdp } 1895130561Sobrien 1896130561Sobrien /* eraxxon: at this point 'offset' is either lower than the lowest entry or 1897130561Sobrien higher than the highest entry. In the former case high = low = mid = 0; 1898130561Sobrien we want to return -1. In the latter case, low = high and mid = low - 1; 1899130561Sobrien we want to return the index of the highest entry. Only in former case 1900130561Sobrien will the following 'catch-all' test be true. */ 190133965Sjdp ++mid; 190233965Sjdp 1903130561Sobrien /* Last entry is catch-all for all higher addresses. */ 190433965Sjdp if (offset < tab[mid].base_addr) 190533965Sjdp return -1; 190633965Sjdp 190733965Sjdp find_min: 190833965Sjdp 1909130561Sobrien /* eraxxon: There may be multiple FDRs in the table with the 1910130561Sobrien same base_addr; make sure that we are at the first one. */ 191133965Sjdp while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr) 191233965Sjdp --mid; 191333965Sjdp 191433965Sjdp return mid; 191533965Sjdp} 191633965Sjdp 191733965Sjdp/* Look up a line given an address, storing the information in 191833965Sjdp LINE_INFO->cache. */ 191933965Sjdp 1920130561Sobrienstatic bfd_boolean 192133965Sjdplookup_line (abfd, debug_info, debug_swap, line_info) 192233965Sjdp bfd *abfd; 192333965Sjdp struct ecoff_debug_info * const debug_info; 192433965Sjdp const struct ecoff_debug_swap * const debug_swap; 192533965Sjdp struct ecoff_find_line *line_info; 192633965Sjdp{ 192733965Sjdp struct ecoff_fdrtab_entry *tab; 192833965Sjdp bfd_vma offset; 1929130561Sobrien bfd_boolean stabs; 193033965Sjdp FDR *fdr_ptr; 193133965Sjdp int i; 193277298Sobrien 1933130561Sobrien /* eraxxon: note that 'offset' is the full vma, not a section offset. */ 193433965Sjdp offset = line_info->cache.start; 193577298Sobrien 193633965Sjdp /* Build FDR table (sorted by object file's base-address) if we 193733965Sjdp don't have it already. */ 193833965Sjdp if (line_info->fdrtab == NULL 193933965Sjdp && !mk_fdrtab (abfd, debug_info, debug_swap, line_info)) 1940130561Sobrien return FALSE; 194133965Sjdp 194233965Sjdp tab = line_info->fdrtab; 194333965Sjdp 1944130561Sobrien /* Find first FDR for address OFFSET. */ 194533965Sjdp i = fdrtab_lookup (line_info, offset); 194633965Sjdp if (i < 0) 1947130561Sobrien return FALSE; /* no FDR, no fun... */ 1948130561Sobrien 1949130561Sobrien /* eraxxon: 'fdrtab_lookup' doesn't give what we want, at least for Compaq's 1950130561Sobrien C++ compiler 6.2. Consider three FDRs with starting addresses of x, y, 1951130561Sobrien and z, respectively, such that x < y < z. Assume further that 1952130561Sobrien y < 'offset' < z. It is possible at times that the PDR for 'offset' is 1953130561Sobrien associated with FDR x and *not* with FDR y. Erg!! 1954130561Sobrien 1955130561Sobrien From a binary dump of my C++ test case 'moo' using Compaq's coffobjanl 1956130561Sobrien (output format has been edited for our purposes): 1957130561Sobrien 1958130561Sobrien FDR [2]: (main.C): First instruction: 0x12000207c <x> 1959130561Sobrien PDR [5] for File [2]: LoopTest__Xv <0x1200020a0> (a) 1960130561Sobrien PDR [7] for File [2]: foo__Xv <0x120002168> 1961130561Sobrien FDR [1]: (-1): First instruction: 0x1200020e8 <y> 1962130561Sobrien PDR [3] for File [1]: <0x120001ad0> (b) 1963130561Sobrien FDR [6]: (-1): First instruction: 0x1200026f0 <z> 1964130561Sobrien 1965130561Sobrien (a) In the case of PDR5, the vma is such that the first few instructions 1966130561Sobrien of the procedure can be found. But since the size of this procedure is 1967130561Sobrien 160b, the vma will soon cross into the 'address space' of FDR1 and no 1968130561Sobrien debugging info will be found. How repugnant! 1969130561Sobrien 1970130561Sobrien (b) It is also possible for a PDR to have a *lower* vma than its associated 1971130561Sobrien FDR; see FDR1 and PDR3. Gross! 1972130561Sobrien 1973130561Sobrien Since the FDRs that are causing so much havok (in this case) 1) do not 1974130561Sobrien describe actual files (fdr.rss == -1), and 2) contain only compiler 1975130561Sobrien generated routines, I thought a simple fix would be to exclude them from 1976130561Sobrien the FDR table in 'mk_fdrtab'. But, besides not knowing for certain 1977130561Sobrien whether this would be correct, it creates an additional problem. If we 1978130561Sobrien happen to ask for source file info on a compiler generated (procedure) 1979130561Sobrien symbol -- which is still in the symbol table -- the result can be 1980130561Sobrien information from a real procedure! This is because compiler generated 1981130561Sobrien procedures with vma's higher than the last FDR in the fdr table will be 1982130561Sobrien associated with a PDR from this FDR, specifically the PDR with the 1983130561Sobrien highest vma. This wasn't a problem before, because each procedure had a 1984130561Sobrien PDR. (Yes, this problem could be eliminated if we kept the size of the 1985130561Sobrien last PDR around, but things are already getting ugly). 1986130561Sobrien 1987130561Sobrien Probably, a better solution would be to have a sorted PDR table. Each 1988130561Sobrien PDR would have a pointer to its FDR so file information could still be 1989130561Sobrien obtained. A FDR table could still be constructed if necessary -- since 1990130561Sobrien it only contains pointers, not much extra memory would be used -- but 1991130561Sobrien the PDR table would be searched to locate debugging info. 1992130561Sobrien 1993130561Sobrien There is still at least one remaining issue. Sometimes a FDR can have a 1994130561Sobrien bogus name, but contain PDRs that should belong to another FDR with a 1995130561Sobrien real name. E.g: 1996130561Sobrien 1997130561Sobrien FDR [3]: 0000000120001b50 (/home/.../Array.H~alt~deccxx_5E5A62AD) 1998130561Sobrien PDR [a] for File [3]: 0000000120001b50 1999130561Sobrien PDR [b] for File [3]: 0000000120001cf0 2000130561Sobrien PDR [c] for File [3]: 0000000120001dc8 2001130561Sobrien PDR [d] for File [3]: 0000000120001e40 2002130561Sobrien PDR [e] for File [3]: 0000000120001eb8 2003130561Sobrien PDR [f] for File [3]: 0000000120001f4c 2004130561Sobrien FDR [4]: 0000000120001b50 (/home/.../Array.H) 2005130561Sobrien 2006130561Sobrien Here, FDR4 has the correct name, but should (seemingly) contain PDRa-f. 2007130561Sobrien The symbol table for PDR4 does contain symbols for PDRa-f, but so does 2008130561Sobrien the symbol table for FDR3. However the former is different; perhaps this 2009130561Sobrien can be detected easily. (I'm not sure at this point.) This problem only 2010130561Sobrien seems to be associated with files with templates. I am assuming the idea 2011130561Sobrien is that there is a 'fake' FDR (with PDRs) for each differently typed set 2012130561Sobrien of templates that must be generated. Currently, FDR4 is completely 2013130561Sobrien excluded from the FDR table in 'mk_fdrtab' because it contains no PDRs. 2014130561Sobrien 2015130561Sobrien Since I don't have time to prepare a real fix for this right now, be 2016130561Sobrien prepared for 'A Horrible Hack' to force the inspection of all non-stabs 2017130561Sobrien FDRs. It's coming... */ 201833965Sjdp fdr_ptr = tab[i].fdr; 201933965Sjdp 202033965Sjdp /* Check whether this file has stabs debugging information. In a 202133965Sjdp file with stabs debugging information, the second local symbol is 202233965Sjdp named @stabs. */ 2023130561Sobrien stabs = FALSE; 202433965Sjdp if (fdr_ptr->csym >= 2) 202533965Sjdp { 202633965Sjdp char *sym_ptr; 202733965Sjdp SYMR sym; 202833965Sjdp 202933965Sjdp sym_ptr = ((char *) debug_info->external_sym 203033965Sjdp + (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size); 203133965Sjdp (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); 203233965Sjdp if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, 203333965Sjdp STABS_SYMBOL) == 0) 2034130561Sobrien stabs = TRUE; 203533965Sjdp } 203633965Sjdp 203733965Sjdp if (!stabs) 203833965Sjdp { 203933965Sjdp bfd_size_type external_pdr_size; 204033965Sjdp char *pdr_ptr; 204133965Sjdp char *best_pdr = NULL; 204233965Sjdp FDR *best_fdr; 2043130561Sobrien bfd_signed_vma best_dist = -1; 204433965Sjdp PDR pdr; 204533965Sjdp unsigned char *line_ptr; 204633965Sjdp unsigned char *line_end; 204733965Sjdp int lineno; 204833965Sjdp /* This file uses ECOFF debugging information. Each FDR has a 204933965Sjdp list of procedure descriptors (PDR). The address in the FDR 205033965Sjdp is the absolute address of the first procedure. The address 205133965Sjdp in the first PDR gives the offset of that procedure relative 205233965Sjdp to the object file's base-address. The addresses in 205333965Sjdp subsequent PDRs specify each procedure's address relative to 205433965Sjdp the object file's base-address. To make things more juicy, 205533965Sjdp whenever the PROF bit in the PDR is set, the real entry point 205633965Sjdp of the procedure may be 16 bytes below what would normally be 205733965Sjdp the procedure's entry point. Instead, DEC came up with a 205833965Sjdp wicked scheme to create profiled libraries "on the fly": 205933965Sjdp instead of shipping a regular and a profiled version of each 206033965Sjdp library, they insert 16 bytes of unused space in front of 206133965Sjdp each procedure and set the "prof" bit in the PDR to indicate 206233965Sjdp that there is a gap there (this is done automagically by "as" 206333965Sjdp when option "-pg" is specified). Thus, normally, you link 206433965Sjdp against such a library and, except for lots of 16 byte gaps 206533965Sjdp between functions, things will behave as usual. However, 206633965Sjdp when invoking "ld" with option "-pg", it will fill those gaps 206733965Sjdp with code that calls mcount(). It then moves the function's 206833965Sjdp entry point down by 16 bytes, and out pops a binary that has 206933965Sjdp all functions profiled. 207033965Sjdp 207133965Sjdp NOTE: Neither FDRs nor PDRs are strictly sorted in memory 207233965Sjdp order. For example, when including header-files that 207333965Sjdp define functions, the FDRs follow behind the including 207433965Sjdp file, even though their code may have been generated at 207533965Sjdp a lower address. File coff-alpha.c from libbfd 207633965Sjdp illustrates this (use "odump -PFv" to look at a file's 207733965Sjdp FDR/PDR). Similarly, PDRs are sometimes out of order 207833965Sjdp as well. An example of this is OSF/1 v3.0 libc's 207933965Sjdp malloc.c. I'm not sure why this happens, but it could 208033965Sjdp be due to optimizations that reorder a function's 208133965Sjdp position within an object-file. 208277298Sobrien 208333965Sjdp Strategy: 208477298Sobrien 208533965Sjdp On the first call to this function, we build a table of FDRs 208633965Sjdp that is sorted by the base-address of the object-file the FDR 208733965Sjdp is referring to. Notice that each object-file may contain 208833965Sjdp code from multiple source files (e.g., due to code defined in 208933965Sjdp include files). Thus, for any given base-address, there may 209033965Sjdp be multiple FDRs (but this case is, fortunately, uncommon). 209133965Sjdp lookup(addr) guarantees to return the first FDR that applies 209233965Sjdp to address ADDR. Thus, after invoking lookup(), we have a 209333965Sjdp list of FDRs that may contain the PDR for ADDR. Next, we 209433965Sjdp walk through the PDRs of these FDRs and locate the one that 209533965Sjdp is closest to ADDR (i.e., for which the difference between 209633965Sjdp ADDR and the PDR's entry point is positive and minimal). 209733965Sjdp Once, the right FDR and PDR are located, we simply walk 209833965Sjdp through the line-number table to lookup the line-number that 209933965Sjdp best matches ADDR. Obviously, things could be sped up by 210033965Sjdp keeping a sorted list of PDRs instead of a sorted list of 210133965Sjdp FDRs. However, this would increase space requirements 210233965Sjdp considerably, which is undesirable. */ 210333965Sjdp external_pdr_size = debug_swap->external_pdr_size; 210433965Sjdp 2105130561Sobrien /* eraxxon: The Horrible Hack: Because of the problems above, set 'i' 2106130561Sobrien to 0 so we look through all FDRs. 2107130561Sobrien 2108130561Sobrien Because FDR's without any symbols are assumed to be non-stabs, 2109130561Sobrien searching through all FDRs may cause the following code to try to 2110130561Sobrien read stabs FDRs as ECOFF ones. However, I don't think this will 2111130561Sobrien harm anything. */ 2112130561Sobrien i = 0; 2113130561Sobrien 211433965Sjdp /* Search FDR list starting at tab[i] for the PDR that best matches 211533965Sjdp OFFSET. Normally, the FDR list is only one entry long. */ 211633965Sjdp best_fdr = NULL; 211733965Sjdp do 211833965Sjdp { 2119130561Sobrien /* eraxxon: 'dist' and 'min_dist' can be negative now 2120130561Sobrien because we iterate over every FDR rather than just ones 2121130561Sobrien with a base address less than or equal to 'offset'. */ 2122130561Sobrien bfd_signed_vma dist = -1, min_dist = -1; 212333965Sjdp char *pdr_hold; 212433965Sjdp char *pdr_end; 212577298Sobrien 212633965Sjdp fdr_ptr = tab[i].fdr; 212777298Sobrien 212833965Sjdp pdr_ptr = ((char *) debug_info->external_pdr 212933965Sjdp + fdr_ptr->ipdFirst * external_pdr_size); 213033965Sjdp pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size; 213133965Sjdp (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); 213233965Sjdp /* Find PDR that is closest to OFFSET. If pdr.prof is set, 213333965Sjdp the procedure entry-point *may* be 0x10 below pdr.adr. We 213433965Sjdp simply pretend that pdr.prof *implies* a lower entry-point. 213533965Sjdp This is safe because it just means that may identify 4 NOPs 213633965Sjdp in front of the function as belonging to the function. */ 213733965Sjdp for (pdr_hold = NULL; 213833965Sjdp pdr_ptr < pdr_end; 213933965Sjdp (pdr_ptr += external_pdr_size, 214033965Sjdp (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr))) 214133965Sjdp { 214233965Sjdp if (offset >= (pdr.adr - 0x10 * pdr.prof)) 214333965Sjdp { 214433965Sjdp dist = offset - (pdr.adr - 0x10 * pdr.prof); 2145130561Sobrien 2146130561Sobrien /* eraxxon: 'dist' can be negative now. Note that 2147130561Sobrien 'min_dist' can be negative if 'pdr_hold' below is NULL. */ 2148130561Sobrien if (!pdr_hold || (dist >= 0 && dist < min_dist)) 214933965Sjdp { 215033965Sjdp min_dist = dist; 215133965Sjdp pdr_hold = pdr_ptr; 215233965Sjdp } 215333965Sjdp } 215433965Sjdp } 215577298Sobrien 2156130561Sobrien if (!best_pdr || (min_dist >= 0 && min_dist < best_dist)) 215733965Sjdp { 2158130561Sobrien best_dist = (bfd_vma) min_dist; 215933965Sjdp best_fdr = fdr_ptr; 216033965Sjdp best_pdr = pdr_hold; 216133965Sjdp } 2162130561Sobrien /* Continue looping until base_addr of next entry is different. */ 216333965Sjdp } 2164130561Sobrien /* eraxxon: We want to iterate over all FDRs. 2165130561Sobrien See previous comment about 'fdrtab_lookup'. */ 2166130561Sobrien while (++i < line_info->fdrtab_len); 216733965Sjdp 216833965Sjdp if (!best_fdr || !best_pdr) 2169130561Sobrien return FALSE; /* Shouldn't happen... */ 217033965Sjdp 2171130561Sobrien /* Phew, finally we got something that we can hold onto. */ 217233965Sjdp fdr_ptr = best_fdr; 217333965Sjdp pdr_ptr = best_pdr; 217433965Sjdp (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); 217533965Sjdp /* Now we can look for the actual line number. The line numbers 217633965Sjdp are stored in a very funky format, which I won't try to 217733965Sjdp describe. The search is bounded by the end of the FDRs line 217833965Sjdp number entries. */ 217933965Sjdp line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine; 218033965Sjdp 2181130561Sobrien /* Make offset relative to procedure entry. */ 218233965Sjdp offset -= pdr.adr - 0x10 * pdr.prof; 218333965Sjdp lineno = pdr.lnLow; 218433965Sjdp line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset; 218533965Sjdp while (line_ptr < line_end) 218633965Sjdp { 218733965Sjdp int delta; 218833965Sjdp unsigned int count; 218933965Sjdp 219033965Sjdp delta = *line_ptr >> 4; 219133965Sjdp if (delta >= 0x8) 219233965Sjdp delta -= 0x10; 219333965Sjdp count = (*line_ptr & 0xf) + 1; 219433965Sjdp ++line_ptr; 219533965Sjdp if (delta == -8) 219633965Sjdp { 219733965Sjdp delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff); 219833965Sjdp if (delta >= 0x8000) 219933965Sjdp delta -= 0x10000; 220033965Sjdp line_ptr += 2; 220133965Sjdp } 220233965Sjdp lineno += delta; 220333965Sjdp if (offset < count * 4) 220433965Sjdp { 220533965Sjdp line_info->cache.stop += count * 4 - offset; 220633965Sjdp break; 220733965Sjdp } 220833965Sjdp offset -= count * 4; 220933965Sjdp } 221033965Sjdp 221133965Sjdp /* If fdr_ptr->rss is -1, then this file does not have full 221233965Sjdp symbols, at least according to gdb/mipsread.c. */ 221333965Sjdp if (fdr_ptr->rss == -1) 221433965Sjdp { 221533965Sjdp line_info->cache.filename = NULL; 221633965Sjdp if (pdr.isym == -1) 221733965Sjdp line_info->cache.functionname = NULL; 221833965Sjdp else 221933965Sjdp { 222033965Sjdp EXTR proc_ext; 222133965Sjdp 222233965Sjdp (*debug_swap->swap_ext_in) 222333965Sjdp (abfd, 222433965Sjdp ((char *) debug_info->external_ext 222533965Sjdp + pdr.isym * debug_swap->external_ext_size), 222633965Sjdp &proc_ext); 222733965Sjdp line_info->cache.functionname = (debug_info->ssext 222833965Sjdp + proc_ext.asym.iss); 222933965Sjdp } 223033965Sjdp } 223133965Sjdp else 223233965Sjdp { 223333965Sjdp SYMR proc_sym; 223433965Sjdp 223533965Sjdp line_info->cache.filename = (debug_info->ss 223633965Sjdp + fdr_ptr->issBase 223733965Sjdp + fdr_ptr->rss); 223833965Sjdp (*debug_swap->swap_sym_in) 223933965Sjdp (abfd, 224033965Sjdp ((char *) debug_info->external_sym 224133965Sjdp + ((fdr_ptr->isymBase + pdr.isym) 224233965Sjdp * debug_swap->external_sym_size)), 224333965Sjdp &proc_sym); 224433965Sjdp line_info->cache.functionname = (debug_info->ss 224533965Sjdp + fdr_ptr->issBase 224633965Sjdp + proc_sym.iss); 224733965Sjdp } 224833965Sjdp if (lineno == ilineNil) 224933965Sjdp lineno = 0; 225033965Sjdp line_info->cache.line_num = lineno; 225133965Sjdp } 225233965Sjdp else 225333965Sjdp { 225433965Sjdp bfd_size_type external_sym_size; 225533965Sjdp const char *directory_name; 225633965Sjdp const char *main_file_name; 225733965Sjdp const char *current_file_name; 225833965Sjdp const char *function_name; 225933965Sjdp const char *line_file_name; 226033965Sjdp bfd_vma low_func_vma; 226133965Sjdp bfd_vma low_line_vma; 2262130561Sobrien bfd_boolean past_line; 2263130561Sobrien bfd_boolean past_fn; 226433965Sjdp char *sym_ptr, *sym_ptr_end; 226533965Sjdp size_t len, funclen; 226633965Sjdp char *buffer = NULL; 226733965Sjdp 226833965Sjdp /* This file uses stabs debugging information. When gcc is not 226933965Sjdp optimizing, it will put the line number information before 227033965Sjdp the function name stabs entry. When gcc is optimizing, it 227133965Sjdp will put the stabs entry for all the function first, followed 227233965Sjdp by the line number information. (This appears to happen 227333965Sjdp because of the two output files used by the -mgpopt switch, 227433965Sjdp which is implied by -O). This means that we must keep 227533965Sjdp looking through the symbols until we find both a line number 227633965Sjdp and a function name which are beyond the address we want. */ 227733965Sjdp 227833965Sjdp line_info->cache.filename = NULL; 227933965Sjdp line_info->cache.functionname = NULL; 228033965Sjdp line_info->cache.line_num = 0; 228133965Sjdp 228233965Sjdp directory_name = NULL; 228333965Sjdp main_file_name = NULL; 228433965Sjdp current_file_name = NULL; 228533965Sjdp function_name = NULL; 228633965Sjdp line_file_name = NULL; 228733965Sjdp low_func_vma = 0; 228833965Sjdp low_line_vma = 0; 2289130561Sobrien past_line = FALSE; 2290130561Sobrien past_fn = FALSE; 229133965Sjdp 229233965Sjdp external_sym_size = debug_swap->external_sym_size; 229333965Sjdp 229433965Sjdp sym_ptr = ((char *) debug_info->external_sym 229533965Sjdp + (fdr_ptr->isymBase + 2) * external_sym_size); 229633965Sjdp sym_ptr_end = sym_ptr + (fdr_ptr->csym - 2) * external_sym_size; 229733965Sjdp for (; 229833965Sjdp sym_ptr < sym_ptr_end && (! past_line || ! past_fn); 229933965Sjdp sym_ptr += external_sym_size) 230033965Sjdp { 230133965Sjdp SYMR sym; 230233965Sjdp 230333965Sjdp (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); 230433965Sjdp 230533965Sjdp if (ECOFF_IS_STAB (&sym)) 230633965Sjdp { 230733965Sjdp switch (ECOFF_UNMARK_STAB (sym.index)) 230833965Sjdp { 230933965Sjdp case N_SO: 231033965Sjdp main_file_name = current_file_name = 231133965Sjdp debug_info->ss + fdr_ptr->issBase + sym.iss; 231233965Sjdp 231333965Sjdp /* Check the next symbol to see if it is also an 231433965Sjdp N_SO symbol. */ 231533965Sjdp if (sym_ptr + external_sym_size < sym_ptr_end) 231633965Sjdp { 231733965Sjdp SYMR nextsym; 231833965Sjdp 231933965Sjdp (*debug_swap->swap_sym_in) (abfd, 232033965Sjdp sym_ptr + external_sym_size, 232133965Sjdp &nextsym); 232233965Sjdp if (ECOFF_IS_STAB (&nextsym) 232333965Sjdp && ECOFF_UNMARK_STAB (nextsym.index) == N_SO) 232433965Sjdp { 232533965Sjdp directory_name = current_file_name; 232633965Sjdp main_file_name = current_file_name = 232733965Sjdp debug_info->ss + fdr_ptr->issBase + nextsym.iss; 232833965Sjdp sym_ptr += external_sym_size; 232933965Sjdp } 233033965Sjdp } 233133965Sjdp break; 233233965Sjdp 233333965Sjdp case N_SOL: 233433965Sjdp current_file_name = 233533965Sjdp debug_info->ss + fdr_ptr->issBase + sym.iss; 233633965Sjdp break; 233733965Sjdp 233833965Sjdp case N_FUN: 233933965Sjdp if (sym.value > offset) 2340130561Sobrien past_fn = TRUE; 234133965Sjdp else if (sym.value >= low_func_vma) 234233965Sjdp { 234333965Sjdp low_func_vma = sym.value; 234433965Sjdp function_name = 234533965Sjdp debug_info->ss + fdr_ptr->issBase + sym.iss; 234633965Sjdp } 234733965Sjdp break; 234833965Sjdp } 234933965Sjdp } 235033965Sjdp else if (sym.st == stLabel && sym.index != indexNil) 235133965Sjdp { 235233965Sjdp if (sym.value > offset) 2353130561Sobrien past_line = TRUE; 235433965Sjdp else if (sym.value >= low_line_vma) 235533965Sjdp { 235633965Sjdp low_line_vma = sym.value; 235733965Sjdp line_file_name = current_file_name; 235833965Sjdp line_info->cache.line_num = sym.index; 235933965Sjdp } 236033965Sjdp } 236133965Sjdp } 236233965Sjdp 236333965Sjdp if (line_info->cache.line_num != 0) 236433965Sjdp main_file_name = line_file_name; 236533965Sjdp 236633965Sjdp /* We need to remove the stuff after the colon in the function 236733965Sjdp name. We also need to put the directory name and the file 236833965Sjdp name together. */ 236933965Sjdp if (function_name == NULL) 237033965Sjdp len = funclen = 0; 237133965Sjdp else 237233965Sjdp len = funclen = strlen (function_name) + 1; 237333965Sjdp 237433965Sjdp if (main_file_name != NULL 237533965Sjdp && directory_name != NULL 237633965Sjdp && main_file_name[0] != '/') 237733965Sjdp len += strlen (directory_name) + strlen (main_file_name) + 1; 237833965Sjdp 237933965Sjdp if (len != 0) 238033965Sjdp { 238133965Sjdp if (line_info->find_buffer != NULL) 238233965Sjdp free (line_info->find_buffer); 238389857Sobrien buffer = (char *) bfd_malloc ((bfd_size_type) len); 238433965Sjdp if (buffer == NULL) 2385130561Sobrien return FALSE; 238633965Sjdp line_info->find_buffer = buffer; 238733965Sjdp } 238833965Sjdp 238933965Sjdp if (function_name != NULL) 239033965Sjdp { 239133965Sjdp char *colon; 239233965Sjdp 239333965Sjdp strcpy (buffer, function_name); 239433965Sjdp colon = strchr (buffer, ':'); 239533965Sjdp if (colon != NULL) 239633965Sjdp *colon = '\0'; 239733965Sjdp line_info->cache.functionname = buffer; 239833965Sjdp } 239933965Sjdp 240033965Sjdp if (main_file_name != NULL) 240133965Sjdp { 240233965Sjdp if (directory_name == NULL || main_file_name[0] == '/') 240333965Sjdp line_info->cache.filename = main_file_name; 240433965Sjdp else 240533965Sjdp { 240633965Sjdp sprintf (buffer + funclen, "%s%s", directory_name, 240733965Sjdp main_file_name); 240833965Sjdp line_info->cache.filename = buffer + funclen; 240933965Sjdp } 241033965Sjdp } 241133965Sjdp } 241233965Sjdp 2413130561Sobrien return TRUE; 241433965Sjdp} 241533965Sjdp 241633965Sjdp/* Do the work of find_nearest_line. */ 241733965Sjdp 2418130561Sobrienbfd_boolean 241933965Sjdp_bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap, 242033965Sjdp line_info, filename_ptr, functionname_ptr, retline_ptr) 242133965Sjdp bfd *abfd; 242233965Sjdp asection *section; 242333965Sjdp bfd_vma offset; 242433965Sjdp struct ecoff_debug_info * const debug_info; 242533965Sjdp const struct ecoff_debug_swap * const debug_swap; 242633965Sjdp struct ecoff_find_line *line_info; 242733965Sjdp const char **filename_ptr; 242833965Sjdp const char **functionname_ptr; 242933965Sjdp unsigned int *retline_ptr; 243033965Sjdp{ 243133965Sjdp offset += section->vma; 243233965Sjdp 243333965Sjdp if (line_info->cache.sect == NULL 243433965Sjdp || line_info->cache.sect != section 243533965Sjdp || offset < line_info->cache.start 243633965Sjdp || offset >= line_info->cache.stop) 243733965Sjdp { 243833965Sjdp line_info->cache.sect = section; 243933965Sjdp line_info->cache.start = offset; 244033965Sjdp line_info->cache.stop = offset; 244133965Sjdp if (! lookup_line (abfd, debug_info, debug_swap, line_info)) 244233965Sjdp { 244333965Sjdp line_info->cache.sect = NULL; 2444130561Sobrien return FALSE; 244533965Sjdp } 244633965Sjdp } 244733965Sjdp 244833965Sjdp *filename_ptr = line_info->cache.filename; 244933965Sjdp *functionname_ptr = line_info->cache.functionname; 245033965Sjdp *retline_ptr = line_info->cache.line_num; 245133965Sjdp 2452130561Sobrien return TRUE; 245333965Sjdp} 245433965Sjdp 245533965Sjdp/* These routines copy symbolic information into a memory buffer. 245633965Sjdp 245733965Sjdp FIXME: The whole point of the shuffle code is to avoid storing 245833965Sjdp everything in memory, since the linker is such a memory hog. This 245933965Sjdp code makes that effort useless. It is only called by the MIPS ELF 246033965Sjdp code when generating a shared library, so it is not that big a 246133965Sjdp deal, but it should be fixed eventually. */ 246233965Sjdp 246333965Sjdp/* Collect a shuffle into a memory buffer. */ 246433965Sjdp 2465130561Sobrienstatic bfd_boolean ecoff_collect_shuffle 2466130561Sobrien PARAMS ((struct shuffle *, bfd_byte *)); 246733965Sjdp 2468130561Sobrienstatic bfd_boolean 246933965Sjdpecoff_collect_shuffle (l, buff) 247033965Sjdp struct shuffle *l; 247133965Sjdp bfd_byte *buff; 247233965Sjdp{ 247333965Sjdp unsigned long total; 247433965Sjdp 247533965Sjdp total = 0; 247633965Sjdp for (; l != (struct shuffle *) NULL; l = l->next) 247733965Sjdp { 247833965Sjdp if (! l->filep) 247933965Sjdp memcpy (buff, l->u.memory, l->size); 248033965Sjdp else 248133965Sjdp { 248233965Sjdp if (bfd_seek (l->u.file.input_bfd, l->u.file.offset, SEEK_SET) != 0 248389857Sobrien || (bfd_bread (buff, (bfd_size_type) l->size, l->u.file.input_bfd) 248489857Sobrien != l->size)) 2485130561Sobrien return FALSE; 248633965Sjdp } 248733965Sjdp total += l->size; 248833965Sjdp buff += l->size; 248933965Sjdp } 249033965Sjdp 2491130561Sobrien return TRUE; 249233965Sjdp} 249333965Sjdp 249433965Sjdp/* Copy PDR information into a memory buffer. */ 249533965Sjdp 2496130561Sobrienbfd_boolean 249733965Sjdp_bfd_ecoff_get_accumulated_pdr (handle, buff) 249833965Sjdp PTR handle; 249933965Sjdp bfd_byte *buff; 250033965Sjdp{ 250133965Sjdp struct accumulate *ainfo = (struct accumulate *) handle; 250233965Sjdp 250333965Sjdp return ecoff_collect_shuffle (ainfo->pdr, buff); 250433965Sjdp} 250533965Sjdp 250633965Sjdp/* Copy symbol information into a memory buffer. */ 250733965Sjdp 2508130561Sobrienbfd_boolean 250933965Sjdp_bfd_ecoff_get_accumulated_sym (handle, buff) 251033965Sjdp PTR handle; 251133965Sjdp bfd_byte *buff; 251233965Sjdp{ 251333965Sjdp struct accumulate *ainfo = (struct accumulate *) handle; 251433965Sjdp 251533965Sjdp return ecoff_collect_shuffle (ainfo->sym, buff); 251633965Sjdp} 251733965Sjdp 251833965Sjdp/* Copy the string table into a memory buffer. */ 251933965Sjdp 2520130561Sobrienbfd_boolean 252133965Sjdp_bfd_ecoff_get_accumulated_ss (handle, buff) 252233965Sjdp PTR handle; 252333965Sjdp bfd_byte *buff; 252433965Sjdp{ 252533965Sjdp struct accumulate *ainfo = (struct accumulate *) handle; 252633965Sjdp struct string_hash_entry *sh; 252733965Sjdp unsigned long total; 252833965Sjdp 252933965Sjdp /* The string table is written out from the hash table if this is a 253033965Sjdp final link. */ 253133965Sjdp BFD_ASSERT (ainfo->ss == (struct shuffle *) NULL); 253233965Sjdp *buff++ = '\0'; 253333965Sjdp total = 1; 253433965Sjdp BFD_ASSERT (ainfo->ss_hash == NULL || ainfo->ss_hash->val == 1); 253533965Sjdp for (sh = ainfo->ss_hash; 253633965Sjdp sh != (struct string_hash_entry *) NULL; 253733965Sjdp sh = sh->next) 253833965Sjdp { 253933965Sjdp size_t len; 254033965Sjdp 254133965Sjdp len = strlen (sh->root.string); 254233965Sjdp memcpy (buff, (PTR) sh->root.string, len + 1); 254333965Sjdp total += len + 1; 254433965Sjdp buff += len + 1; 254533965Sjdp } 254633965Sjdp 2547130561Sobrien return TRUE; 254833965Sjdp} 2549