* syms.c: Include "bfdlink.h".

(struct stab_find_info): Define.
	(_bfd_stab_section_find_nearest_line): New function.
	* libbfd-in.h (_bfd_stab_section_find_nearest_line): Declare.
	* libbfd.h: Rebuild.
	* elf-bfd.h (struct elf_obj_tdata): Add line_info field.
	* elf.c (_bfd_elf_find_nearest_line): Try calling
	_bfd_stab_section_find_nearest_line before searching the ELF
	symbol table.  Find the closest STT_FUNC symbol, not the last one.
	* libcoff-in.h (coff_data_type): Add line_info field.
	* libcoff.h: Rebuild.
	* coffgen.c (coff_find_nearest_line): Try calling
	_bfd_stab_section_find_nearest_line before searching the COFF
	symbol table.
	* Makefile.in: Rebuild dependencies.
This commit is contained in:
Ian Lance Taylor 1996-01-26 23:42:58 +00:00
parent a77bf669dc
commit 86aac8eabe
7 changed files with 596 additions and 50 deletions

View File

@ -1,3 +1,27 @@
Fri Jan 26 18:33:35 1996 Ian Lance Taylor <ian@cygnus.com>
* syms.c: Include "bfdlink.h".
(struct stab_find_info): Define.
(_bfd_stab_section_find_nearest_line): New function.
* libbfd-in.h (_bfd_stab_section_find_nearest_line): Declare.
* libbfd.h: Rebuild.
* elf-bfd.h (struct elf_obj_tdata): Add line_info field.
* elf.c (_bfd_elf_find_nearest_line): Try calling
_bfd_stab_section_find_nearest_line before searching the ELF
symbol table. Find the closest STT_FUNC symbol, not the last one.
* libcoff-in.h (coff_data_type): Add line_info field.
* libcoff.h: Rebuild.
* coffgen.c (coff_find_nearest_line): Try calling
_bfd_stab_section_find_nearest_line before searching the COFF
symbol table.
* Makefile.in: Rebuild dependencies.
Fri Jan 26 16:11:19 1996 Michael Meissner <meissner@tiktok.cygnus.com>
* elf32-ppc.c (R_PPC_EMB_SDA21 relocations): Make relocation size
4 bytes, so we get the correct value when updating the register
field in little endian mode.
Thu Jan 25 12:14:16 1996 Ian Lance Taylor <ian@cygnus.com>
* libcoff-in.h (struct xcoff_tdata): Remove toc_section and

View File

@ -1,5 +1,6 @@
# Makefile template for Configure for the BFD library.
# Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
# Copyright (C) 1990, 91, 92, 93, 94, 95, 1996
# Free Software Foundation, Inc.
# Written by Cygnus Support.
#
# This file is part of BFD, the Binary File Descriptor library.
@ -713,7 +714,8 @@ libbfd.o: libbfd.c
opncls.o: opncls.c
reloc.o: reloc.c $(INCDIR)/bfdlink.h
section.o: section.c
syms.o: syms.c $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
syms.o: syms.c $(INCDIR)/bfdlink.h $(INCDIR)/aout/stab_gnu.h \
$(INCDIR)/aout/stab.def
targets.o: targets.c
hash.o: hash.c
linker.o: linker.c $(INCDIR)/bfdlink.h genlink.h
@ -852,7 +854,7 @@ elf32-ppc.o: elf32-ppc.c $(INCDIR)/bfdlink.h elf-bfd.h \
$(INCDIR)/elf/ppc.h elf32-target.h
elf32-sparc.o: elf32-sparc.c $(INCDIR)/bfdlink.h elf-bfd.h \
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
elf32-target.h
$(INCDIR)/elf/sparc.h elf32-target.h
elf32.o: elf32.c elfcode.h $(INCDIR)/bfdlink.h elf-bfd.h \
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
elfcore.h elflink.h
@ -962,8 +964,8 @@ aout64.o: aout64.c aoutx.h $(INCDIR)/bfdlink.h libaout.h \
$(INCDIR)/aout/ar.h
coff-alpha.o: coff-alpha.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h \
$(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \
$(INCDIR)/coff/alpha.h libcoff.h libecoff.h coffswap.h \
ecoffswap.h
$(INCDIR)/coff/alpha.h $(INCDIR)/aout/ar.h libcoff.h \
libecoff.h coffswap.h ecoffswap.h
demo64.o: demo64.c aoutf1.h $(INCDIR)/aout/sun4.h libaout.h \
$(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
$(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h aout-target.h
@ -987,8 +989,7 @@ hpux-core.o: hpux-core.c
irix-core.o: irix-core.c
lynx-core.o: lynx-core.c
osf-core.o: osf-core.c
trad-core.o: trad-core.c libaout.h $(INCDIR)/bfdlink.h \
hosts/i386bsd.h
trad-core.o: trad-core.c libaout.h $(INCDIR)/bfdlink.h
cisco-core.o: cisco-core.c
i386dynix.o: i386dynix.c $(INCDIR)/aout/dynix3.h aoutx.h \
$(INCDIR)/bfdlink.h libaout.h $(INCDIR)/aout/aout64.h \

View File

@ -102,6 +102,11 @@ struct elf_link_hash_entry
require an entry in the procedure linkage table. */
bfd_vma plt_offset;
/* If this symbol is used in the linker created sections, the processor
specific backend uses this field to map the field into the offset
from the beginning of the section. */
struct elf_linker_section_pointers *linker_section_pointer;
/* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */
char type;
@ -482,6 +487,52 @@ struct bfd_elf_section_data
#define get_elf_backend_data(abfd) \
((struct elf_backend_data *) (abfd)->xvec->backend_data)
/* Enumeration to specify the special section. */
typedef enum elf_linker_section_enum
{
LINKER_SECTION_UNKNOWN, /* not used */
LINKER_SECTION_GOT, /* .got section for global offset pointers */
LINKER_SECTION_PLT, /* .plt section for generated procedure stubs */
LINKER_SECTION_SDATA, /* .sdata/.sbss section for PowerPC */
LINKER_SECTION_SDATA2, /* .sdata2/.sbss2 section for PowerPC */
LINKER_SECTION_MAX /* # of linker sections */
} elf_linker_section_enum_t;
/* Sections created by the linker. */
typedef struct elf_linker_section
{
char *name; /* name of the section */
char *rel_name; /* name of the associated .rel{,a}. section */
char *bss_name; /* name of a related .bss section */
char *sym_name; /* name of symbol to reference this section */
asection *section; /* pointer to the section */
asection *bss_section; /* pointer to the bss section associated with this */
asection *rel_section; /* pointer to the relocations needed for this section */
struct elf_link_hash_entry *sym_hash; /* pointer to the created symbol hash value */
bfd_vma initial_size; /* initial size before any linker generated allocations */
bfd_vma sym_offset; /* offset of symbol from beginning of section */
bfd_vma hole_size; /* size of reserved address hole in allocation */
bfd_vma hole_offset; /* current offset for the hole */
bfd_vma max_hole_offset; /* maximum offset for the hole */
elf_linker_section_enum_t which; /* which section this is */
boolean hole_written_p; /* whether the hole has been initialized */
int alignment; /* alignment for the section */
flagword flags; /* flags to use to create the section */
} elf_linker_section_t;
/* Linked list of allocated pointer entries. This hangs off of the symbol lists, and
provides allows us to return different pointers, based on different addend's. */
typedef struct elf_linker_section_pointers
{
struct elf_linker_section_pointers *next; /* next allocated pointer for this symbol */
bfd_vma offset; /* offset of pointer from beginning of section */
bfd_signed_vma addend; /* addend used */
elf_linker_section_enum_t which; /* which linker section this is */
boolean written_address_p; /* whether address was written yet */
} elf_linker_section_pointers_t;
/* Some private data is stashed away for future use using the tdata pointer
in the bfd structure. */
@ -494,7 +545,7 @@ struct elf_obj_tdata
struct bfd_strtab_hash *strtab_ptr;
int num_locals;
int num_globals;
asymbol **section_syms; /* STT_SECTION symbols for each section */
asymbol **section_syms; /* STT_SECTION symbols for each section */
Elf_Internal_Shdr symtab_hdr;
Elf_Internal_Shdr shstrtab_hdr;
Elf_Internal_Shdr strtab_hdr;
@ -503,10 +554,10 @@ struct elf_obj_tdata
unsigned int symtab_section, shstrtab_section;
unsigned int strtab_section, dynsymtab_section;
file_ptr next_file_pos;
void *prstatus; /* The raw /proc prstatus structure */
void *prpsinfo; /* The raw /proc prpsinfo structure */
bfd_vma gp; /* The gp value (MIPS only, for now) */
unsigned int gp_size; /* The gp size (MIPS only, for now) */
void *prstatus; /* The raw /proc prstatus structure */
void *prpsinfo; /* The raw /proc prpsinfo structure */
bfd_vma gp; /* The gp value (MIPS only, for now) */
unsigned int gp_size; /* The gp size (MIPS only, for now) */
/* This is set to true if the object was created by the backend
linker. */
@ -521,6 +572,10 @@ struct elf_obj_tdata
table, used when linking. This is indexed by the symbol index. */
bfd_vma *local_got_offsets;
/* A mapping from local symbols to offsets into the various linker
sections added. This is index by the symbol index. */
elf_linker_section_pointers_t **linker_section_pointers;
/* The linker ELF emulation code needs to let the backend ELF linker
know what filename should be used for a dynamic object if the
dynamic object is found using a search. This field is used to
@ -537,6 +592,9 @@ struct elf_obj_tdata
/* Records the result of `get_program_header_size'. */
bfd_size_type program_header_size;
/* Used by find_nearest_line entry point. */
PTR line_info;
/* Used by MIPS ELF find_nearest_line entry point. The structure
could be included directly in this one, but there's no point to
wasting the memory just for the infrequently called
@ -545,6 +603,9 @@ struct elf_obj_tdata
/* Used to determine if the e_flags field has been initialized */
boolean flags_init;
/* Linker sections that we are interested in. */
struct elf_linker_section *linker_section[ (int)LINKER_SECTION_MAX ];
};
#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
@ -562,9 +623,11 @@ struct elf_obj_tdata
#define elf_gp_size(bfd) (elf_tdata(bfd) -> gp_size)
#define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes)
#define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got_offsets)
#define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers)
#define elf_dt_needed_name(bfd) (elf_tdata(bfd) -> dt_needed_name)
#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab)
#define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init)
#define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
extern int _bfd_elf_section_from_bfd_section PARAMS ((bfd *, asection *));
extern char *bfd_elf_string_from_elf_section
@ -661,6 +724,56 @@ boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *,
boolean _bfd_elf_create_got_section PARAMS ((bfd *,
struct bfd_link_info *));
elf_linker_section_t *_bfd_elf_create_linker_section
PARAMS ((bfd *abfd,
struct bfd_link_info *info,
enum elf_linker_section_enum,
elf_linker_section_t *defaults));
elf_linker_section_pointers_t *_bfd_elf_find_pointer_linker_section
PARAMS ((elf_linker_section_pointers_t *linker_pointers,
bfd_signed_vma addend,
elf_linker_section_enum_t which));
boolean bfd_elf32_create_pointer_linker_section
PARAMS ((bfd *abfd,
struct bfd_link_info *info,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
const Elf32_Internal_Rela *rel));
bfd_vma bfd_elf32_finish_pointer_linker_section
PARAMS ((bfd *output_abfd,
bfd *input_bfd,
struct bfd_link_info *info,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
bfd_vma relocation,
const Elf32_Internal_Rela *rel,
int relative_reloc));
boolean bfd_elf64_create_pointer_linker_section
PARAMS ((bfd *abfd,
struct bfd_link_info *info,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
const Elf64_Internal_Rela *rel));
bfd_vma bfd_elf64_finish_pointer_linker_section
PARAMS ((bfd *output_abfd,
bfd *input_bfd,
struct bfd_link_info *info,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
bfd_vma relocation,
const Elf64_Internal_Rela *rel,
int relative_reloc));
boolean _bfd_elf_make_linker_section_rela
PARAMS ((bfd *dynobj,
elf_linker_section_t *lsect,
int alignment));
extern const bfd_target *bfd_elf32_object_p PARAMS ((bfd *));
extern const bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *));
extern char *bfd_elf32_core_file_failing_command PARAMS ((bfd *));

View File

@ -554,6 +554,7 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
ret->weakdef = NULL;
ret->got_offset = (bfd_vma) -1;
ret->plt_offset = (bfd_vma) -1;
ret->linker_section_pointer = (elf_linker_section_pointers_t *)0;
ret->type = STT_NOTYPE;
ret->elf_link_hash_flags = 0;
}
@ -3142,15 +3143,26 @@ _bfd_elf_find_nearest_line (abfd,
CONST char **functionname_ptr;
unsigned int *line_ptr;
{
boolean found;
const char *filename;
asymbol *func;
bfd_vma low_func;
asymbol **p;
if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
&found, filename_ptr,
functionname_ptr, line_ptr,
&elf_tdata (abfd)->line_info))
return false;
if (found)
return true;
if (symbols == NULL)
return false;
filename = NULL;
func = NULL;
low_func = 0;
for (p = symbols; *p != NULL; p++)
{
@ -3169,9 +3181,13 @@ _bfd_elf_find_nearest_line (abfd,
filename = bfd_asymbol_name (&q->symbol);
break;
case STT_FUNC:
if (func == NULL
|| q->symbol.value <= offset)
func = (asymbol *) q;
if (q->symbol.section == section
&& q->symbol.value >= low_func
&& q->symbol.value <= offset)
{
func = (asymbol *) q;
low_func = q->symbol.value;
}
break;
}
}

View File

@ -89,6 +89,9 @@ typedef struct coff_tdata
int *local_toc_sym_map;
struct bfd_link_info *link_info;
/* Used by coff_find_nearest_line. */
PTR line_info;
} coff_data_type;
/* Tdata for pe image files. */
@ -117,11 +120,11 @@ struct xcoff_tdata
/* TOC value. */
bfd_vma toc;
/* Section holding TOC. */
asection *toc_section;
/* Index of section holding TOC. */
int sntoc;
/* Section holding entry point. */
asection *entry_section;
/* Index of section holding entry point. */
int snentry;
/* .text alignment from optional header. */
int text_align_power;
@ -223,11 +226,6 @@ struct coff_link_hash_entry
/* Pointer to array of auxiliary entries, if any. */
union internal_auxent *aux;
/* If this symbol requires an entry in the table of contents, the
processor specific backend uses this field to hold the offset
into the .toc section. */
bfd_vma toc_offset;
};
/* COFF linker hash table. */

View File

@ -89,6 +89,9 @@ typedef struct coff_tdata
int *local_toc_sym_map;
struct bfd_link_info *link_info;
/* Used by coff_find_nearest_line. */
PTR line_info;
} coff_data_type;
/* Tdata for pe image files. */
@ -117,11 +120,11 @@ struct xcoff_tdata
/* TOC value. */
bfd_vma toc;
/* Section holding TOC. */
asection *toc_section;
/* Index of section holding TOC. */
int sntoc;
/* Section holding entry point. */
asection *entry_section;
/* Index of section holding entry point. */
int snentry;
/* .text alignment from optional header. */
int text_align_power;
@ -223,11 +226,6 @@ struct coff_link_hash_entry
/* Pointer to array of auxiliary entries, if any. */
union internal_auxent *aux;
/* If this symbol requires an entry in the table of contents, the
processor specific backend uses this field to hold the offset
into the .toc section. */
bfd_vma toc_offset;
};
/* COFF linker hash table. */

View File

@ -48,6 +48,7 @@ SECTION
@menu
@* Reading Symbols::
@* Writing Symbols::
@* Mini Symbols::
@* typedef asymbol::
@* symbol handling functions::
@end menu
@ -91,7 +92,7 @@ SUBSECTION
INODE
Writing Symbols, Mini symbols, Reading Symbols, Symbols
Writing Symbols, Mini Symbols, Reading Symbols, Symbols
SUBSECTION
Writing symbols
@ -138,9 +139,9 @@ SUBSECTION
be described.
INODE
Mini symbols, typedef asymbol, Writing Symbols, Symbols
Mini Symbols, typedef asymbol, Writing Symbols, Symbols
SUBSECTION
Mini symbols
Mini Symbols
Mini symbols provide read-only access to the symbol table.
They use less memory space, but require more time to access.
@ -166,7 +167,7 @@ SUBSECTION
/*
DOCDD
INODE
typedef asymbol, symbol handling functions, Mini symbols, Symbols
typedef asymbol, symbol handling functions, Mini Symbols, Symbols
*/
/*
@ -262,15 +263,14 @@ CODE_FRAGMENT
. {* Signal that the symbol is the label of constructor section. *}
.#define BSF_CONSTRUCTOR 0x800
.
. {* Signal that the symbol is a warning symbol. If the symbol
. is a warning symbol, then the value field (I know this is
. tacky) will point to the asymbol which when referenced will
. cause the warning. *}
. {* Signal that the symbol is a warning symbol. The name is a
. warning. The name of the next symbol is the one to warn about;
. if a reference is made to a symbol with the same name as the next
. symbol, a warning is issued by the linker. *}
.#define BSF_WARNING 0x1000
.
. {* Signal that the symbol is indirect. The value of the symbol
. is a pointer to an undefined asymbol which contains the
. name to use instead. *}
. {* Signal that the symbol is indirect. This symbol is an indirect
. pointer to the symbol with the same name as the next symbol. *}
.#define BSF_INDIRECT 0x2000
.
. {* BSF_FILE marks symbols that contain a file name. This is used
@ -299,8 +299,8 @@ CODE_FRAGMENT
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "bfdlink.h"
#include "aout/stab_gnu.h"
/*
@ -634,12 +634,9 @@ _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep)
if (storage < 0)
goto error_return;
syms = (asymbol **) malloc ((size_t) storage);
syms = (asymbol **) bfd_malloc ((size_t) storage);
if (syms == NULL)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
goto error_return;
if (dynamic)
symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
@ -672,3 +669,402 @@ _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym)
{
return *(asymbol **) minisym;
}
/* Look through stabs debugging information in .stab and .stabstr
sections to find the source file and line closest to a desired
location. This is used by COFF and ELF targets. It sets *pfound
to true if it finds some information. The *pinfo field is used to
pass cached information in and out of this routine; this first time
the routine is called for a BFD, *pinfo should be NULL. The value
placed in *pinfo should be saved with the BFD, and passed back each
time this function is called. */
/* A pointer to this structure is stored in *pinfo. */
struct stab_find_info
{
/* The .stab section. */
asection *stabsec;
/* The .stabstr section. */
asection *strsec;
/* The contents of the .stab section. */
bfd_byte *stabs;
/* The contents of the .stabstr section. */
bfd_byte *strs;
/* An malloc buffer to hold the file name. */
char *filename;
/* Cached values to restart quickly. */
bfd_vma cached_offset;
bfd_byte *cached_stab;
bfd_byte *cached_str;
bfd_size_type cached_stroff;
};
boolean
_bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound,
pfilename, pfnname, pline, pinfo)
bfd *abfd;
asymbol **symbols;
asection *section;
bfd_vma offset;
boolean *pfound;
const char **pfilename;
const char **pfnname;
unsigned int *pline;
PTR *pinfo;
{
struct stab_find_info *info;
bfd_size_type stabsize, strsize;
bfd_byte *stab, *stabend, *str;
bfd_size_type stroff;
bfd_vma fnaddr;
char *directory_name, *main_file_name, *current_file_name, *line_file_name;
char *fnname;
bfd_vma low_func_vma, low_line_vma;
*pfound = false;
*pfilename = bfd_get_filename (abfd);
*pfnname = NULL;
*pline = 0;
info = (struct stab_find_info *) *pinfo;
if (info != NULL)
{
if (info->stabsec == NULL || info->strsec == NULL)
{
/* No stabs debugging information. */
return true;
}
stabsize = info->stabsec->_raw_size;
strsize = info->strsec->_raw_size;
}
else
{
long reloc_size, reloc_count;
arelent **reloc_vector;
info = (struct stab_find_info *) bfd_zalloc (abfd, sizeof *info);
if (info == NULL)
return false;
/* FIXME: When using the linker --split-by-file or
--split-by-reloc options, it is possible for the .stab and
.stabstr sections to be split. We should handle that. */
info->stabsec = bfd_get_section_by_name (abfd, ".stab");
info->strsec = bfd_get_section_by_name (abfd, ".stabstr");
if (info->stabsec == NULL || info->strsec == NULL)
{
/* No stabs debugging information. Set *pinfo so that we
can return quickly in the info != NULL case above. */
*pinfo = info;
return true;
}
stabsize = info->stabsec->_raw_size;
strsize = info->strsec->_raw_size;
info->stabs = (bfd_byte *) bfd_alloc (abfd, stabsize);
info->strs = (bfd_byte *) bfd_alloc (abfd, strsize);
if (info->stabs == NULL || info->strs == NULL)
return false;
if (! bfd_get_section_contents (abfd, info->stabsec, info->stabs, 0,
stabsize)
|| ! bfd_get_section_contents (abfd, info->strsec, info->strs, 0,
strsize))
return false;
/* If this is a relocateable object file, we have to relocate
the entries in .stab. This should always be simple 32 bit
relocations against symbols defined in this object file, so
this should be no big deal. */
reloc_size = bfd_get_reloc_upper_bound (abfd, info->stabsec);
if (reloc_size < 0)
return false;
reloc_vector = (arelent **) bfd_malloc (reloc_size);
if (reloc_vector == NULL && reloc_size != 0)
return false;
reloc_count = bfd_canonicalize_reloc (abfd, info->stabsec, reloc_vector,
symbols);
if (reloc_count < 0)
{
if (reloc_vector != NULL)
free (reloc_vector);
return false;
}
if (reloc_count > 0)
{
arelent **pr;
for (pr = reloc_vector; *pr != NULL; pr++)
{
arelent *r;
unsigned long val;
asymbol *sym;
r = *pr;
if (r->howto->rightshift != 0
|| r->howto->size != 2
|| r->howto->bitsize != 32
|| r->howto->pc_relative
|| r->howto->bitpos != 0
|| r->howto->dst_mask != 0xffffffff)
{
(*_bfd_error_handler)
("Unsupported .stab relocation");
bfd_set_error (bfd_error_invalid_operation);
if (reloc_vector != NULL)
free (reloc_vector);
return false;
}
val = bfd_get_32 (abfd, info->stabs + r->address);
val &= r->howto->src_mask;
sym = *r->sym_ptr_ptr;
val += sym->value + sym->section->vma + r->addend;
bfd_put_32 (abfd, val, info->stabs + r->address);
}
}
if (reloc_vector != NULL)
free (reloc_vector);
*pinfo = info;
}
/* We are passed a section relative offset. The offsets in the
stabs information are absolute. */
offset += bfd_get_section_vma (abfd, section);
/* Stabs entries use a 12 byte format:
4 byte string table index
1 byte stab type
1 byte stab other field
2 byte stab desc field
4 byte stab value
FIXME: This will have to change for a 64 bit object format.
The stabs symbols are divided into compilation units. For the
first entry in each unit, the type of 0, the value is the length
of the string table for this unit, and the desc field is the
number of stabs symbols for this unit. */
#define STRDXOFF (0)
#define TYPEOFF (4)
#define OTHEROFF (5)
#define DESCOFF (6)
#define VALOFF (8)
#define STABSIZE (12)
/* It would be nice if we could skip ahead to the stabs symbols for
the next compilation unit to quickly scan through the compilation
units. Unfortunately, since each line number gets a separate
stabs entry, it is entirely plausible that a large source file
will overflow the 16 bit count of stabs entries. */
fnaddr = 0;
directory_name = NULL;
main_file_name = NULL;
current_file_name = NULL;
line_file_name = NULL;
fnname = NULL;
low_func_vma = 0;
low_line_vma = 0;
stabend = info->stabs + stabsize;
if (info->cached_stab == NULL || offset < info->cached_offset)
{
stab = info->stabs;
str = info->strs;
stroff = 0;
}
else
{
stab = info->cached_stab;
str = info->cached_str;
stroff = info->cached_stroff;
}
info->cached_offset = offset;
for (; stab < stabend; stab += STABSIZE)
{
boolean done;
bfd_vma val;
char *name;
done = false;
switch (stab[TYPEOFF])
{
case 0:
/* This is the first entry in a compilation unit. */
if ((bfd_size_type) ((info->strs + strsize) - str) < stroff)
{
done = true;
break;
}
str += stroff;
stroff = bfd_get_32 (abfd, stab + VALOFF);
break;
case N_SO:
/* The main file name. */
val = bfd_get_32 (abfd, stab + VALOFF);
if (val > offset)
{
done = true;
break;
}
name = str + bfd_get_32 (abfd, stab + STRDXOFF);
/* An empty string indicates the end of the compilation
unit. */
if (*name == '\0')
{
/* If there are functions in different sections, they
may have addresses larger than val, but we don't want
to forget the file name. When there are functions in
different cases, there is supposed to be an N_FUN at
the end of the function indicating where it ends. */
if (low_func_vma < val || fnname == NULL)
main_file_name = NULL;
break;
}
/* We know that we have to get to at least this point in the
stabs entries for this offset. */
info->cached_stab = stab;
info->cached_str = str;
info->cached_stroff = stroff;
current_file_name = name;
/* Look ahead to the next symbol. Two consecutive N_SO
symbols are a directory and a file name. */
if (stab + STABSIZE >= stabend
|| *(stab + STABSIZE + TYPEOFF) != N_SO)
directory_name = NULL;
else
{
stab += STABSIZE;
directory_name = current_file_name;
current_file_name = str + bfd_get_32 (abfd, stab + STRDXOFF);
}
main_file_name = current_file_name;
break;
case N_SOL:
/* The name of an include file. */
current_file_name = str + bfd_get_32 (abfd, stab + STRDXOFF);
break;
case N_SLINE:
case N_DSLINE:
case N_BSLINE:
/* A line number. The value is relative to the start of the
current function. */
val = fnaddr + bfd_get_32 (abfd, stab + VALOFF);
if (val >= low_line_vma && val <= offset)
{
*pline = bfd_get_16 (abfd, stab + DESCOFF);
low_line_vma = val;
line_file_name = current_file_name;
}
break;
case N_FUN:
/* A function name. */
val = bfd_get_32 (abfd, stab + VALOFF);
name = str + bfd_get_32 (abfd, stab + STRDXOFF);
/* An empty string here indicates the end of a function, and
the value is relative to fnaddr. */
if (*name == '\0')
{
val += fnaddr;
if (val >= low_func_vma && val < offset)
fnname = NULL;
}
else
{
if (val >= low_func_vma && val <= offset)
{
fnname = name;
low_func_vma = val;
}
fnaddr = val;
}
break;
}
if (done)
break;
}
if (main_file_name == NULL)
{
/* No information found. */
return true;
}
*pfound = true;
if (*pline != 0)
main_file_name = line_file_name;
if (main_file_name != NULL)
{
if (main_file_name[0] == '/' || directory_name == NULL)
*pfilename = main_file_name;
else
{
size_t dirlen;
dirlen = strlen (directory_name);
if (info->filename == NULL
|| strncmp (info->filename, directory_name, dirlen) != 0
|| strcmp (info->filename + dirlen, main_file_name) != 0)
{
if (info->filename != NULL)
free (info->filename);
info->filename = (char *) bfd_malloc (dirlen +
strlen (main_file_name)
+ 1);
if (info->filename == NULL)
return false;
strcpy (info->filename, directory_name);
strcpy (info->filename + dirlen, main_file_name);
}
*pfilename = info->filename;
}
}
if (fnname != NULL)
{
char *s;
/* This will typically be something like main:F(0,1), so we want
to clobber the colon. It's OK to change the name, since the
string is in our own local storage anyhow. */
s = strchr (fnname, ':');
if (s != NULL)
*s = '\0';
*pfnname = fnname;
}
return true;
}