[PATCH] libdw: Don't free uninitialized Dwarf_Abbrev_Hash's of "fake" CUs.

Jonathon Anderson jma14@rice.edu
Thu Oct 31 23:43:00 GMT 2019


fake_{loc,loclists,addr}_cu are Dwarf_CUs that are created separate from
all the others, so their contents are minimal and mostly initialized by
a calloc. On dwarf_end however, they are freed through the same code path
as all the others, so they call DAH_free like all the others. This changes
that so that these three are exempt from DAH and split-DWARF matters, and
swaps the calloc for a malloc so Memcheck will catch any others.
---
> The Dwarf_Abbrev_Hash_free looks in the correct place.  But I don't
> believe the Free split dwarf hunk should not be under the same if
> not-fake block.

That can be fixed.

I don't really like `unit_type = 0`, but its the only value that isn't one
of the DW_UT values. And its what the calloc would've done.

 libdw/dwarf_begin_elf.c | 21 ++++++++++++++++++---
 libdw/dwarf_end.c       |  9 +++++++--
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 8d137414..ebb3eaea 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -223,7 +223,7 @@ valid_p (Dwarf *result)
      inside the .debug_loc or .debug_loclists section.  */
   if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
     {
-      result->fake_loc_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
+      result->fake_loc_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
       if (unlikely (result->fake_loc_cu == NULL))
 	{
 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
@@ -240,12 +240,17 @@ valid_p (Dwarf *result)
 	  result->fake_loc_cu->endp
 	    = (result->sectiondata[IDX_debug_loc]->d_buf
 	       + result->sectiondata[IDX_debug_loc]->d_size);
+	  result->fake_loc_cu->locs = NULL;
+	  result->fake_loc_cu->address_size = 0;
+	  result->fake_loc_cu->version = 0;
+	  result->fake_loc_cu->unit_type = 0;
+	  result->fake_loc_cu->split = NULL;
 	}
     }
 
   if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
     {
-      result->fake_loclists_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
+      result->fake_loclists_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
       if (unlikely (result->fake_loclists_cu == NULL))
 	{
 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
@@ -263,6 +268,11 @@ valid_p (Dwarf *result)
 	  result->fake_loclists_cu->endp
 	    = (result->sectiondata[IDX_debug_loclists]->d_buf
 	       + result->sectiondata[IDX_debug_loclists]->d_size);
+	  result->fake_loclists_cu->locs = NULL;
+	  result->fake_loclists_cu->address_size = 0;
+	  result->fake_loclists_cu->version = 0;
+	  result->fake_loclists_cu->unit_type = 0;
+	  result->fake_loclists_cu->split = NULL;
 	}
     }
 
@@ -272,7 +282,7 @@ valid_p (Dwarf *result)
      inside the .debug_addr section, if it exists.  */
   if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
     {
-      result->fake_addr_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
+      result->fake_addr_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
       if (unlikely (result->fake_addr_cu == NULL))
 	{
 	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
@@ -291,6 +301,11 @@ valid_p (Dwarf *result)
 	  result->fake_addr_cu->endp
 	    = (result->sectiondata[IDX_debug_addr]->d_buf
 	       + result->sectiondata[IDX_debug_addr]->d_size);
+	  result->fake_addr_cu->locs = NULL;
+	  result->fake_addr_cu->address_size = 0;
+	  result->fake_addr_cu->version = 0;
+	  result->fake_addr_cu->unit_type = 0;
+	  result->fake_addr_cu->split = NULL;
 	}
     }
 
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index a2e94436..265239c4 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -52,8 +52,6 @@ cu_free (void *arg)
 {
   struct Dwarf_CU *p = (struct Dwarf_CU *) arg;
 
-  Dwarf_Abbrev_Hash_free (&p->abbrev_hash);
-
   tdestroy (p->locs, noop_free);
 
   /* Free split dwarf one way (from skeleton to split).  */
@@ -65,6 +63,13 @@ cu_free (void *arg)
 	p->split->dbg->fake_addr_cu = NULL;
       INTUSE(dwarf_end) (p->split->dbg);
     }
+
+  /* Only free the Abbrev_Hash if its not a fake CU.  */
+  if(p != p->dbg->fake_loc_cu && p != p->dbg->fake_loclists_cu
+     && p != p->dbg->fake_addr_cu)
+    {
+      Dwarf_Abbrev_Hash_free (&p->abbrev_hash);
+    }
 }
 
 
-- 
2.24.0.rc2



More information about the Elfutils-devel mailing list