149d3bc9Richard Lowe/*
249d3bc9Richard Lowe  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
307dc194Richard Lowe  Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
44d9fdb4Robert Mustacchi  Portions Copyright 2011-2019. David Anderson.  All Rights Reserved.
54d9fdb4Robert Mustacchi
64d9fdb4Robert Mustacchi  This program is free software; you can redistribute it
74d9fdb4Robert Mustacchi  and/or modify it under the terms of version 2.1 of the
84d9fdb4Robert Mustacchi  GNU Lesser General Public License as published by the Free
94d9fdb4Robert Mustacchi  Software Foundation.
104d9fdb4Robert Mustacchi
114d9fdb4Robert Mustacchi  This program is distributed in the hope that it would be
124d9fdb4Robert Mustacchi  useful, but WITHOUT ANY WARRANTY; without even the implied
134d9fdb4Robert Mustacchi  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
144d9fdb4Robert Mustacchi  PURPOSE.
154d9fdb4Robert Mustacchi
164d9fdb4Robert Mustacchi  Further, this software is distributed without any warranty
174d9fdb4Robert Mustacchi  that it is free of the rightful claim of any third person
184d9fdb4Robert Mustacchi  regarding infringement or the like.  Any license provided
194d9fdb4Robert Mustacchi  herein, whether implied or otherwise, applies only to this
204d9fdb4Robert Mustacchi  software file.  Patent licenses, if any, provided herein
214d9fdb4Robert Mustacchi  do not apply to combinations of this program with other
224d9fdb4Robert Mustacchi  software, or any other product whatsoever.
234d9fdb4Robert Mustacchi
244d9fdb4Robert Mustacchi  You should have received a copy of the GNU Lesser General
254d9fdb4Robert Mustacchi  Public License along with this program; if not, write the
264d9fdb4Robert Mustacchi  Free Software Foundation, Inc., 51 Franklin Street - Fifth
274d9fdb4Robert Mustacchi  Floor, Boston MA 02110-1301, USA.
2849d3bc9Richard Lowe
2949d3bc9Richard Lowe*/
3049d3bc9Richard Lowe
3149d3bc9Richard Lowe#include "config.h"
3207dc194Richard Lowe#include "pro_incl.h"
334d9fdb4Robert Mustacchi#include <stddef.h>
344d9fdb4Robert Mustacchi#include "dwarf.h"
354d9fdb4Robert Mustacchi#include "libdwarf.h"
364d9fdb4Robert Mustacchi#include "pro_opaque.h"
374d9fdb4Robert Mustacchi#include "pro_alloc.h"
3807dc194Richard Lowe#ifdef HAVE_STDLIB_H
3949d3bc9Richard Lowe#include <stdlib.h>
4007dc194Richard Lowe#endif /* HAVE_STDLIB_H */
414d9fdb4Robert Mustacchi#ifdef HAVE_MALLOC_H
424d9fdb4Robert Mustacchi/* Useful include for some Windows compilers. */
434d9fdb4Robert Mustacchi#include <malloc.h>
444d9fdb4Robert Mustacchi#endif /* HAVE_MALLOC_H */
4507dc194Richard Lowe#ifdef HAVE_STRING_H
4607dc194Richard Lowe#include <string.h>
4707dc194Richard Lowe#endif /* HAVE_STRING_H */
484d9fdb4Robert Mustacchi#ifdef HAVE_STDINT_H
494d9fdb4Robert Mustacchi#include <stdint.h> /* For uintptr_t */
504d9fdb4Robert Mustacchi#endif /* HAVE_STDINT_H */
514d9fdb4Robert Mustacchi#ifdef HAVE_INTTYPES_H
524d9fdb4Robert Mustacchi#include <inttypes.h>
534d9fdb4Robert Mustacchi#endif /* HAVE_INTTYPES_H */
544d9fdb4Robert Mustacchi#include "dwarf_tsearch.h"
554d9fdb4Robert Mustacchi
564d9fdb4Robert Mustacchi/*  When each block is allocated, there is a two-word structure
574d9fdb4Robert Mustacchi    allocated at the beginning so the block can go on a list.
584d9fdb4Robert Mustacchi    The address returned is the address *after* the two pointers
594d9fdb4Robert Mustacchi    at the start.  But this allows us to be given a pointer to
604d9fdb4Robert Mustacchi    a generic block, and go backwards to find the list-node.  Then
614d9fdb4Robert Mustacchi    we can remove this block from it's list without the need to search
624d9fdb4Robert Mustacchi    through a linked list in order to remove the node.  It also allows
634d9fdb4Robert Mustacchi    us to 'delete' a memory block without needing the dbg structure.
644d9fdb4Robert Mustacchi    We still need the dbg structure on allocation so that we know which
654d9fdb4Robert Mustacchi    linked list to add the block to.
664d9fdb4Robert Mustacchi
674d9fdb4Robert Mustacchi    Only the allocation of the dbg structure itself cannot use
684d9fdb4Robert Mustacchi    _dwarf_p_get_alloc.
694d9fdb4Robert Mustacchi    That structure should be set up by hand, and the two list pointers
704d9fdb4Robert Mustacchi    should be initialized to point at the node itself.  That initializes
714d9fdb4Robert Mustacchi    the doubly linked list.  */
7207dc194Richard Lowe
7307dc194Richard Lowe#define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t)))
7407dc194Richard Lowe#define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t)))
7507dc194Richard Lowe
7607dc194Richard Lowe
7707dc194Richard Lowe/*
7807dc194Richard Lowe  dbg should be NULL only when allocating dbg itself.  In that
7907dc194Richard Lowe  case we initialize it to an empty circular doubly-linked list.
8007dc194Richard Lowe*/
8107dc194Richard Lowe
8207dc194Richard LoweDwarf_Ptr
8307dc194Richard Lowe_dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size)
8449d3bc9Richard Lowe{
8549d3bc9Richard Lowe    void *sp;
8607dc194Richard Lowe    memory_list_t *lp = NULL;
8707dc194Richard Lowe    memory_list_t *dbglp = NULL;
8807dc194Richard Lowe    memory_list_t *nextblock = NULL;
8907dc194Richard Lowe
9007dc194Richard Lowe    /* alloc control struct and data block together for performance reasons */
9107dc194Richard Lowe    lp = (memory_list_t *) malloc(size + sizeof(memory_list_t));
9207dc194Richard Lowe    if (lp == NULL) {
9307dc194Richard Lowe        /* should throw an error */
9407dc194Richard Lowe        return NULL;
9507dc194Richard Lowe    }
964d9fdb4Robert Mustacchi
9707dc194Richard Lowe    /* point to 'size' bytes just beyond lp struct */
9807dc194Richard Lowe    sp = LIST_TO_BLOCK(lp);
9907dc194Richard Lowe    memset(sp, 0, size);
10007dc194Richard Lowe
10107dc194Richard Lowe    if (dbg == NULL) {
10207dc194Richard Lowe        lp->next = lp->prev = lp;
10307dc194Richard Lowe    } else {
10407dc194Richard Lowe        /* I always have to draw a picture to understand this part. */
10507dc194Richard Lowe
10607dc194Richard Lowe        dbglp = BLOCK_TO_LIST(dbg);
10707dc194Richard Lowe        nextblock = dbglp->next;
1084d9fdb4Robert Mustacchi
10907dc194Richard Lowe        /* Insert between dbglp and nextblock */
11007dc194Richard Lowe        dbglp->next = lp;
11107dc194Richard Lowe        lp->prev = dbglp;
11207dc194Richard Lowe        lp->next = nextblock;
11307dc194Richard Lowe        nextblock->prev = lp;
11407dc194Richard Lowe    }
11549d3bc9Richard Lowe
11649d3bc9Richard Lowe    return sp;
11749d3bc9Richard Lowe}
11849d3bc9Richard Lowe
11907dc194Richard Lowe/*
12007dc194Richard Lowe  This routine is only here in case a caller of an older version of the
12107dc194Richard Lowe  library is calling this for some reason.
1224d9fdb4Robert Mustacchi  This does nothing!
1234d9fdb4Robert Mustacchi  No need to remove this block.  In theory the user might be
1244d9fdb4Robert Mustacchi  depending on the fact that we used to just 'free' this.
12507dc194Richard Lowe  In theory they might also be
12607dc194Richard Lowe  passing a block that they got from libdwarf.  So we don't know if we
12707dc194Richard Lowe  should try to remove this block from our global list.  Safest just to
12807dc194Richard Lowe  do nothing at this point.
12907dc194Richard Lowe
13007dc194Richard Lowe  !!!
13107dc194Richard Lowe  This function is deprecated!  Don't call it inside libdwarf or outside of it.
1324d9fdb4Robert Mustacchi  Does nothing!
13307dc194Richard Lowe  !!!
13407dc194Richard Lowe*/
1354d9fdb4Robert Mustacchi
13607dc194Richard Lowevoid
1374d9fdb4Robert Mustacchidwarf_p_dealloc(UNUSEDARG Dwarf_Small * ptr)
13849d3bc9Richard Lowe{
13949d3bc9Richard Lowe    return;
14049d3bc9Richard Lowe}
14149d3bc9Richard Lowe
14207dc194Richard Lowe/*
14307dc194Richard Lowe  The dbg structure is not needed here anymore.
14407dc194Richard Lowe*/
14549d3bc9Richard Lowe
14607dc194Richard Lowevoid
1474d9fdb4Robert Mustacchi_dwarf_p_dealloc(UNUSEDARG Dwarf_P_Debug dbg,
1484d9fdb4Robert Mustacchi    Dwarf_Small * ptr) /* ARGSUSED */
1494d9fdb4Robert Mustacchi{
1504d9fdb4Robert Mustacchi    memory_list_t *lp;
1514d9fdb4Robert Mustacchi    lp = BLOCK_TO_LIST(ptr);
1524d9fdb4Robert Mustacchi
1534d9fdb4Robert Mustacchi    /*  Remove from a doubly linked, circular list.
1544d9fdb4Robert Mustacchi        Read carefully, use a white board if necessary.
1554d9fdb4Robert Mustacchi        If this is an empty list, the following statements are no-ops, and
1564d9fdb4Robert Mustacchi        will write to the same memory location they read from.
1574d9fdb4Robert Mustacchi        This should only happen when we deallocate the dbg structure itself.
1584d9fdb4Robert Mustacchi    */
1594d9fdb4Robert Mustacchi    if (lp == lp->next) {
1604d9fdb4Robert Mustacchi        /*  The list has a single item, itself. */
1614d9fdb4Robert Mustacchi        lp->prev = 0;
1624d9fdb4Robert Mustacchi        lp->next = 0;
1634d9fdb4Robert Mustacchi    } else if (lp->next == lp->prev) {
1644d9fdb4Robert Mustacchi        /*  List had exactly two entries. Reduce it to one,
1654d9fdb4Robert Mustacchi            cutting lp out. */
1664d9fdb4Robert Mustacchi        memory_list_t * remaining = lp->next;
1674d9fdb4Robert Mustacchi        remaining->next = remaining;
1684d9fdb4Robert Mustacchi        remaining->prev = remaining;
1694d9fdb4Robert Mustacchi    } else  {
1704d9fdb4Robert Mustacchi        /*  Multi=entry. Just cut lp out. */
1714d9fdb4Robert Mustacchi        lp->prev->next = lp->next;
1724d9fdb4Robert Mustacchi        lp->next->prev = lp->prev;
1734d9fdb4Robert Mustacchi        lp->prev = lp->next = 0;
1744d9fdb4Robert Mustacchi    }
1754d9fdb4Robert Mustacchi    free((void*)lp);
1764d9fdb4Robert Mustacchi}
1774d9fdb4Robert Mustacchi
1784d9fdb4Robert Mustacchi
1794d9fdb4Robert Mustacchistatic void
1804d9fdb4Robert Mustacchi_dwarf_str_hashtab_freenode(void * nodep)
18149d3bc9Richard Lowe{
1824d9fdb4Robert Mustacchi    free(nodep);
18349d3bc9Richard Lowe}
18407dc194Richard Lowe
18507dc194Richard Lowe
18607dc194Richard Lowe/*
18707dc194Richard Lowe  This routine deallocates all the nodes on the dbg list,
18807dc194Richard Lowe  and then deallocates the dbg structure itself.
18907dc194Richard Lowe*/
19007dc194Richard Lowe
19107dc194Richard Lowevoid
19207dc194Richard Lowe_dwarf_p_dealloc_all(Dwarf_P_Debug dbg)
19307dc194Richard Lowe{
19407dc194Richard Lowe    memory_list_t *dbglp;
1954d9fdb4Robert Mustacchi    memory_list_t *base_dbglp;
19607dc194Richard Lowe
19707dc194Richard Lowe    if (dbg == NULL) {
19807dc194Richard Lowe        /* should throw an error */
19907dc194Richard Lowe        return;
20007dc194Richard Lowe    }
20107dc194Richard Lowe
2024d9fdb4Robert Mustacchi    base_dbglp = BLOCK_TO_LIST(dbg);
2034d9fdb4Robert Mustacchi    dbglp = base_dbglp->next;
2044d9fdb4Robert Mustacchi
2054d9fdb4Robert Mustacchi    while (dbglp != base_dbglp) {
2064d9fdb4Robert Mustacchi        memory_list_t*next = dbglp->next;
2074d9fdb4Robert Mustacchi
2084d9fdb4Robert Mustacchi        _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp));
2094d9fdb4Robert Mustacchi        dbglp = next;
21007dc194Richard Lowe    }
2114d9fdb4Robert Mustacchi    dwarf_tdestroy(dbg->de_debug_str_hashtab,
2124d9fdb4Robert Mustacchi        _dwarf_str_hashtab_freenode);
2134d9fdb4Robert Mustacchi    dwarf_tdestroy(dbg->de_debug_line_str_hashtab,
2144d9fdb4Robert Mustacchi        _dwarf_str_hashtab_freenode);
2154d9fdb4Robert Mustacchi    free((void *)base_dbglp);
21607dc194Richard Lowe}