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