This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[intercu] Use cleanups properly
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Tue, 24 Feb 2004 19:03:35 -0500
- Subject: [intercu] Use cleanups properly
This removes a couple of FIXMEs by adding appropriate cleanup functions, and
either doing or discarding them on success. The only memory leak plugged in
the non-error case was releasing the dwarf2_tmp_obstack, which got lost in
the shuffle.
Committed to the intercu branch.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
2004-02-24 Daniel Jacobowitz <drow@mvista.com>
* dwarf2read.c (free_one_comp_unit): Update signature so it can be
used as a cleanup. Clear the per_cu pointer. Add some comments.
(free_one_cached_comp_unit): Update signature so it can be used
as a cleanup. Remove unused argument.
(dwarf2_build_psymtabs_hard): Update call to
free_one_cached_comp_unit. Don't free the obstack here.
(process_queue): Keep dwarf2_queue up to date as we remove items
from the queue.
(dwarf2_release_queue): New function.
(psymtab_to_symtab_1): Use cleanups.
(load_full_comp_unit): Likewise.
(free_comp_units_worker): Remove clearing of the cu pointer.
(clear_per_cu_pointer): Also free the partial_die_obstack. Update
comments.
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.135.2.31
diff -u -p -r1.135.2.31 dwarf2read.c
--- dwarf2read.c 24 Feb 2004 03:27:21 -0000 1.135.2.31
+++ dwarf2read.c 25 Feb 2004 00:01:53 -0000
@@ -987,7 +987,7 @@ static struct dwarf2_per_cu_data *dwarf2
static struct partial_symtab *dwarf2_find_comp_unit_psymtab
(unsigned int offset, struct objfile *objfile);
-static void free_one_comp_unit (struct dwarf2_cu *);
+static void free_one_comp_unit (void *);
static void clear_per_cu_pointer (void *);
@@ -995,7 +995,7 @@ static void free_cached_comp_units (void
static void age_cached_comp_units (void *);
-static void free_one_cached_comp_unit (struct dwarf2_cu *, struct dwarf2_cu *);
+static void free_one_cached_comp_unit (void *);
static void set_die_type (struct die_info *, struct type *,
struct dwarf2_cu *);
@@ -1446,7 +1446,7 @@ dwarf2_build_psymtabs_hard (struct objfi
a nice speed boost but require a lot of editing in this
function. */
if (per_cu->cu != NULL)
- free_one_cached_comp_unit (&cu, per_cu->cu);
+ free_one_cached_comp_unit (per_cu->cu);
cu.per_cu = per_cu;
@@ -1486,9 +1486,6 @@ dwarf2_build_psymtabs_hard (struct objfi
scan_partial_symbols (first_die, &lowpc, &highpc, &cu, 0);
- cu.partial_dies = NULL;
- obstack_free (&cu.partial_die_obstack, NULL);
-
/* If we didn't find a lowpc, set it to highpc to avoid
complaints from `maint check'. */
if (lowpc == ((CORE_ADDR) -1))
@@ -2346,6 +2343,33 @@ process_queue (struct objfile *objfile)
item->per_cu->queued = 0;
}
last = item;
+ dwarf2_queue = item = last->next;
+ xfree (last);
+ }
+}
+
+/* Free all allocated queue entries. This function only releases anything if
+ an error was thrown; if the queue was processed then it would have been
+ freed as we went along. */
+
+static void
+dwarf2_release_queue (void *dummy)
+{
+ struct dwarf2_queue_item *item, *last;
+
+ item = dwarf2_queue;
+ while (item)
+ {
+ /* Anything still marked queued is likely to be in an
+ inconsistent state, so discard it. */
+ if (item->per_cu->queued)
+ {
+ if (item->per_cu->cu != NULL)
+ free_one_cached_comp_unit (item->per_cu->cu);
+ item->per_cu->queued = 0;
+ }
+
+ last = item;
item = item->next;
xfree (last);
}
@@ -2361,13 +2385,12 @@ psymtab_to_symtab_1 (struct partial_symt
obstack_init (&dwarf2_tmp_obstack);
back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
- /* FIXME: More cleanup issues. */
if (dwarf2_per_objfile->cu_tree == NULL)
{
struct dwarf2_cu *cu;
cu = load_full_comp_unit (pst, NULL);
+ make_cleanup (free_one_comp_unit, cu);
process_full_comp_unit (pst, cu);
- free_one_comp_unit (cu);
}
else
{
@@ -2381,6 +2404,9 @@ psymtab_to_symtab_1 (struct partial_symt
per_cu = (struct dwarf2_per_cu_data *) node->value;
per_cu->psymtab = pst;
+
+ make_cleanup (dwarf2_release_queue, NULL);
+
queue_comp_unit (per_cu);
process_queue (pst->objfile);
@@ -2390,9 +2416,10 @@ psymtab_to_symtab_1 (struct partial_symt
caching. */
age_cached_comp_units (NULL);
}
+
+ do_cleanups (back_to);
}
-/* FIXME: Cleanup issues. */
static struct dwarf2_cu *
load_full_comp_unit (struct partial_symtab *pst,
struct dwarf2_per_cu_data *per_cu)
@@ -2401,7 +2428,7 @@ load_full_comp_unit (struct partial_symt
struct dwarf2_cu *cu;
unsigned long offset;
char *info_ptr;
- struct cleanup *back_to;
+ struct cleanup *back_to, *free_cu_cleanup;
struct attribute *attr;
/* Set local variables from the partial symbol table info. */
@@ -2412,6 +2439,9 @@ load_full_comp_unit (struct partial_symt
cu = xmalloc (sizeof (struct dwarf2_cu));
memset (cu, 0, sizeof (struct dwarf2_cu));
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+
cu->objfile = pst->objfile;
/* read in the comp_unit header */
@@ -2444,6 +2474,10 @@ load_full_comp_unit (struct partial_symt
do_cleanups (back_to);
+ /* We've successfully allocated this compilation unit. Let our caller
+ clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
+
return cu;
}
@@ -9095,14 +9129,23 @@ dwarf2_find_comp_unit_psymtab (unsigned
offset);
}
-/* Release one cached compilation unit, CU. */
+/* Release one cached compilation unit, CU. We unlink it from the tree
+ of compilation units, but we don't remove it from the read_in_chain
+ (so it should not be on that chain to begin with). */
static void
-free_one_comp_unit (struct dwarf2_cu *cu)
+free_one_comp_unit (void *data)
{
+ struct dwarf2_cu *cu = data;
+
+ if (cu->per_cu != NULL)
+ cu->per_cu->cu = NULL;
+ cu->per_cu = NULL;
+
obstack_free (&cu->partial_die_obstack, NULL);
if (cu->dies)
free_die_list (cu->dies);
+
xfree (cu);
}
@@ -9143,7 +9186,6 @@ free_comp_units_worker (struct dwarf2_cu
|| (!aging && target_cu == NULL))
{
free_one_comp_unit (per_cu->cu);
- per_cu->cu = NULL;
*last_chain = next_cu;
}
else
@@ -9156,6 +9198,13 @@ free_comp_units_worker (struct dwarf2_cu
}
}
+/* This cleanup function is passed the address of a dwarf2_cu on the stack
+ when we're finished with it. We can't free the pointer itself, but be
+ sure to unlink it from the cache. Also release any associated storage
+ and perform cache maintenance.
+
+ Only used during partial symbol parsing. */
+
static void
clear_per_cu_pointer (void *data)
{
@@ -9163,12 +9212,15 @@ clear_per_cu_pointer (void *data)
if (cu->per_cu != NULL)
{
- age_cached_comp_units (NULL);
+ obstack_free (&cu->partial_die_obstack, NULL);
+ cu->partial_dies = NULL;
/* This compilation unit is on the stack in our caller, so we
should not xfree it. Just unlink it. */
cu->per_cu->cu = NULL;
cu->per_cu = NULL;
+
+ age_cached_comp_units (NULL);
}
}
@@ -9185,7 +9237,7 @@ age_cached_comp_units (void *data)
}
static void
-free_one_cached_comp_unit (struct dwarf2_cu *cu, struct dwarf2_cu *target_cu)
+free_one_cached_comp_unit (void *target_cu)
{
free_comp_units_worker (target_cu, 0);
}