vectors. */
static struct obstack ob;
-/* String obstack for .debug_line filenames. */
-static struct obstack strob;
-
typedef struct
{
Elf *elf;
{
/* Abbreviation number. */
unsigned int entry;
- /* Hash value, in cu->cu_abbrev hash tables it is
+ /* Hash value, in first abbrev hash tables it is
the same as entry, in cu->cu_new_abbrev hash tables
iterative hash of all the relevant values. */
hashval_t hash;
/* Number of attributes. */
unsigned int nattr;
/* How many DIEs refer to this abbreviation (unused
- in cu->cu_abbrev hash tables). */
+ in first abbrev hash tables). */
unsigned int nusers;
/* True if DIEs with this abbreviation have children. */
bool children;
unit. */
struct dw_cu
{
- /* Abbreviation hash table, or NULL for newly created
- partial CUs. */
- htab_t cu_abbrev;
/* Cached entries from .debug_line file table. */
struct dw_file *cu_files;
unsigned int cu_nfiles;
+ /* Kind of CU, normal (present in .debug_info), newly created
+ partial unit or .debug_types unit. */
+ enum { CU_NORMAL, CU_PU, CU_TYPES } cu_kind;
/* CUs linked from first_cu through this chain. */
struct dw_cu *cu_next;
- /* Offset in original .debug_info if cu_abbrev is non-NULL,
- otherwise a unique index of the newly created partial CU. */
+ /* Offset in original .debug_info if CU_NORMAL or .debug_types
+ if CU_TYPES, otherwise a unique index of the newly created
+ partial CU. */
unsigned int cu_offset;
/* DWARF version of the CU. */
unsigned int cu_version;
#define die_safe_nextdup(die) \
((die)->die_toplevel ? (die)->die_nextdup : (dw_die_ref) NULL)
-/* Hash function in cu->cu_abbrev as well as cu->cu_new_abbrev htab. */
+/* Hash function in first abbrev hash table as well as cu->cu_new_abbrev
+ htab. */
static hashval_t
abbrev_hash (const void *p)
{
return t->hash;
}
-/* Equality function in cu->cu_abbrev htab. */
+/* Equality function in first abbrev htab. */
static int
abbrev_eq (const void *p, const void *q)
{
return t1->entry == t2->entry;
}
-/* Delete function in cu->cu_abbrev htab. */
-static void
-abbrev_del (void *p)
-{
- free (p);
-}
-
/* Equality function in cu->cu_new_abbrev htab. */
static int
abbrev_eq2 (const void *p, const void *q)
static unsigned int max_nattr;
/* Parse a .debug_abbrev entry at PTR. If !DEBUG_TYPES, return
- cu->cu_abbrev style hash table, otherwise return cu->cu_new_abbrev
+ first abbrev htab style hash table, otherwise return cu->cu_new_abbrev
style hash table (this is used for reading .debug_types abbreviations
which we are not rewriting). */
static htab_t
htab_t h;
unsigned int attr, form;
struct abbrev_tag *t;
- unsigned int size;
void **slot;
if (debug_types)
h = htab_try_create (20, abbrev_hash, abbrev_eq2, NULL);
else
- h = htab_try_create (50, abbrev_hash, abbrev_eq, abbrev_del);
+ h = htab_try_create (50, abbrev_hash, abbrev_eq, NULL);
if (h == NULL)
{
no_memory:
error (0, ENOMEM, "%s: Could not read .debug_abbrev", dso->filename);
if (h)
- {
- h->del_f = abbrev_del;
- htab_delete (h);
- }
+ htab_delete (h);
return NULL;
}
while ((attr = read_uleb128 (ptr)) != 0)
{
- size = 10;
- t = xmalloc (sizeof (*t) + size * sizeof (struct abbrev_attr));
- t->entry = attr;
- t->hash = attr;
- t->nattr = 0;
- t->nusers = 0;
- t->tag = read_uleb128 (ptr);
- t->children = *ptr++ == DW_CHILDREN_yes;
- t->op_type_referenced = false;
- while ((attr = read_uleb128 (ptr)) != 0)
+ unsigned int nattr = 0;
+ unsigned char *p = ptr;
+
+ read_uleb128 (p);
+ p++;
+ while (read_uleb128 (p) != 0)
{
- if (t->nattr == size)
- {
- size += 10;
- t = realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr));
- if (t == NULL)
- goto no_memory;
- }
- form = read_uleb128 (ptr);
+ nattr++;
+ form = read_uleb128 (p);
if (form == 2
|| (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
{
error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
- free (t);
- h->del_f = abbrev_del;
htab_delete (h);
return NULL;
}
-
- t->attr[t->nattr].attr = attr;
- t->attr[t->nattr++].form = form;
}
- if (read_uleb128 (ptr) != 0)
+ if (read_uleb128 (p) != 0)
{
error (0, 0, "%s: DWARF abbreviation does not end with 2 zeros",
dso->filename);
- free (t);
- h->del_f = abbrev_del;
htab_delete (h);
return NULL;
}
+
+ t = (struct abbrev_tag *)
+ obstack_alloc (&ob,
+ sizeof (*t) + nattr * sizeof (struct abbrev_attr));
+ t->entry = attr;
+ t->hash = attr;
+ t->nattr = 0;
+ t->nusers = 0;
+ t->tag = read_uleb128 (ptr);
+ t->children = *ptr++ == DW_CHILDREN_yes;
+ t->op_type_referenced = false;
+ while ((attr = read_uleb128 (ptr)) != 0)
+ {
+ form = read_uleb128 (ptr);
+ t->attr[t->nattr].attr = attr;
+ t->attr[t->nattr++].form = form;
+ }
+ read_uleb128 (ptr);
if (t->nattr > max_nattr)
max_nattr = t->nattr;
if (debug_types)
compute_abbrev_hash (t);
slot = htab_find_slot_with_hash (h, t, t->hash, INSERT);
if (slot == NULL)
- {
- free (t);
- goto no_memory;
- }
+ goto no_memory;
if (*slot != NULL)
{
error (0, 0, "%s: Duplicate DWARF abbreviation %d", dso->filename,
t->entry);
- free (t);
- h->del_f = abbrev_del;
htab_delete (h);
return NULL;
}
}
cu->cu_nfiles = file_cnt;
- cu->cu_files = calloc (file_cnt, sizeof (struct dw_file));
- if (cu->cu_files == NULL)
- {
- error (0, ENOMEM, "Not enough memory");
- return 1;
- }
+ cu->cu_files = (struct dw_file *)
+ obstack_alloc (&ob, file_cnt * sizeof (struct dw_file));
+ memset (cu->cu_files, 0, file_cnt * sizeof (struct dw_file));
ptr = file;
file_cnt = 0;
size_t dir_len = strlen (cu->cu_files[file_cnt].dir);
if (dir_len)
{
- obstack_grow (&strob, cu->cu_files[file_cnt].dir,
+ obstack_grow (&ob, cu->cu_files[file_cnt].dir,
dir_len);
if (cu->cu_files[file_cnt].dir[dir_len - 1] != '/')
- obstack_1grow (&strob, '/');
- obstack_grow (&strob, cu->cu_files[file_cnt].file,
+ obstack_1grow (&ob, '/');
+ obstack_grow (&ob, cu->cu_files[file_cnt].file,
file_len);
cu->cu_files[file_cnt].file
- = (char *) obstack_finish (&strob);
+ = (char *) obstack_finish (&ob);
cu->cu_files[file_cnt].dir = NULL;
}
}
/* Walk toplevel DIEs in tree rooted by PARENT, and see if they
match previously processed DIEs. */
-static void
+static int
find_dups (dw_die_ref parent)
{
void **slot;
child->u.p1.die_ref_hash,
INSERT);
if (slot == NULL)
- error (1, ENOMEM, "Not enough memory to find duplicates");
+ {
+ error (0, ENOMEM, "Not enough memory to find duplicates");
+ return 1;
+ }
if (*slot == NULL)
*slot = child;
}
else if (child->die_named_namespace)
- find_dups (child);
+ if (find_dups (child))
+ return 1;
}
+ return 0;
}
#ifdef DEBUG_DUMP_DIES
read_debug_info (DSO *dso)
{
unsigned char *ptr, *endcu, *endsec;
- uint32_t value;
- htab_t abbrev;
+ unsigned int value;
+ htab_t abbrev = NULL;
+ unsigned int last_abbrev_offset = 0;
struct abbrev_tag tag, *t;
dup_htab = htab_try_create (100000, die_hash, die_eq, NULL);
return 1;
}
- obstack_init (&ob);
- obstack_init (&strob);
ptr = debug_sections[DEBUG_INFO].data;
endsec = ptr + debug_sections[DEBUG_INFO].size;
while (ptr < endsec)
if (ptr + 11 > endsec)
{
error (0, 0, "%s: .debug_info CU header too small", dso->filename);
- return 1;
+ goto fail;
}
endcu = ptr + 4;
if (endcu == ptr + 0xffffffff)
{
error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
- return 1;
+ goto fail;
}
if (endcu > endsec)
{
error (0, 0, "%s: .debug_info too small", dso->filename);
- return 1;
+ goto fail;
}
cu_version = read_16 (ptr);
{
error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
cu_version);
- return 1;
+ goto fail;
}
value = read_32 (ptr);
else
error (0, 0, "%s: DWARF CU abbrev offset too large",
dso->filename);
- return 1;
+ goto fail;
}
if (ptr_size == 0)
{
error (0, 0, "%s: Invalid DWARF pointer size %d",
dso->filename, ptr_size);
- return 1;
+ goto fail;
}
}
else if (read_8 (ptr) != ptr_size)
{
error (0, 0, "%s: DWARF pointer size differs between CUs",
dso->filename);
- return 1;
+ goto fail;
}
- abbrev = read_abbrev (dso, debug_sections[DEBUG_ABBREV].data + value,
- false);
- if (abbrev == NULL)
- return 1;
+ if (abbrev == NULL || value != last_abbrev_offset)
+ {
+ if (abbrev)
+ htab_delete (abbrev);
+ abbrev = read_abbrev (dso, debug_sections[DEBUG_ABBREV].data + value,
+ false);
+ if (abbrev == NULL)
+ goto fail;
+ }
+ last_abbrev_offset = value;
cu = (struct dw_cu *) obstack_alloc (&ob, sizeof (struct dw_cu));
memset (cu, '\0', sizeof (*cu));
- cu->cu_abbrev = abbrev;
+ cu->cu_kind = CU_NORMAL;
cu->cu_offset = cu_offset;
cu->cu_version = cu_version;
diep = &cu->cu_die;
if (diep == NULL)
{
error (0, 0, "%s: Wrong .debug_info DIE tree", dso->filename);
- return 1;
+ goto fail;
}
t = htab_find_with_hash (abbrev, &tag, tag.entry);
if (t == NULL)
{
error (0, 0, "%s: Could not find DWARF abbreviation %d",
dso->filename, tag.entry);
- return 1;
+ goto fail;
}
if (parent == NULL
|| parent->die_parent == NULL
{
error (0, 0, "%s: Attributes extend beyond end of CU",
dso->filename);
- return 1;
+ goto fail;
}
}
switch (form)
default:
error (0, 0, "%s: Unknown DWARF DW_FORM_%d",
dso->filename, form);
- return 1;
+ goto fail;
}
if (ptr >= endcu)
{
error (0, 0, "%s: Attributes extend beyond end of CU",
dso->filename);
- return 1;
+ goto fail;
}
if (form == DW_FORM_block1)
{
error (0, 0, "%s: Attributes extend beyond end of CU",
dso->filename);
- return 1;
+ goto fail;
}
if (t->attr[i].attr > DW_AT_linkage_name
{
error (0, 0, "%s: Unknown DWARF DW_AT_%d with block DW_FORM",
dso->filename, t->attr[i].attr);
- return 1;
+ goto fail;
}
ptr += len;
die->die_size = (ptr - debug_sections[DEBUG_INFO].data)
- die_offset;
if (off_htab_add_die (die))
- return 1;
+ goto fail;
}
if (cu->cu_die == NULL
{
error (0, 0, "%s: .debug_info section chunk doesn't contain a single"
" compile_unit or partial_unit", dso->filename);
- return 1;
+ goto fail;
}
cu->cu_comp_dir = get_AT_string (cu->cu_die, DW_AT_comp_dir);
debug_line_off = get_AT_int (cu->cu_die, DW_AT_stmt_list, &present);
if (present && read_debug_line (dso, cu, debug_line_off))
- return 1;
+ goto fail;
if (checksum_die (dso, NULL, cu->cu_die))
- return 1;
+ goto fail;
checksum_ref_die (NULL, cu->cu_die, NULL, NULL);
#ifdef DEBUG_DUMP_DIES
dump_dies (0, cu->cu_die);
#endif
- find_dups (cu->cu_die);
+ if (find_dups (cu->cu_die))
+ goto fail;
}
+ if (abbrev)
+ htab_delete (abbrev);
htab_delete (dup_htab);
dup_htab = NULL;
return 0;
+fail:
+ if (abbrev)
+ htab_delete (abbrev);
+ htab_delete (dup_htab);
+ dup_htab = NULL;
+ return 1;
}
/* Compare function called from qsort, which should ensure that
= (struct dw_cu *)
obstack_alloc (&ob, sizeof (struct dw_cu));
memset (partial_cu, '\0', sizeof (*partial_cu));
+ partial_cu->cu_kind = CU_PU;
partial_cu->cu_offset = cu_off++;
partial_cu->cu_version = cu->cu_version;
if (first_partial_cu == NULL)
unsigned int new_edge_cost;
/* If no PUs were created, there is nothing to do here. */
- if (first_cu == NULL || first_cu->cu_abbrev != NULL)
+ if (first_cu == NULL || first_cu->cu_kind != CU_PU)
return 0;
obstack_init (&iob);
min_cu_version = first_cu->cu_version;
/* First construct a bipartite graph between CUs and PUs. */
for (pu = first_cu, npus = 0;
- pu && pu->cu_abbrev == NULL; pu = pu->cu_next, npus++)
+ pu && pu->cu_kind == CU_PU; pu = pu->cu_next, npus++)
{
dw_die_ref die, rdie;
struct dw_cu *prev_cu;
else if (new_pu_version == 2)
edge_cost = 1 + ptr_size;
new_edge_cost = new_pu_version == 2 ? 1 + ptr_size : 5;
- for (pu = first_cu; pu && pu->cu_abbrev == NULL; pu = pu->cu_next)
+ for (pu = first_cu; pu && pu->cu_kind == CU_PU; pu = pu->cu_next)
{
ipu = pu->u1.cu_icu;
for (i = 0; i < ipu->incoming_count; i++)
ipus = (struct import_cu **)
obstack_alloc (&iob, (npus + ncus) * sizeof (*ipus));
for (pu = first_cu, npus = 0;
- pu && pu->cu_abbrev == NULL; pu = pu->cu_next, npus++)
+ pu && pu->cu_kind == CU_PU; pu = pu->cu_next, npus++)
{
ipu = pu->u1.cu_icu;
qsort (ipu->incoming, ipu->incoming_count, sizeof (*ipu->incoming),
= (struct dw_cu *)
obstack_alloc (&ob, sizeof (struct dw_cu));
memset (partial_cu, '\0', sizeof (*partial_cu));
+ partial_cu->cu_kind = CU_PU;
partial_cu->cu_offset = cu_off++;
partial_cu->cu_version = new_pu_version;
partial_cu->u1.cu_icu = ipu;
cu = (struct dw_cu *) obstack_alloc (&ob, sizeof (struct dw_cu));
memset (cu, '\0', sizeof (*cu));
+ cu->cu_kind = CU_TYPES;
cu->cu_new_abbrev = abbrev;
cu->cu_offset = cu_offset;
cu->cu_version = cu_version;
else
{
struct abbrev_tag *newt
- = xmalloc (sizeof (*newt) + t->nattr * sizeof (struct abbrev_attr));
- memcpy (newt, t, sizeof (*newt)
- + t->nattr * sizeof (struct abbrev_attr));
+ = (struct abbrev_tag *)
+ obstack_copy (&ob, t,
+ sizeof (*newt)
+ + t->nattr * sizeof (struct abbrev_attr));
*slot = newt;
die->u.p2.die_new_abbrev = newt;
}
/* Helper to record all abbrevs from the hash table into ob obstack
vector. Called through htab_traverse. */
static int
-list_abbrevs (void **slot, void *info __attribute__((unused)))
+list_abbrevs (void **slot, void *data)
{
- obstack_ptr_grow (&ob, *slot);
+ struct obstack *obp = (struct obstack *) data;
+ obstack_ptr_grow (obp, *slot);
return 1;
}
if (nabbrevs1 > nabbrevs2)
return 1;
/* The rest is just to get stable sort. */
- if (cu1->cu_abbrev != NULL && cu2->cu_abbrev == NULL)
+ if (cu1->cu_kind != CU_PU && cu2->cu_kind == CU_PU)
return -1;
- if (cu1->cu_abbrev == NULL && cu2->cu_abbrev != NULL)
+ if (cu1->cu_kind == CU_PU && cu2->cu_kind != CU_PU)
return 1;
if (cu1->cu_offset < cu2->cu_offset)
return -1;
{
unsigned long total_size = 0, abbrev_size = 0;
struct dw_cu *cu, **cuarr;
- struct abbrev_tag *t
- = xmalloc (sizeof (*t) + (max_nattr + 4) * sizeof (struct abbrev_attr));
+ struct abbrev_tag *t;
unsigned int ncus, nlargeabbrevs = 0, i, laststart;
struct obstack vec;
obstack_init (&vec);
+ t = (struct abbrev_tag *)
+ obstack_alloc (&vec, sizeof (*t)
+ + (max_nattr + 4) * sizeof (struct abbrev_attr));
for (cu = first_cu, ncus = 0; cu; cu = cu->cu_next, ncus++)
{
unsigned int intracu, ndies = 0, tagsize = 0, nchildren = 0;
enum dwarf_form intracuform = DW_FORM_ref4;
dw_die_ref child, *lastotr, child_next, *last;
- if (cu->cu_die == NULL)
+ if (cu->cu_kind == CU_TYPES)
{
if (cu->u1.cu_new_abbrev_owner != NULL)
{
if (build_abbrevs (cu, t, &ndies, &vec))
{
obstack_free (&vec, NULL);
- free (t);
return 1;
}
nabbrevs = htab_elements (cu->cu_new_abbrev);
- htab_traverse (cu->cu_new_abbrev, list_abbrevs, NULL);
+ htab_traverse (cu->cu_new_abbrev, list_abbrevs, &ob);
assert (obstack_object_size (&ob) == nabbrevs * sizeof (void *));
arr = (struct abbrev_tag **) obstack_finish (&ob);
intracu = obstack_object_size (&vec) / sizeof (void *) / 2;
}
intracuvec = intracuarr;
- off = finalize_new_die_offsets (cu->cu_die, 11, intracusize, &intracuvec);
+ off = finalize_new_die_offsets (cu->cu_die, 11, intracusize,
+ &intracuvec);
if (off == -1U)
{
error (0, 0, "%s: DW_OP_call2 or typed DWARF stack referenced DIE"
" layed out at too big offset", dso->filename);
obstack_free (&vec, NULL);
- free (t);
return 1;
}
assert (*intracuvec == NULL && off == cusize);
{
obstack_free (&ob, (void *) arr);
obstack_free (&vec, NULL);
- free (t);
error (0, ENOMEM, "Could not compute .debug_abbrev");
return 1;
}
cu->cu_new_offset = total_size;
total_size += cusize;
}
- obstack_free (&vec, NULL);
- free (t);
- cuarr = (struct dw_cu **) xmalloc (ncus * sizeof (struct dw_cu *));
+ obstack_free (&vec, (void *) t);
+ cuarr = (struct dw_cu **) obstack_alloc (&vec,
+ ncus * sizeof (struct dw_cu *));
for (cu = first_cu, i = 0; cu; cu = cu->cu_next)
if (cu->u1.cu_new_abbrev_owner == NULL)
cuarr[i++] = cu;
if (cuarr[i]->u1.cu_new_abbrev_owner != NULL)
continue;
nabbrevs = htab_elements (cuarr[i]->cu_new_abbrev);
- htab_traverse (cuarr[i]->cu_new_abbrev, list_abbrevs, NULL);
- assert (obstack_object_size (&ob) == nabbrevs * sizeof (void *));
- arr = (struct abbrev_tag **) obstack_finish (&ob);
+ htab_traverse (cuarr[i]->cu_new_abbrev, list_abbrevs, &vec);
+ assert (obstack_object_size (&vec) == nabbrevs * sizeof (void *));
+ arr = (struct abbrev_tag **) obstack_finish (&vec);
if (nabbrevs >= 128)
{
nattempts = 0;
adjusting .debug_abbrev offsets into it, so the
assigned entry values for .debug_types section
can't change. */
- if (cuarr[i]->cu_die == NULL)
+ if (cuarr[i]->cu_kind == CU_TYPES)
{
if (t == NULL || t->entry != arr[k]->entry)
break;
INSERT);
if (slot == NULL)
{
- obstack_free (&ob, (void *) arr);
- free (cuarr);
+ obstack_free (&vec, NULL);
error (0, ENOMEM, "Could not compute .debug_abbrev");
return 1;
}
arr[k]->entry = ((struct abbrev_tag *) *slot)->entry;
else
{
- struct abbrev_tag *newt
- = xmalloc (sizeof (*newt)
- + arr[k]->nattr
- * sizeof (struct abbrev_attr));
+ struct abbrev_tag *newt;
arr[k]->entry = ++entry;
- memcpy (newt, arr[k],
- sizeof (*newt)
- + arr[k]->nattr * sizeof (struct abbrev_attr));
+ newt = (struct abbrev_tag *)
+ obstack_copy (&ob, arr[k],
+ sizeof (*newt)
+ + arr[k]->nattr
+ * sizeof (struct abbrev_attr));
*slot = newt;
}
}
cuarr[i]->u1.cu_new_abbrev_owner = cuarr[j];
break;
}
- obstack_free (&ob, (void *) arr);
+ obstack_free (&vec, (void *) arr);
continue;
}
/* Don't search all CUs, that might be too expensive. So just search
/* We aren't rewriting .debug_types section, merely adjusting
.debug_abbrev offsets into it, so the assigned entry
values for .debug_types section can't change. */
- if (cuarr[i]->cu_die == NULL && t->entry != arr[k]->entry)
+ if (cuarr[i]->cu_kind == CU_TYPES && t->entry != arr[k]->entry)
break;
}
if (k == nabbrevs)
/* We aren't rewriting .debug_types section, merely adjusting
.debug_abbrev offsets into it, so the assigned entry
values for .debug_types section can't change. */
- if (cuarr[i]->cu_die == NULL
+ if (cuarr[i]->cu_kind == CU_TYPES
&& (t == NULL || t->entry != arr[k]->entry))
{
curdups = 0;
INSERT);
if (slot == NULL)
{
- obstack_free (&ob, (void *) arr);
- free (cuarr);
+ obstack_free (&vec, NULL);
error (0, ENOMEM, "Could not compute .debug_abbrev");
return 1;
}
arr[k]->entry = ((struct abbrev_tag *) *slot)->entry;
else
{
- struct abbrev_tag *newt
- = xmalloc (sizeof (*newt)
- + arr[k]->nattr
- * sizeof (struct abbrev_attr));
+ struct abbrev_tag *newt;
arr[k]->entry = ++entry;
- memcpy (newt, arr[k],
- sizeof (*newt)
- + arr[k]->nattr * sizeof (struct abbrev_attr));
+ newt = (struct abbrev_tag *)
+ obstack_copy (&ob, arr[k],
+ sizeof (*newt)
+ + arr[k]->nattr
+ * sizeof (struct abbrev_attr));
*slot = newt;
}
}
cuarr[i]->u1.cu_new_abbrev_owner = cuarr[j];
}
}
- obstack_free (&ob, (void *) arr);
+ obstack_free (&vec, (void *) arr);
}
- free (cuarr);
+ obstack_free (&vec, NULL);
for (cu = first_cu; cu; cu = cu->cu_next)
{
struct abbrev_tag **arr;
if (cu->u1.cu_new_abbrev_owner != NULL)
{
cu->u2.cu_new_abbrev_offset = -1U;
+ htab_delete (cu->cu_new_abbrev);
+ cu->cu_new_abbrev = NULL;
continue;
}
cu->u2.cu_new_abbrev_offset = abbrev_size;
nabbrevs = htab_elements (cu->cu_new_abbrev);
- htab_traverse (cu->cu_new_abbrev, list_abbrevs, NULL);
+ htab_traverse (cu->cu_new_abbrev, list_abbrevs, &ob);
assert (obstack_object_size (&ob) == nabbrevs * sizeof (void *));
arr = (struct abbrev_tag **) obstack_finish (&ob);
for (i = 0; i < nabbrevs; i++)
if (cu->u1.cu_new_abbrev_owner != NULL)
continue;
nabbrevs = htab_elements (cu->cu_new_abbrev);
- htab_traverse (cu->cu_new_abbrev, list_abbrevs, NULL);
+ htab_traverse (cu->cu_new_abbrev, list_abbrevs, &ob);
assert (obstack_object_size (&ob) == nabbrevs * sizeof (void *));
arr = (struct abbrev_tag **) obstack_finish (&ob);
qsort (arr, nabbrevs, sizeof (*arr), abbrev_entry_cmp);
}
*ptr++ = 0;
obstack_free (&ob, (void *) arr);
+ htab_delete (cu->cu_new_abbrev);
+ cu->cu_new_abbrev = NULL;
}
assert (abbrev + abbrev_size == ptr);
return abbrev;
{
unsigned long next_off = info_size;
/* Ignore .debug_types CUs. */
- if (cu->cu_die == NULL)
+ if (cu->cu_kind == CU_TYPES)
break;
- if (cu->cu_next && cu->cu_next->cu_die)
+ if (cu->cu_next && cu->cu_next->cu_kind != CU_TYPES)
next_off = cu->cu_next->cu_new_offset;
/* Write CU header. */
write_32 (ptr, next_off - cu->cu_new_offset - 4);
for (cu = first_cu; cu; cu = cu->cu_next)
{
/* Ignore .debug_info CUs. */
- if (cu->cu_die != NULL)
+ if (cu->cu_kind != CU_TYPES)
continue;
ptr = types + cu->cu_offset + 6;
write_32 (ptr, cu->u2.cu_new_abbrev_offset);
goto error_out;
}
- /* Allocate DSO structure. Leave place for additional 20 new section
- headers. */
+ /* Allocate DSO structure. */
dso = (DSO *)
- malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr)
- + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *));
+ malloc (sizeof(DSO) + ehdr.e_shnum * sizeof(GElf_Shdr)
+ + ehdr.e_shnum * sizeof(Elf_Scn *)
+ + strlen (name) + 1);
if (!dso)
{
error (0, ENOMEM, "Could not open DSO");
memset (dso, 0, sizeof(DSO));
dso->elf = elf;
dso->ehdr = ehdr;
- dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum + 20];
+ dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum];
for (i = 0; i < ehdr.e_shnum; ++i)
{
gelf_getshdr (dso->scn[i], dso->shdr + i);
}
- dso->filename = (const char *) strdup (name);
+ dso->filename = (const char *) &dso->scn[ehdr.e_shnum];
+ strcpy ((char *) &dso->scn[ehdr.e_shnum], name);
return dso;
error_out:
- if (dso)
- {
- free ((char *) dso->filename);
- free (dso);
- }
+ free (dso);
if (elf)
elf_end (elf);
if (fd != -1)
unsigned char *new_debug_abbrev, *new_debug_info;
unsigned char *new_debug_loc, *new_debug_types;
struct stat st;
+ struct dw_cu *cu;
if (argc < 3)
error (1, 0, "Usage: dwz input_object output_object");
if (dso == NULL)
exit (1);
+ obstack_init (&ob);
+
if (read_dwarf (dso))
exit (1);
new_debug_loc = write_loc ();
new_debug_types = write_types ();
+ for (cu = first_cu; cu; cu = cu->cu_next)
+ {
+ if (cu->cu_new_abbrev)
+ htab_delete (cu->cu_new_abbrev);
+ cu->cu_new_abbrev = NULL;
+ }
+ if (off_htab != NULL)
+ htab_delete (off_htab);
+ off_htab = NULL;
+ if (loc_htab != NULL)
+ {
+ obstack_free (&loc_ob, NULL);
+ htab_delete (loc_htab);
+ loc_htab = NULL;
+ }
+ obstack_free (&ob, NULL);
+
write_dso (dso, outfile, new_debug_abbrev, new_debug_abbrev_size,
new_debug_info, new_debug_info_size, new_debug_loc,
new_debug_types, &st);
+ free (new_debug_info);
+ free (new_debug_abbrev);
+ free (new_debug_loc);
+ free (new_debug_types);
+
if (elf_end (dso->elf) < 0)
error (1, 0, "elf_end failed: %s\n", elf_errmsg (elf_errno()));
close (fd);
+ free (dso);
+
return 0;
}