xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_alloc.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
149d3bc91SRichard Lowe /*
249d3bc91SRichard Lowe   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
307dc1947SRichard Lowe   Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
4*4d9fdb46SRobert Mustacchi   Portions Copyright 2011-2019. David Anderson.  All Rights Reserved.
5*4d9fdb46SRobert Mustacchi 
6*4d9fdb46SRobert Mustacchi   This program is free software; you can redistribute it
7*4d9fdb46SRobert Mustacchi   and/or modify it under the terms of version 2.1 of the
8*4d9fdb46SRobert Mustacchi   GNU Lesser General Public License as published by the Free
9*4d9fdb46SRobert Mustacchi   Software Foundation.
10*4d9fdb46SRobert Mustacchi 
11*4d9fdb46SRobert Mustacchi   This program is distributed in the hope that it would be
12*4d9fdb46SRobert Mustacchi   useful, but WITHOUT ANY WARRANTY; without even the implied
13*4d9fdb46SRobert Mustacchi   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14*4d9fdb46SRobert Mustacchi   PURPOSE.
15*4d9fdb46SRobert Mustacchi 
16*4d9fdb46SRobert Mustacchi   Further, this software is distributed without any warranty
17*4d9fdb46SRobert Mustacchi   that it is free of the rightful claim of any third person
18*4d9fdb46SRobert Mustacchi   regarding infringement or the like.  Any license provided
19*4d9fdb46SRobert Mustacchi   herein, whether implied or otherwise, applies only to this
20*4d9fdb46SRobert Mustacchi   software file.  Patent licenses, if any, provided herein
21*4d9fdb46SRobert Mustacchi   do not apply to combinations of this program with other
22*4d9fdb46SRobert Mustacchi   software, or any other product whatsoever.
23*4d9fdb46SRobert Mustacchi 
24*4d9fdb46SRobert Mustacchi   You should have received a copy of the GNU Lesser General
25*4d9fdb46SRobert Mustacchi   Public License along with this program; if not, write the
26*4d9fdb46SRobert Mustacchi   Free Software Foundation, Inc., 51 Franklin Street - Fifth
27*4d9fdb46SRobert Mustacchi   Floor, Boston MA 02110-1301, USA.
2849d3bc91SRichard Lowe 
2949d3bc91SRichard Lowe */
3049d3bc91SRichard Lowe 
3149d3bc91SRichard Lowe #include "config.h"
3207dc1947SRichard Lowe #include "pro_incl.h"
33*4d9fdb46SRobert Mustacchi #include <stddef.h>
34*4d9fdb46SRobert Mustacchi #include "dwarf.h"
35*4d9fdb46SRobert Mustacchi #include "libdwarf.h"
36*4d9fdb46SRobert Mustacchi #include "pro_opaque.h"
37*4d9fdb46SRobert Mustacchi #include "pro_alloc.h"
3807dc1947SRichard Lowe #ifdef HAVE_STDLIB_H
3949d3bc91SRichard Lowe #include <stdlib.h>
4007dc1947SRichard Lowe #endif /* HAVE_STDLIB_H */
41*4d9fdb46SRobert Mustacchi #ifdef HAVE_MALLOC_H
42*4d9fdb46SRobert Mustacchi /* Useful include for some Windows compilers. */
43*4d9fdb46SRobert Mustacchi #include <malloc.h>
44*4d9fdb46SRobert Mustacchi #endif /* HAVE_MALLOC_H */
4507dc1947SRichard Lowe #ifdef HAVE_STRING_H
4607dc1947SRichard Lowe #include <string.h>
4707dc1947SRichard Lowe #endif /* HAVE_STRING_H */
48*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDINT_H
49*4d9fdb46SRobert Mustacchi #include <stdint.h> /* For uintptr_t */
50*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDINT_H */
51*4d9fdb46SRobert Mustacchi #ifdef HAVE_INTTYPES_H
52*4d9fdb46SRobert Mustacchi #include <inttypes.h>
53*4d9fdb46SRobert Mustacchi #endif /* HAVE_INTTYPES_H */
54*4d9fdb46SRobert Mustacchi #include "dwarf_tsearch.h"
55*4d9fdb46SRobert Mustacchi 
56*4d9fdb46SRobert Mustacchi /*  When each block is allocated, there is a two-word structure
57*4d9fdb46SRobert Mustacchi     allocated at the beginning so the block can go on a list.
58*4d9fdb46SRobert Mustacchi     The address returned is the address *after* the two pointers
59*4d9fdb46SRobert Mustacchi     at the start.  But this allows us to be given a pointer to
60*4d9fdb46SRobert Mustacchi     a generic block, and go backwards to find the list-node.  Then
61*4d9fdb46SRobert Mustacchi     we can remove this block from it's list without the need to search
62*4d9fdb46SRobert Mustacchi     through a linked list in order to remove the node.  It also allows
63*4d9fdb46SRobert Mustacchi     us to 'delete' a memory block without needing the dbg structure.
64*4d9fdb46SRobert Mustacchi     We still need the dbg structure on allocation so that we know which
65*4d9fdb46SRobert Mustacchi     linked list to add the block to.
66*4d9fdb46SRobert Mustacchi 
67*4d9fdb46SRobert Mustacchi     Only the allocation of the dbg structure itself cannot use
68*4d9fdb46SRobert Mustacchi     _dwarf_p_get_alloc.
69*4d9fdb46SRobert Mustacchi     That structure should be set up by hand, and the two list pointers
70*4d9fdb46SRobert Mustacchi     should be initialized to point at the node itself.  That initializes
71*4d9fdb46SRobert Mustacchi     the doubly linked list.  */
7207dc1947SRichard Lowe 
7307dc1947SRichard Lowe #define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t)))
7407dc1947SRichard Lowe #define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t)))
7507dc1947SRichard Lowe 
7607dc1947SRichard Lowe 
7707dc1947SRichard Lowe /*
7807dc1947SRichard Lowe   dbg should be NULL only when allocating dbg itself.  In that
7907dc1947SRichard Lowe   case we initialize it to an empty circular doubly-linked list.
8007dc1947SRichard Lowe */
8107dc1947SRichard Lowe 
8207dc1947SRichard Lowe Dwarf_Ptr
8307dc1947SRichard Lowe _dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size)
8449d3bc91SRichard Lowe {
8549d3bc91SRichard Lowe     void *sp;
8607dc1947SRichard Lowe     memory_list_t *lp = NULL;
8707dc1947SRichard Lowe     memory_list_t *dbglp = NULL;
8807dc1947SRichard Lowe     memory_list_t *nextblock = NULL;
8907dc1947SRichard Lowe 
9007dc1947SRichard Lowe     /* alloc control struct and data block together for performance reasons */
9107dc1947SRichard Lowe     lp = (memory_list_t *) malloc(size + sizeof(memory_list_t));
9207dc1947SRichard Lowe     if (lp == NULL) {
9307dc1947SRichard Lowe         /* should throw an error */
9407dc1947SRichard Lowe         return NULL;
9507dc1947SRichard Lowe     }
96*4d9fdb46SRobert Mustacchi 
9707dc1947SRichard Lowe     /* point to 'size' bytes just beyond lp struct */
9807dc1947SRichard Lowe     sp = LIST_TO_BLOCK(lp);
9907dc1947SRichard Lowe     memset(sp, 0, size);
10007dc1947SRichard Lowe 
10107dc1947SRichard Lowe     if (dbg == NULL) {
10207dc1947SRichard Lowe         lp->next = lp->prev = lp;
10307dc1947SRichard Lowe     } else {
10407dc1947SRichard Lowe         /* I always have to draw a picture to understand this part. */
10507dc1947SRichard Lowe 
10607dc1947SRichard Lowe         dbglp = BLOCK_TO_LIST(dbg);
10707dc1947SRichard Lowe         nextblock = dbglp->next;
108*4d9fdb46SRobert Mustacchi 
10907dc1947SRichard Lowe         /* Insert between dbglp and nextblock */
11007dc1947SRichard Lowe         dbglp->next = lp;
11107dc1947SRichard Lowe         lp->prev = dbglp;
11207dc1947SRichard Lowe         lp->next = nextblock;
11307dc1947SRichard Lowe         nextblock->prev = lp;
11407dc1947SRichard Lowe     }
11549d3bc91SRichard Lowe 
11649d3bc91SRichard Lowe     return sp;
11749d3bc91SRichard Lowe }
11849d3bc91SRichard Lowe 
11907dc1947SRichard Lowe /*
12007dc1947SRichard Lowe   This routine is only here in case a caller of an older version of the
12107dc1947SRichard Lowe   library is calling this for some reason.
122*4d9fdb46SRobert Mustacchi   This does nothing!
123*4d9fdb46SRobert Mustacchi   No need to remove this block.  In theory the user might be
124*4d9fdb46SRobert Mustacchi   depending on the fact that we used to just 'free' this.
12507dc1947SRichard Lowe   In theory they might also be
12607dc1947SRichard Lowe   passing a block that they got from libdwarf.  So we don't know if we
12707dc1947SRichard Lowe   should try to remove this block from our global list.  Safest just to
12807dc1947SRichard Lowe   do nothing at this point.
12907dc1947SRichard Lowe 
13007dc1947SRichard Lowe   !!!
13107dc1947SRichard Lowe   This function is deprecated!  Don't call it inside libdwarf or outside of it.
132*4d9fdb46SRobert Mustacchi   Does nothing!
13307dc1947SRichard Lowe   !!!
13407dc1947SRichard Lowe */
135*4d9fdb46SRobert Mustacchi 
13607dc1947SRichard Lowe void
137*4d9fdb46SRobert Mustacchi dwarf_p_dealloc(UNUSEDARG Dwarf_Small * ptr)
13849d3bc91SRichard Lowe {
13949d3bc91SRichard Lowe     return;
14049d3bc91SRichard Lowe }
14149d3bc91SRichard Lowe 
14207dc1947SRichard Lowe /*
14307dc1947SRichard Lowe   The dbg structure is not needed here anymore.
14407dc1947SRichard Lowe */
14549d3bc91SRichard Lowe 
14607dc1947SRichard Lowe void
147*4d9fdb46SRobert Mustacchi _dwarf_p_dealloc(UNUSEDARG Dwarf_P_Debug dbg,
148*4d9fdb46SRobert Mustacchi     Dwarf_Small * ptr) /* ARGSUSED */
149*4d9fdb46SRobert Mustacchi {
150*4d9fdb46SRobert Mustacchi     memory_list_t *lp;
151*4d9fdb46SRobert Mustacchi     lp = BLOCK_TO_LIST(ptr);
152*4d9fdb46SRobert Mustacchi 
153*4d9fdb46SRobert Mustacchi     /*  Remove from a doubly linked, circular list.
154*4d9fdb46SRobert Mustacchi         Read carefully, use a white board if necessary.
155*4d9fdb46SRobert Mustacchi         If this is an empty list, the following statements are no-ops, and
156*4d9fdb46SRobert Mustacchi         will write to the same memory location they read from.
157*4d9fdb46SRobert Mustacchi         This should only happen when we deallocate the dbg structure itself.
158*4d9fdb46SRobert Mustacchi     */
159*4d9fdb46SRobert Mustacchi     if (lp == lp->next) {
160*4d9fdb46SRobert Mustacchi         /*  The list has a single item, itself. */
161*4d9fdb46SRobert Mustacchi         lp->prev = 0;
162*4d9fdb46SRobert Mustacchi         lp->next = 0;
163*4d9fdb46SRobert Mustacchi     } else if (lp->next == lp->prev) {
164*4d9fdb46SRobert Mustacchi         /*  List had exactly two entries. Reduce it to one,
165*4d9fdb46SRobert Mustacchi             cutting lp out. */
166*4d9fdb46SRobert Mustacchi         memory_list_t * remaining = lp->next;
167*4d9fdb46SRobert Mustacchi         remaining->next = remaining;
168*4d9fdb46SRobert Mustacchi         remaining->prev = remaining;
169*4d9fdb46SRobert Mustacchi     } else  {
170*4d9fdb46SRobert Mustacchi         /*  Multi=entry. Just cut lp out. */
171*4d9fdb46SRobert Mustacchi         lp->prev->next = lp->next;
172*4d9fdb46SRobert Mustacchi         lp->next->prev = lp->prev;
173*4d9fdb46SRobert Mustacchi         lp->prev = lp->next = 0;
174*4d9fdb46SRobert Mustacchi     }
175*4d9fdb46SRobert Mustacchi     free((void*)lp);
176*4d9fdb46SRobert Mustacchi }
177*4d9fdb46SRobert Mustacchi 
178*4d9fdb46SRobert Mustacchi 
179*4d9fdb46SRobert Mustacchi static void
180*4d9fdb46SRobert Mustacchi _dwarf_str_hashtab_freenode(void * nodep)
18149d3bc91SRichard Lowe {
182*4d9fdb46SRobert Mustacchi     free(nodep);
18349d3bc91SRichard Lowe }
18407dc1947SRichard Lowe 
18507dc1947SRichard Lowe 
18607dc1947SRichard Lowe /*
18707dc1947SRichard Lowe   This routine deallocates all the nodes on the dbg list,
18807dc1947SRichard Lowe   and then deallocates the dbg structure itself.
18907dc1947SRichard Lowe */
19007dc1947SRichard Lowe 
19107dc1947SRichard Lowe void
19207dc1947SRichard Lowe _dwarf_p_dealloc_all(Dwarf_P_Debug dbg)
19307dc1947SRichard Lowe {
19407dc1947SRichard Lowe     memory_list_t *dbglp;
195*4d9fdb46SRobert Mustacchi     memory_list_t *base_dbglp;
19607dc1947SRichard Lowe 
19707dc1947SRichard Lowe     if (dbg == NULL) {
19807dc1947SRichard Lowe         /* should throw an error */
19907dc1947SRichard Lowe         return;
20007dc1947SRichard Lowe     }
20107dc1947SRichard Lowe 
202*4d9fdb46SRobert Mustacchi     base_dbglp = BLOCK_TO_LIST(dbg);
203*4d9fdb46SRobert Mustacchi     dbglp = base_dbglp->next;
204*4d9fdb46SRobert Mustacchi 
205*4d9fdb46SRobert Mustacchi     while (dbglp != base_dbglp) {
206*4d9fdb46SRobert Mustacchi         memory_list_t*next = dbglp->next;
207*4d9fdb46SRobert Mustacchi 
208*4d9fdb46SRobert Mustacchi         _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp));
209*4d9fdb46SRobert Mustacchi         dbglp = next;
21007dc1947SRichard Lowe     }
211*4d9fdb46SRobert Mustacchi     dwarf_tdestroy(dbg->de_debug_str_hashtab,
212*4d9fdb46SRobert Mustacchi         _dwarf_str_hashtab_freenode);
213*4d9fdb46SRobert Mustacchi     dwarf_tdestroy(dbg->de_debug_line_str_hashtab,
214*4d9fdb46SRobert Mustacchi         _dwarf_str_hashtab_freenode);
215*4d9fdb46SRobert Mustacchi     free((void *)base_dbglp);
21607dc1947SRichard Lowe }
217