[16/21] Fix addr2line mapping - garbage collected modules

Message ID 20250402121759.1962001-17-jovan.dmitrovic@htecgroup.com
State New
Headers
Series Integrate MIPS-Specific Support |

Commit Message

Jovan Dmitrovic April 2, 2025, 12:18 p.m. UTC
  From: Faraz Shahbazker <fshahbazker@wavecomp.com>

Release branch only commit

If all the functions in a C module are garbage-collected by the linker,
debug_ranges for that module consists of a list of empty ranges. In
this case, lookup falls to iterating over the line information without
a range match. If there is other valid code at lower addresses
(starting at 0x0), the defunct line information of a garbage-collected
section will accidentally match against that address, producing
incorrect addr2line output.

There is no clean way of fixing this, so we hack addr2line to
distinguish ranges that were truncated due to garbage-collection from
ranges that were not specified to begin with. If all range-information
of a compilation unit was truncated, then don't fall through to check
line information, but pass over that compilation unit.

Cherry-picked 038a17f
from https://github.com/MIPS/binutils-gdb

Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Milica Matic <milica.matic@htecgroup.com>

bfd/
	* dwarf2.c (arange) <truncated>: New field.
	(arange_add): Set/reset truncated flag for the range.
	(comp_unit_find_nearest_line): Short-circuit to fail for
	compilation unit with only truncated ranges.
---
 bfd/dwarf2.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
  

Comments

Jan Beulich April 2, 2025, 1:28 p.m. UTC | #1
On 02.04.2025 14:18, Jovan Dmitrovic wrote:
> From: Faraz Shahbazker <fshahbazker@wavecomp.com>
> 
> Release branch only commit

Would you mind clarifying what this means (here)?

Jan
  
Jan Beulich April 3, 2025, 8:55 a.m. UTC | #2
On 02.04.2025 14:18, Jovan Dmitrovic wrote:
> From: Faraz Shahbazker <fshahbazker@wavecomp.com>
> 
> Release branch only commit
> 
> If all the functions in a C module are garbage-collected by the linker,
> debug_ranges for that module consists of a list of empty ranges. In
> this case, lookup falls to iterating over the line information without
> a range match. If there is other valid code at lower addresses
> (starting at 0x0), the defunct line information of a garbage-collected
> section will accidentally match against that address, producing
> incorrect addr2line output.
> 
> There is no clean way of fixing this, so we hack addr2line to
> distinguish ranges that were truncated due to garbage-collection from
> ranges that were not specified to begin with.

And why is it necessary to distinguish the two cases?

> If all range-information
> of a compilation unit was truncated, then don't fall through to check
> line information, but pass over that compilation unit.
> 
> Cherry-picked 038a17f
> from https://github.com/MIPS/binutils-gdb

I don't think such should be there in the eventual commits.

Jan

> Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
> Signed-off-by: Milica Matic <milica.matic@htecgroup.com>
> 
> bfd/
> 	* dwarf2.c (arange) <truncated>: New field.
> 	(arange_add): Set/reset truncated flag for the range.
> 	(comp_unit_find_nearest_line): Short-circuit to fail for
> 	compilation unit with only truncated ranges.
> ---
>  bfd/dwarf2.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
> index ceca4225076..20d0ad933bd 100644
> --- a/bfd/dwarf2.c
> +++ b/bfd/dwarf2.c
> @@ -342,6 +342,7 @@ struct arange
>    struct arange *next;
>    bfd_vma low;
>    bfd_vma high;
> +  bool truncated;
>  };
>  
>  /* A minimal decoding of DWARF2 compilation units.  We only decode
> @@ -2319,7 +2320,11 @@ arange_add (struct comp_unit *unit, struct arange *first_arange,
>  
>    /* Ignore empty ranges.  */
>    if (low_pc == high_pc)
> -    return true;
> +    {
> +      if (first_arange->high == 0)
> +	first_arange->truncated = true;
> +      return true;
> +    }
>  
>    if (trie_root != NULL)
>      {
> @@ -2339,6 +2344,7 @@ arange_add (struct comp_unit *unit, struct arange *first_arange,
>      {
>        first_arange->low = low_pc;
>        first_arange->high = high_pc;
> +      first_arange->truncated = false;
>        return true;
>      }
>  
> @@ -2367,6 +2373,7 @@ arange_add (struct comp_unit *unit, struct arange *first_arange,
>      return false;
>    arange->low = low_pc;
>    arange->high = high_pc;
> +  arange->truncated = false;
>    arange->next = first_arange->next;
>    first_arange->next = arange;
>    return true;
> @@ -4733,6 +4740,9 @@ comp_unit_maybe_decode_line_info (struct comp_unit *unit)
>    if (unit->error)
>      return false;
>  
> +  if (unit->arange.truncated)
> +    return false;
> +
>    if (! unit->line_table)
>      {
>        if (! unit->stmtlist)
  

Patch

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index ceca4225076..20d0ad933bd 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -342,6 +342,7 @@  struct arange
   struct arange *next;
   bfd_vma low;
   bfd_vma high;
+  bool truncated;
 };
 
 /* A minimal decoding of DWARF2 compilation units.  We only decode
@@ -2319,7 +2320,11 @@  arange_add (struct comp_unit *unit, struct arange *first_arange,
 
   /* Ignore empty ranges.  */
   if (low_pc == high_pc)
-    return true;
+    {
+      if (first_arange->high == 0)
+	first_arange->truncated = true;
+      return true;
+    }
 
   if (trie_root != NULL)
     {
@@ -2339,6 +2344,7 @@  arange_add (struct comp_unit *unit, struct arange *first_arange,
     {
       first_arange->low = low_pc;
       first_arange->high = high_pc;
+      first_arange->truncated = false;
       return true;
     }
 
@@ -2367,6 +2373,7 @@  arange_add (struct comp_unit *unit, struct arange *first_arange,
     return false;
   arange->low = low_pc;
   arange->high = high_pc;
+  arange->truncated = false;
   arange->next = first_arange->next;
   first_arange->next = arange;
   return true;
@@ -4733,6 +4740,9 @@  comp_unit_maybe_decode_line_info (struct comp_unit *unit)
   if (unit->error)
     return false;
 
+  if (unit->arange.truncated)
+    return false;
+
   if (! unit->line_table)
     {
       if (! unit->stmtlist)