This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: ld/2338: objdump -d -l doesn't work correctly
On Tue, Feb 28, 2006 at 01:50:53PM -0500, Daniel Jacobowitz wrote:
> On Tue, Feb 28, 2006 at 10:23:52AM -0800, H. J. Lu wrote:
> > On Tue, Feb 28, 2006 at 09:14:41AM -0800, H. J. Lu wrote:
> > > > HJ, "may not work correctly" doesn't say anything about why you really
> > > > need a gap. If you do need a gap, then there is a bug somewhere else.
> > > > That should be fixed. Presumably the same problem, whatever it is,
> > > > could affect final linked executables with more than one text section.
> > >
> > > decode_line_info in dwarf2.c calls add_line_info for both low_pc
> > > and high_pc. If there is no gap, there may be 2 entries in line info
> > > table with the same address. The line info looks up will fail if
> > > an address matches more than 2 lines.
> > >
> >
> > add_line_info should sort entries with the same address by line number.
> > This patch does that.
>
> Anything related to debug info line mappings that needs to sort by line
> number is very suspect. It sounds like you're hacking around invalid
> or misinterpreted data.
>
> Maybe you just need to handle end_sequence specially, possibly again
> by sorting it before other entries.
>
Here is the updated patch.
H.J.
---
2006-02-28 H.J. Lu <hongjiu.lu@intel.com>
PR binutils/2338
* dwarf2.c (loadable_section): New struct.
(dwarf2_debug): Add loadable_section_count and
loadable_sections.
(add_line_info): Insert entries of the same address with the
proper order of end_sequence.
(check_function_name): Removed.
(unset_sections): New.
(place_sections): New.
(_bfd_dwarf2_find_nearest_line): Updated. Call place_sections
and unset_sections on relocatable files.
(_bfd_dwarf2_find_line): Likewise.
--- bfd/dwarf2.c.rel 2006-02-16 10:08:05.000000000 -0800
+++ bfd/dwarf2.c 2006-02-28 11:39:27.000000000 -0800
@@ -74,6 +74,12 @@ struct dwarf_block
bfd_byte *data;
};
+struct loadable_section
+{
+ asection *section;
+ bfd_vma adj_vma;
+};
+
struct dwarf2_debug
{
/* A list of all previously read comp_units. */
@@ -124,6 +130,12 @@ struct dwarf2_debug
calling chain for subsequent calls to bfd_find_inliner_info to
use. */
struct funcinfo *inliner_chain;
+
+ /* Number of loadable sections. */
+ unsigned int loadable_section_count;
+
+ /* Array of loadable sections. */
+ struct loadable_section *loadable_sections;
};
struct arange
@@ -803,6 +815,15 @@ add_line_info (struct line_info_table *t
{
/* Abnormal but easy: lcl_head is 1) in the *middle* of the line
list and 2) the head of 'info'. */
+ if (address == table->lcl_head->prev_line->address
+ && end_sequence != 0
+ && table->lcl_head->end_sequence != 0
+ && table->lcl_head->prev_line->end_sequence == 0)
+ {
+ /* If the new adress is the same, we need to make sure that
+ the order of end_sequence is correct. */
+ table->lcl_head = table->lcl_head->prev_line;
+ }
info->prev_line = table->lcl_head->prev_line;
table->lcl_head->prev_line = info;
break;
@@ -2179,28 +2200,91 @@ find_debug_info (bfd *abfd, asection *af
return NULL;
}
-/* Return TRUE if there is no mismatch bewteen function FUNC and
- section SECTION from symbol table SYMBOLS in ABFD. */
+/* Unset vmas for loadable sections in STASH. */
+
+static void
+unset_sections (struct dwarf2_debug *stash)
+{
+ unsigned int i;
+ struct loadable_section *p;
+
+ i = stash->loadable_section_count;
+ p = stash->loadable_sections;
+ for (; i > 0; i--, p++)
+ p->section->vma = 0;
+}
+
+/* Set unique vmas for loadable sections in ABFD and save vmas in
+ STASH for unset_sections. */
static bfd_boolean
-check_function_name (bfd *abfd, asection *section, asymbol **symbols,
- const char *func)
+place_sections (bfd *abfd, struct dwarf2_debug *stash)
{
- /* Mismatch can only happen when we have 2 functions with the same
- address. It can only occur in a relocatable file. */
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
- && func != NULL
- && section != NULL
- && symbols != NULL)
- {
- asymbol **p;
-
- for (p = symbols; *p != NULL; p++)
- {
- if (((*p)->flags & BSF_FUNCTION) != 0
- && (*p)->name != NULL
- && strcmp ((*p)->name, func) == 0)
- return (*p)->section == section;
+ struct loadable_section *p;
+ unsigned int i;
+
+ if (stash->loadable_section_count != 0)
+ {
+ i = stash->loadable_section_count;
+ p = stash->loadable_sections;
+ for (; i > 0; i--, p++)
+ p->section->vma = p->adj_vma;
+ }
+ else
+ {
+ asection *sect;
+ bfd_vma last_vma = 0;
+ bfd_size_type amt;
+ struct loadable_section *p;
+
+ i = 0;
+ for (sect = abfd->sections; sect != NULL; sect = sect->next)
+ {
+ bfd_size_type sz;
+
+ if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+ continue;
+
+ sz = sect->rawsize ? sect->rawsize : sect->size;
+ if (sz == 0)
+ continue;
+
+ i++;
+ }
+
+ amt = i * sizeof (struct loadable_section);
+ p = (struct loadable_section *) bfd_zalloc (abfd, amt);
+ if (! p)
+ return FALSE;
+
+ stash->loadable_sections = p;
+ stash->loadable_section_count = i;
+
+ for (sect = abfd->sections; sect != NULL; sect = sect->next)
+ {
+ bfd_size_type sz;
+
+ if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+ continue;
+
+ sz = sect->rawsize ? sect->rawsize : sect->size;
+ if (sz == 0)
+ continue;
+
+ p->section = sect;
+ if (last_vma != 0)
+ {
+ /* Align the new address to the current section
+ alignment. */
+ last_vma = ((last_vma
+ + ~((bfd_vma) -1 << sect->alignment_power))
+ & ((bfd_vma) -1 << sect->alignment_power));
+ sect->vma = last_vma;
+ }
+ p->adj_vma = sect->vma;
+ last_vma += sect->vma + sz;
+
+ p++;
}
}
@@ -2239,7 +2323,27 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
struct comp_unit* each;
+ bfd_vma found = FALSE;
+
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 ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ {
+ if (! place_sections (abfd, stash))
+ return FALSE;
+ }
+
addr = offset;
if (section->output_section)
addr += section->output_section->vma + section->output_offset;
@@ -2256,15 +2360,10 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
addr_size = 4;
BFD_ASSERT (addr_size == 4 || addr_size == 8);
- if (! stash)
+ if (! *pinfo)
{
bfd_size_type total_size;
asection *msec;
- bfd_size_type amt = sizeof (struct dwarf2_debug);
-
- stash = bfd_zalloc (abfd, amt);
- if (! stash)
- return FALSE;
*pinfo = stash;
@@ -2273,7 +2372,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
/* No dwarf2 info. Note that at this point the stash
has been allocated, but contains zeros, this lets
future calls to this function fail quicker. */
- return FALSE;
+ goto done;
/* 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
@@ -2285,7 +2384,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
stash->info_ptr = bfd_alloc (abfd, total_size);
if (stash->info_ptr == NULL)
- return FALSE;
+ goto done;
stash->info_ptr_end = stash->info_ptr;
@@ -2319,7 +2418,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
/* 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)
- return FALSE;
+ goto done;
stash->inliner_chain = NULL;
@@ -2328,10 +2427,11 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
if (comp_unit_contains_address (each, addr)
&& comp_unit_find_nearest_line (each, addr, filename_ptr,
functionname_ptr,
- linenumber_ptr, stash)
- && check_function_name (abfd, section, symbols,
- *functionname_ptr))
- return TRUE;
+ linenumber_ptr, stash))
+ {
+ found = TRUE;
+ goto done;
+ }
/* Read each remaining comp. units checking each as they are read. */
while (stash->info_ptr < stash->info_ptr_end)
@@ -2398,15 +2498,20 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
filename_ptr,
functionname_ptr,
linenumber_ptr,
- stash)
- && check_function_name (abfd, section, symbols,
- *functionname_ptr))
- return TRUE;
+ stash))
+ {
+ found = TRUE;
+ goto done;
+ }
}
}
}
- return FALSE;
+done:
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ unset_sections (stash);
+
+ return found;
}
/* The DWARF2 version of find_line. Return TRUE if the line is found
@@ -2438,10 +2543,29 @@ _bfd_dwarf2_find_line (bfd *abfd,
asection *section;
- bfd_boolean found;
+ 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;
@@ -2449,19 +2573,13 @@ _bfd_dwarf2_find_line (bfd *abfd,
addr += section->vma;
*filename_ptr = NULL;
- stash = *pinfo;
*filename_ptr = NULL;
*linenumber_ptr = 0;
- if (! stash)
+ if (! *pinfo)
{
bfd_size_type total_size;
asection *msec;
- bfd_size_type amt = sizeof (struct dwarf2_debug);
-
- stash = bfd_zalloc (abfd, amt);
- if (! stash)
- return FALSE;
*pinfo = stash;
@@ -2470,7 +2588,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
/* No dwarf2 info. Note that at this point the stash
has been allocated, but contains zeros, this lets
future calls to this function fail quicker. */
- return FALSE;
+ goto done;
/* 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
@@ -2482,7 +2600,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
stash->info_ptr = bfd_alloc (abfd, total_size);
if (stash->info_ptr == NULL)
- return FALSE;
+ goto done;
stash->info_ptr_end = stash->info_ptr;
@@ -2516,7 +2634,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
/* 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)
- return FALSE;
+ goto done;
stash->inliner_chain = NULL;
@@ -2528,7 +2646,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
found = comp_unit_find_line (each, symbol, addr, filename_ptr,
linenumber_ptr, stash);
if (found)
- return found;
+ goto done;
}
/* The DWARF2 spec says that the initial length field, and the
@@ -2605,12 +2723,16 @@ _bfd_dwarf2_find_line (bfd *abfd,
linenumber_ptr,
stash));
if (found)
- return TRUE;
+ goto done;
}
}
}
- return FALSE;
+done:
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ unset_sections (stash);
+
+ return found;
}
bfd_boolean