This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: Remove code duplication in dwarf2.c
- From: "H. J. Lu" <hjl at lucon dot org>
- To: Nick Clifton <nickc at redhat dot com>
- Cc: binutils at sources dot redhat dot com
- Date: Sat, 23 Jun 2007 09:04:01 -0700
- Subject: Re: PATCH: Remove code duplication in dwarf2.c
- References: <20070622164806.GA5874@lucon.org> <467CDB2B.3090201@redhat.com>
On Sat, Jun 23, 2007 at 09:34:51AM +0100, Nick Clifton wrote:
> Hi H.J.
>
> >Both _bfd_dwarf2_find_nearest_line and _bfd_dwarf2_find_line have
> >the same code to follow .gnu_debuglink section. This patch uses
> >a function instead of duplicating the code. OK to install?
>
> Sort-of. Andreas has just posted a patch to provide a global debug
> directory parameter to the call to bfd_follow_gnu_debuglink() which I
> would like to see integrated into your patch. Plus it seems to me that
> there is a lot more code duplication between _bfd_dwarf2_find_line and
> _bfd_dwarf2_find_nearest_line, so maybe you could expand your patch even
> more ?
>
How about this path?
H.J.
---
2007-06-23 H.J. Lu <hongjiu.lu@intel.com>
* dwarf2.c (find_line): New.
(_bfd_dwarf2_find_nearest_line): Use it.
(_bfd_dwarf2_find_line): Use it.
--- bfd/dwarf2.c.dup 2007-06-23 07:55:38.000000000 -0700
+++ bfd/dwarf2.c 2007-06-23 09:02:36.000000000 -0700
@@ -2301,22 +2301,17 @@ place_sections (bfd *abfd, struct dwarf2
return TRUE;
}
-/* The DWARF2 version of find_nearest_line. Return TRUE if the line
- is found without error. ADDR_SIZE is the number of bytes in the
- initial .debug_info length field and in the abbreviation offset.
- You may use zero to indicate that the default value should be
- used. */
-
-bfd_boolean
-_bfd_dwarf2_find_nearest_line (bfd *abfd,
- asection *section,
- asymbol **symbols,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr,
- unsigned int *linenumber_ptr,
- unsigned int addr_size,
- void **pinfo)
+/* Return TRUE if the line is found without error. ADDR_SIZE is the
+ number of bytes in the initial .debug_info length field and in the
+ abbreviation offset. You may use zero to indicate that the default
+ value should be used. */
+
+static bfd_boolean
+find_line (bfd *abfd, 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,
@@ -2331,6 +2326,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
bfd_vma addr;
struct comp_unit* each;
bfd_vma found = FALSE;
+ bfd_boolean do_line;
stash = *pinfo;
@@ -2351,7 +2347,22 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
return FALSE;
}
- addr = offset;
+ 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
@@ -2360,13 +2371,6 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
*functionname_ptr = NULL;
*linenumber_ptr = 0;
- /* The DWARF2 spec says that the initial length field, and the
- offset of the abbreviation table, should both be 4-byte values.
- However, some compilers do things differently. */
- if (addr_size == 0)
- addr_size = 4;
- BFD_ASSERT (addr_size == 4 || addr_size == 8);
-
if (! *pinfo)
{
bfd *debug_bfd;
@@ -2452,14 +2456,30 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
/* Check the previously read comp. units first. */
for (each = stash->all_comp_units; each; each = each->next_unit)
- if (comp_unit_contains_address (each, addr)
- && comp_unit_find_nearest_line (each, addr, filename_ptr,
- functionname_ptr,
- linenumber_ptr, stash))
- {
- found = TRUE;
+ {
+ if (do_line)
+ found = (((symbol->flags & BSF_FUNCTION) == 0
+ || comp_unit_contains_address (each, addr))
+ && comp_unit_find_line (each, symbol, addr,
+ filename_ptr, linenumber_ptr,
+ stash));
+ else
+ found = (comp_unit_contains_address (each, addr)
+ && comp_unit_find_nearest_line (each, addr,
+ filename_ptr,
+ functionname_ptr,
+ linenumber_ptr,
+ stash));
+ if (found)
goto done;
- }
+ }
+
+ /* The DWARF2 spec says that the initial length field, and the
+ offset of the abbreviation table, should both be 4-byte values.
+ However, some compilers do things differently. */
+ if (addr_size == 0)
+ addr_size = 4;
+ BFD_ASSERT (addr_size == 4 || addr_size == 8);
/* Read each remaining comp. units checking each as they are read. */
while (stash->info_ptr < stash->info_ptr_end)
@@ -2526,17 +2546,24 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
unit->high == 0), we need to consult the line info
table to see if a compilation unit contains the given
address. */
- if ((each->arange.high == 0
- || comp_unit_contains_address (each, addr))
- && comp_unit_find_nearest_line (each, addr,
- filename_ptr,
- functionname_ptr,
- linenumber_ptr,
- stash))
- {
- found = TRUE;
- goto done;
- }
+ if (do_line)
+ found = (((symbol->flags & BSF_FUNCTION) == 0
+ || each->arange.high == 0
+ || comp_unit_contains_address (each, addr))
+ && comp_unit_find_line (each, symbol, addr,
+ filename_ptr,
+ linenumber_ptr,
+ stash));
+ else
+ found = ((each->arange.high == 0
+ || comp_unit_contains_address (each, addr))
+ && comp_unit_find_nearest_line (each, addr,
+ filename_ptr,
+ functionname_ptr,
+ linenumber_ptr,
+ stash));
+ if (found)
+ goto done;
}
}
}
@@ -2548,6 +2575,25 @@ done:
return found;
}
+/* The DWARF2 version of find_nearest_line. Return TRUE if the line
+ is found without error. */
+
+bfd_boolean
+_bfd_dwarf2_find_nearest_line (bfd *abfd,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *linenumber_ptr,
+ unsigned int addr_size,
+ void **pinfo)
+{
+ return find_line (abfd, section, offset, NULL, symbols, filename_ptr,
+ functionname_ptr, linenumber_ptr, addr_size,
+ pinfo);
+}
+
/* The DWARF2 version of find_line. Return TRUE if the line is found
without error. */
@@ -2560,236 +2606,9 @@ _bfd_dwarf2_find_line (bfd *abfd,
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;
- asection *section;
- bfd_boolean found = FALSE;
-
- section = bfd_get_section (symbol);
-
- stash = *pinfo;
-
- if (! stash)
- {
- bfd_size_type amt = sizeof (struct dwarf2_debug);
-
- stash = bfd_zalloc (abfd, amt);
- if (! stash)
- return FALSE;
- }
-
- /* In a relocatable file, 2 functions may have the same address.
- We change the section vma so that they won't overlap. */
- if (!stash && (abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- {
- if (! place_sections (abfd, stash))
- return FALSE;
- }
-
- addr = symbol->value;
- if (section->output_section)
- addr += section->output_section->vma + section->output_offset;
- else
- addr += section->vma;
-
- *filename_ptr = NULL;
- *filename_ptr = NULL;
- *linenumber_ptr = 0;
-
- if (! *pinfo)
- {
- bfd *debug_bfd;
- bfd_size_type total_size;
- asection *msec;
-
- *pinfo = stash;
-
- msec = find_debug_info (abfd, NULL);
- if (msec == NULL)
- {
- char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
-
- if (debug_filename == NULL)
- /* No dwarf2 info, and no gnu_debuglink to follow.
- Note that at this point the stash has been allocated, but
- contains zeros. This lets future calls to this function
- fail more quickly. */
- goto done;
-
- if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
- || ! bfd_check_format (debug_bfd, bfd_object)
- || (msec = find_debug_info (debug_bfd, NULL)) == NULL)
- {
- if (debug_bfd)
- bfd_close (debug_bfd);
- /* FIXME: Should we report our failure to follow the debuglink ? */
- free (debug_filename);
- goto done;
- }
- }
- else
- debug_bfd = abfd;
-
- /* There can be more than one DWARF2 info section in a BFD these days.
- Read them all in and produce one large stash. We do this in two
- passes - in the first pass we just accumulate the section sizes.
- In the second pass we read in the section's contents. The allows
- us to avoid reallocing the data as we add sections to the stash. */
- for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec))
- total_size += msec->size;
-
- stash->info_ptr = bfd_alloc (debug_bfd, total_size);
- if (stash->info_ptr == NULL)
- goto done;
-
- stash->info_ptr_end = stash->info_ptr;
-
- for (msec = find_debug_info (debug_bfd, NULL);
- msec;
- msec = find_debug_info (debug_bfd, msec))
- {
- bfd_size_type size;
- bfd_size_type start;
-
- size = msec->size;
- if (size == 0)
- continue;
-
- start = stash->info_ptr_end - stash->info_ptr;
-
- if ((bfd_simple_get_relocated_section_contents
- (debug_bfd, msec, stash->info_ptr + start, symbols)) == NULL)
- continue;
-
- stash->info_ptr_end = stash->info_ptr + start + size;
- }
-
- BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
-
- stash->sec = find_debug_info (debug_bfd, NULL);
- stash->sec_info_ptr = stash->info_ptr;
- stash->syms = symbols;
- stash->bfd = debug_bfd;
- }
-
- /* A null info_ptr indicates that there is no dwarf2 info
- (or that an error occured while setting up the stash). */
- if (! stash->info_ptr)
- goto done;
-
- stash->inliner_chain = NULL;
-
- /* Check the previously read comp. units first. */
- for (each = stash->all_comp_units; each; each = each->next_unit)
- if ((symbol->flags & BSF_FUNCTION) == 0
- || comp_unit_contains_address (each, addr))
- {
- found = comp_unit_find_line (each, symbol, addr, filename_ptr,
- linenumber_ptr, stash);
- if (found)
- goto done;
- }
-
- /* The DWARF2 spec says that the initial length field, and the
- offset of the abbreviation table, should both be 4-byte values.
- However, some compilers do things differently. */
- if (addr_size == 0)
- addr_size = 4;
- BFD_ASSERT (addr_size == 4 || addr_size == 8);
-
- /* Read each remaining comp. units checking each as they are read. */
- while (stash->info_ptr < stash->info_ptr_end)
- {
- bfd_vma length;
- unsigned int offset_size = addr_size;
- bfd_byte *info_ptr_unit = stash->info_ptr;
-
- length = read_4_bytes (stash->bfd, stash->info_ptr);
- /* A 0xffffff length is the DWARF3 way of indicating we use
- 64-bit offsets, instead of 32-bit offsets. */
- if (length == 0xffffffff)
- {
- offset_size = 8;
- length = read_8_bytes (stash->bfd, stash->info_ptr + 4);
- stash->info_ptr += 12;
- }
- /* A zero length is the IRIX way of indicating 64-bit offsets,
- mostly because the 64-bit length will generally fit in 32
- bits, and the endianness helps. */
- else if (length == 0)
- {
- offset_size = 8;
- length = read_4_bytes (stash->bfd, stash->info_ptr + 4);
- stash->info_ptr += 8;
- }
- /* In the absence of the hints above, we assume 32-bit DWARF2
- offsets even for targets with 64-bit addresses, because:
- a) most of the time these targets will not have generated
- more than 2Gb of debug info and so will not need 64-bit
- offsets,
- and
- b) if they do use 64-bit offsets but they are not using
- the size hints that are tested for above then they are
- not conforming to the DWARF3 standard anyway. */
- else if (addr_size == 8)
- {
- offset_size = 4;
- stash->info_ptr += 4;
- }
- else
- stash->info_ptr += 4;
-
- if (length > 0)
- {
- each = parse_comp_unit (stash, length, info_ptr_unit,
- offset_size);
- stash->info_ptr += length;
-
- if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
- == stash->sec->size)
- {
- stash->sec = find_debug_info (stash->bfd, stash->sec);
- stash->sec_info_ptr = stash->info_ptr;
- }
-
- if (each)
- {
- each->next_unit = stash->all_comp_units;
- stash->all_comp_units = each;
-
- /* DW_AT_low_pc and DW_AT_high_pc are optional for
- compilation units. If we don't have them (i.e.,
- unit->high == 0), we need to consult the line info
- table to see if a compilation unit contains the given
- address. */
- found = (((symbol->flags & BSF_FUNCTION) == 0
- || each->arange.high <= 0
- || comp_unit_contains_address (each, addr))
- && comp_unit_find_line (each, symbol, addr,
- filename_ptr,
- linenumber_ptr,
- stash));
- if (found)
- goto done;
- }
- }
- }
-
-done:
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- unset_sections (stash);
-
- return found;
+ return find_line (abfd, NULL, 0, symbol, symbols, filename_ptr,
+ NULL, linenumber_ptr, addr_size,
+ pinfo);
}
bfd_boolean