summaryrefslogtreecommitdiff
path: root/usr/src/tools/ctf/dwarf/common/pro_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/pro_alloc.c')
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_alloc.c153
1 files changed, 135 insertions, 18 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/pro_alloc.c b/usr/src/tools/ctf/dwarf/common/pro_alloc.c
index 2f85bcd84b..1ca7806239 100644
--- a/usr/src/tools/ctf/dwarf/common/pro_alloc.c
+++ b/usr/src/tools/ctf/dwarf/common/pro_alloc.c
@@ -1,6 +1,7 @@
/*
Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of version 2.1 of the GNU Lesser General Public License
@@ -19,10 +20,10 @@
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
USA.
- Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky,
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
Mountain View, CA 94043, or:
http://www.sgi.com
@@ -36,36 +37,152 @@
#include "config.h"
-#include "dwarf_incl.h"
+#include "pro_incl.h"
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <malloc.h>
/*
- The allocator wants to know which region
- this is to be in so it can allocate the new space
- with respect to the right region.
+ When each block is allocated, there is a two-word structure
+ allocated at the beginning so the block can go on a list.
+ The address returned is the address *after* the two pointers
+ at the start. But this allows us to be given a pointer to
+ a generic block, and go backwards to find the list-node. Then
+ we can remove this block from it's list without the need to search
+ through a linked list in order to remove the node. It also allows
+ us to 'delete' a memory block without needing the dbg structure.
+ We still need the dbg structure on allocation so that we know which
+ linked list to add the block to.
+
+ Only the allocation of the dbg structure itself cannot use _dwarf_p_get_alloc.
+ That structure should be set up by hand, and the two list pointers
+ should be initialized to point at the node itself. That initializes
+ the doubly linked list.
*/
- /*ARGSUSED*/
- Dwarf_Ptr _dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size)
+
+#define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t)))
+#define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t)))
+
+
+/*
+ dbg should be NULL only when allocating dbg itself. In that
+ case we initialize it to an empty circular doubly-linked list.
+*/
+
+Dwarf_Ptr
+_dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size)
{
void *sp;
+ memory_list_t *lp = NULL;
+ memory_list_t *dbglp = NULL;
+ memory_list_t *nextblock = NULL;
+
+ /* alloc control struct and data block together for performance reasons */
+ lp = (memory_list_t *) malloc(size + sizeof(memory_list_t));
+ if (lp == NULL) {
+ /* should throw an error */
+ return NULL;
+ }
+
+ /* point to 'size' bytes just beyond lp struct */
+ sp = LIST_TO_BLOCK(lp);
+ memset(sp, 0, size);
+
+ if (dbg == NULL) {
+ lp->next = lp->prev = lp;
+ } else {
+ /* I always have to draw a picture to understand this part. */
+
+ dbglp = BLOCK_TO_LIST(dbg);
+ nextblock = dbglp->next;
+
+ /* Insert between dbglp and nextblock */
+ dbglp->next = lp;
+ lp->prev = dbglp;
+ lp->next = nextblock;
+ nextblock->prev = lp;
+ }
- sp = malloc(size);
- memset(sp,0, (int) size);
return sp;
}
-
- /*ARGSUSED*/ void
-dwarf_p_dealloc(void *space, Dwarf_Unsigned typ)
+/*
+ This routine is only here in case a caller of an older version of the
+ library is calling this for some reason.
+ We will clean up any stray blocks when the session is closed.
+ No need to remove this block. In theory the user might be
+ depending on the fact that we used to just 'free' this.
+ In theory they might also be
+ passing a block that they got from libdwarf. So we don't know if we
+ should try to remove this block from our global list. Safest just to
+ do nothing at this point.
+
+ !!!
+ This function is deprecated! Don't call it inside libdwarf or outside of it.
+ !!!
+*/
+
+void
+dwarf_p_dealloc(Dwarf_Small * ptr)
{
- free(space);
return;
}
+/*
+ The dbg structure is not needed here anymore.
+*/
-/* Essentially a stub for now. */
- /*ARGSUSED*/ void
-_dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr)
+void
+_dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr) /* ARGSUSED */
{
- dwarf_p_dealloc(ptr, DW_DLA_STRING);
+ memory_list_t *lp;
+ lp = BLOCK_TO_LIST(ptr);
+
+ /*
+ Remove from a doubly linked, circular list.
+ Read carefully, use a white board if necessary.
+ If this is an empty list, the following statements are no-ops, and
+ will write to the same memory location they read from.
+ This should only happen when we deallocate the dbg structure itself.
+ */
+
+ lp->prev->next = lp->next;
+ lp->next->prev = lp->prev;
+
+ free((void*)lp);
}
+
+
+/*
+ This routine deallocates all the nodes on the dbg list,
+ and then deallocates the dbg structure itself.
+*/
+
+void
+_dwarf_p_dealloc_all(Dwarf_P_Debug dbg)
+{
+ memory_list_t *dbglp;
+
+ if (dbg == NULL) {
+ /* should throw an error */
+ return;
+ }
+
+ dbglp = BLOCK_TO_LIST(dbg);
+ while (dbglp->next != dbglp) {
+ _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp->next));
+ }
+ if (dbglp->next != dbglp ||
+ dbglp->prev != dbglp) {
+
+ /* should throw error */
+ /* For some reason we couldn't free all the blocks? */
+ return;
+ }
+ _dwarf_p_dealloc(NULL, (void*)dbg);
+}
+