Line 3115... |
Line 3115... |
filename_ptr, linenumber_ptr);
|
filename_ptr, linenumber_ptr);
|
return info_hash_lookup_varinfo (stash->varinfo_hash_table, sym, addr,
|
return info_hash_lookup_varinfo (stash->varinfo_hash_table, sym, addr,
|
filename_ptr, linenumber_ptr);
|
filename_ptr, linenumber_ptr);
|
}
|
}
|
|
|
/* Find the source code location of SYMBOL. If SYMBOL is NULL
|
/* Read debug information from DEBUG_BFD when DEBUG_BFD is specified.
|
then find the nearest source code location corresponding to
|
If DEBUG_BFD is not specified, we read debug information from ABFD
|
the address SECTION + OFFSET.
|
or its gnu_debuglink. The results will be stored in PINFO.
|
Returns TRUE if the line is found without error and fills in
|
The function returns TRUE iff debug information is ready. */
|
FILENAME_PTR and LINENUMBER_PTR. In the case where SYMBOL was
|
|
NULL the FUNCTIONNAME_PTR is also filled in.
|
|
SYMBOLS contains the symbol table for ABFD.
|
|
DEBUG_SECTIONS contains the name of the dwarf debug sections.
|
|
ADDR_SIZE is the number of bytes in the initial .debug_info length
|
|
field and in the abbreviation offset, or zero to indicate that the
|
|
default value should be used. */
|
|
|
|
static bfd_boolean
|
bfd_boolean
|
find_line (bfd *abfd,
|
_bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
|
const struct dwarf_debug_section *debug_sections,
|
const struct dwarf_debug_section *debug_sections,
|
asection *section,
|
|
bfd_vma offset,
|
|
asymbol *symbol,
|
|
asymbol **symbols,
|
asymbol **symbols,
|
const char **filename_ptr,
|
|
const char **functionname_ptr,
|
|
unsigned int *linenumber_ptr,
|
|
unsigned int addr_size,
|
|
void **pinfo)
|
void **pinfo)
|
{
|
{
|
/* Read each compilation unit from the section .debug_info, and check
|
|
to see if it contains the address we are searching for. If yes,
|
|
lookup the address, and return the line number info. If no, go
|
|
on to the next compilation unit.
|
|
|
|
We keep a list of all the previously read compilation units, and
|
|
a pointer to the next un-read compilation unit. Check the
|
|
previously read units before reading more. */
|
|
struct dwarf2_debug *stash;
|
|
/* What address are we looking for? */
|
|
bfd_vma addr;
|
|
struct comp_unit* each;
|
|
bfd_vma found = FALSE;
|
|
bfd_boolean do_line;
|
|
|
|
stash = (struct dwarf2_debug *) *pinfo;
|
|
|
|
if (! stash)
|
|
{
|
|
bfd_size_type amt = sizeof (struct dwarf2_debug);
|
bfd_size_type amt = sizeof (struct dwarf2_debug);
|
|
bfd_size_type total_size;
|
|
asection *msec;
|
|
struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;
|
|
|
|
if (stash != NULL)
|
|
return TRUE;
|
|
|
stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt);
|
stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt);
|
if (! stash)
|
if (! stash)
|
return FALSE;
|
return FALSE;
|
stash->debug_sections = debug_sections;
|
stash->debug_sections = debug_sections;
|
}
|
|
|
|
/* In a relocatable file, 2 functions may have the same address.
|
|
We change the section vma so that they won't overlap. */
|
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
|
|
{
|
|
if (! place_sections (abfd, stash))
|
|
return FALSE;
|
|
}
|
|
|
|
do_line = (section == NULL
|
|
&& offset == 0
|
|
&& functionname_ptr == NULL
|
|
&& symbol != NULL);
|
|
if (do_line)
|
|
{
|
|
addr = symbol->value;
|
|
section = bfd_get_section (symbol);
|
|
}
|
|
else if (section != NULL
|
|
&& functionname_ptr != NULL
|
|
&& symbol == NULL)
|
|
addr = offset;
|
|
else
|
|
abort ();
|
|
|
|
if (section->output_section)
|
|
addr += section->output_section->vma + section->output_offset;
|
|
else
|
|
addr += section->vma;
|
|
*filename_ptr = NULL;
|
|
if (! do_line)
|
|
*functionname_ptr = NULL;
|
|
*linenumber_ptr = 0;
|
|
|
|
if (! *pinfo)
|
|
{
|
|
bfd *debug_bfd;
|
|
bfd_size_type total_size;
|
|
asection *msec;
|
|
|
|
*pinfo = stash;
|
*pinfo = stash;
|
|
|
msec = find_debug_info (abfd, debug_sections, NULL);
|
if (debug_bfd == NULL)
|
if (msec == NULL)
|
debug_bfd = abfd;
|
|
|
|
msec = find_debug_info (debug_bfd, debug_sections, NULL);
|
|
if (msec == NULL && abfd == debug_bfd)
|
{
|
{
|
char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
|
char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
|
|
|
if (debug_filename == NULL)
|
if (debug_filename == NULL)
|
/* No dwarf2 info, and no gnu_debuglink to follow.
|
/* No dwarf2 info, and no gnu_debuglink to follow.
|
Note that at this point the stash has been allocated, but
|
Note that at this point the stash has been allocated, but
|
contains zeros. This lets future calls to this function
|
contains zeros. This lets future calls to this function
|
fail more quickly. */
|
fail more quickly. */
|
goto done;
|
return FALSE;
|
|
|
if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
|
if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
|
|| ! bfd_check_format (debug_bfd, bfd_object)
|
|| ! bfd_check_format (debug_bfd, bfd_object)
|
|| (msec = find_debug_info (debug_bfd,
|
|| (msec = find_debug_info (debug_bfd,
|
debug_sections, NULL)) == NULL)
|
debug_sections, NULL)) == NULL)
|
{
|
{
|
if (debug_bfd)
|
if (debug_bfd)
|
bfd_close (debug_bfd);
|
bfd_close (debug_bfd);
|
/* FIXME: Should we report our failure to follow the debuglink ? */
|
/* FIXME: Should we report our failure to follow the debuglink ? */
|
free (debug_filename);
|
free (debug_filename);
|
goto done;
|
return FALSE;
|
}
|
}
|
}
|
}
|
else
|
|
debug_bfd = abfd;
|
|
|
|
/* There can be more than one DWARF2 info section in a BFD these
|
/* There can be more than one DWARF2 info section in a BFD these
|
days. First handle the easy case when there's only one. If
|
days. First handle the easy case when there's only one. If
|
there's more than one, try case two: none of the sections is
|
there's more than one, try case two: none of the sections is
|
compressed. In that case, read them all in and produce one
|
compressed. In that case, read them all in and produce one
|
Line 3253... |
Line 3187... |
/* Case 1: only one info section. */
|
/* Case 1: only one info section. */
|
total_size = msec->size;
|
total_size = msec->size;
|
if (! read_section (debug_bfd, &stash->debug_sections[debug_info],
|
if (! read_section (debug_bfd, &stash->debug_sections[debug_info],
|
symbols, 0,
|
symbols, 0,
|
&stash->info_ptr_memory, &total_size))
|
&stash->info_ptr_memory, &total_size))
|
goto done;
|
return FALSE;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Case 2: multiple sections. */
|
/* Case 2: multiple sections. */
|
for (total_size = 0;
|
for (total_size = 0;
|
Line 3265... |
Line 3199... |
msec = find_debug_info (debug_bfd, debug_sections, msec))
|
msec = find_debug_info (debug_bfd, debug_sections, msec))
|
total_size += msec->size;
|
total_size += msec->size;
|
|
|
stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
|
stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
|
if (stash->info_ptr_memory == NULL)
|
if (stash->info_ptr_memory == NULL)
|
goto done;
|
return FALSE;
|
|
|
total_size = 0;
|
total_size = 0;
|
for (msec = find_debug_info (debug_bfd, debug_sections, NULL);
|
for (msec = find_debug_info (debug_bfd, debug_sections, NULL);
|
msec;
|
msec;
|
msec = find_debug_info (debug_bfd, debug_sections, msec))
|
msec = find_debug_info (debug_bfd, debug_sections, msec))
|
Line 3281... |
Line 3215... |
continue;
|
continue;
|
|
|
if (!(bfd_simple_get_relocated_section_contents
|
if (!(bfd_simple_get_relocated_section_contents
|
(debug_bfd, msec, stash->info_ptr_memory + total_size,
|
(debug_bfd, msec, stash->info_ptr_memory + total_size,
|
symbols)))
|
symbols)))
|
goto done;
|
return FALSE;
|
|
|
total_size += size;
|
total_size += size;
|
}
|
}
|
}
|
}
|
|
|
Line 3293... |
Line 3227... |
stash->info_ptr_end = stash->info_ptr + total_size;
|
stash->info_ptr_end = stash->info_ptr + total_size;
|
stash->sec = find_debug_info (debug_bfd, debug_sections, NULL);
|
stash->sec = find_debug_info (debug_bfd, debug_sections, NULL);
|
stash->sec_info_ptr = stash->info_ptr;
|
stash->sec_info_ptr = stash->info_ptr;
|
stash->syms = symbols;
|
stash->syms = symbols;
|
stash->bfd_ptr = debug_bfd;
|
stash->bfd_ptr = debug_bfd;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Find the source code location of SYMBOL. If SYMBOL is NULL
|
|
then find the nearest source code location corresponding to
|
|
the address SECTION + OFFSET.
|
|
Returns TRUE if the line is found without error and fills in
|
|
FILENAME_PTR and LINENUMBER_PTR. In the case where SYMBOL was
|
|
NULL the FUNCTIONNAME_PTR is also filled in.
|
|
SYMBOLS contains the symbol table for ABFD.
|
|
DEBUG_SECTIONS contains the name of the dwarf debug sections.
|
|
ADDR_SIZE is the number of bytes in the initial .debug_info length
|
|
field and in the abbreviation offset, or zero to indicate that the
|
|
default value should be used. */
|
|
|
|
static bfd_boolean
|
|
find_line (bfd *abfd,
|
|
const struct dwarf_debug_section *debug_sections,
|
|
asection *section,
|
|
bfd_vma offset,
|
|
asymbol *symbol,
|
|
asymbol **symbols,
|
|
const char **filename_ptr,
|
|
const char **functionname_ptr,
|
|
unsigned int *linenumber_ptr,
|
|
unsigned int addr_size,
|
|
void **pinfo)
|
|
{
|
|
/* Read each compilation unit from the section .debug_info, and check
|
|
to see if it contains the address we are searching for. If yes,
|
|
lookup the address, and return the line number info. If no, go
|
|
on to the next compilation unit.
|
|
|
|
We keep a list of all the previously read compilation units, and
|
|
a pointer to the next un-read compilation unit. Check the
|
|
previously read units before reading more. */
|
|
struct dwarf2_debug *stash;
|
|
/* What address are we looking for? */
|
|
bfd_vma addr;
|
|
struct comp_unit* each;
|
|
bfd_vma found = FALSE;
|
|
bfd_boolean do_line;
|
|
|
|
*filename_ptr = NULL;
|
|
if (functionname_ptr != NULL)
|
|
*functionname_ptr = NULL;
|
|
*linenumber_ptr = 0;
|
|
|
|
if (! _bfd_dwarf2_slurp_debug_info (abfd, NULL,
|
|
debug_sections, symbols, pinfo))
|
|
return FALSE;
|
|
|
|
stash = (struct dwarf2_debug *) *pinfo;
|
|
|
|
/* In a relocatable file, 2 functions may have the same address.
|
|
We change the section vma so that they won't overlap. */
|
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
|
|
{
|
|
if (! place_sections (abfd, stash))
|
|
return FALSE;
|
}
|
}
|
|
|
|
do_line = (section == NULL
|
|
&& offset == 0
|
|
&& functionname_ptr == NULL
|
|
&& symbol != NULL);
|
|
if (do_line)
|
|
{
|
|
addr = symbol->value;
|
|
section = bfd_get_section (symbol);
|
|
}
|
|
else if (section != NULL
|
|
&& functionname_ptr != NULL
|
|
&& symbol == NULL)
|
|
addr = offset;
|
|
else
|
|
abort ();
|
|
|
|
if (section->output_section)
|
|
addr += section->output_section->vma + section->output_offset;
|
|
else
|
|
addr += section->vma;
|
|
|
/* A null info_ptr indicates that there is no dwarf2 info
|
/* A null info_ptr indicates that there is no dwarf2 info
|
(or that an error occured while setting up the stash). */
|
(or that an error occured while setting up the stash). */
|
if (! stash->info_ptr)
|
if (! stash->info_ptr)
|
goto done;
|
return FALSE;
|
|
|
stash->inliner_chain = NULL;
|
stash->inliner_chain = NULL;
|
|
|
/* Check the previously read comp. units first. */
|
/* Check the previously read comp. units first. */
|
if (do_line)
|
if (do_line)
|
Line 3525... |
Line 3541... |
|
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
void
|
void
|
_bfd_dwarf2_cleanup_debug_info (bfd *abfd)
|
_bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
|
{
|
{
|
|
struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;;
|
struct comp_unit *each;
|
struct comp_unit *each;
|
struct dwarf2_debug *stash;
|
|
|
|
if (abfd == NULL || elf_tdata (abfd) == NULL)
|
|
return;
|
|
|
|
stash = (struct dwarf2_debug *) elf_tdata (abfd)->dwarf2_find_line_info;
|
|
|
|
if (stash == NULL)
|
if (abfd == NULL || stash == NULL)
|
return;
|
return;
|
|
|
for (each = stash->all_comp_units; each; each = each->next_unit)
|
for (each = stash->all_comp_units; each; each = each->next_unit)
|
{
|
{
|
struct abbrev_info **abbrevs = each->abbrevs;
|
struct abbrev_info **abbrevs = each->abbrevs;
|