149d3bc9Richard Lowe/*
249d3bc9Richard Lowe
349d3bc9Richard Lowe  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
407dc194Richard Lowe  Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
549d3bc9Richard Lowe
649d3bc9Richard Lowe  This program is free software; you can redistribute it and/or modify it
749d3bc9Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
849d3bc9Richard Lowe  as published by the Free Software Foundation.
949d3bc9Richard Lowe
1049d3bc9Richard Lowe  This program is distributed in the hope that it would be useful, but
1149d3bc9Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1349d3bc9Richard Lowe
1449d3bc9Richard Lowe  Further, this software is distributed without any warranty that it is
1549d3bc9Richard Lowe  free of the rightful claim of any third person regarding infringement
1649d3bc9Richard Lowe  or the like.  Any license provided herein, whether implied or
1749d3bc9Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
1849d3bc9Richard Lowe  any, provided herein do not apply to combinations of this program with
1949d3bc9Richard Lowe  other software, or any other product whatsoever.
2049d3bc9Richard Lowe
2149d3bc9Richard Lowe  You should have received a copy of the GNU Lesser General Public
2249d3bc9Richard Lowe  License along with this program; if not, write the Free Software
2307dc194Richard Lowe  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2449d3bc9Richard Lowe  USA.
2549d3bc9Richard Lowe
2607dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2749d3bc9Richard Lowe  Mountain View, CA 94043, or:
2849d3bc9Richard Lowe
2949d3bc9Richard Lowe  http://www.sgi.com
3049d3bc9Richard Lowe
3149d3bc9Richard Lowe  For further information regarding this notice, see:
3249d3bc9Richard Lowe
3349d3bc9Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3449d3bc9Richard Lowe
3549d3bc9Richard Lowe*/
3649d3bc9Richard Lowe
3749d3bc9Richard Lowe
3849d3bc9Richard Lowe
3949d3bc9Richard Lowe#include "config.h"
4007dc194Richard Lowe#include "pro_incl.h"
4107dc194Richard Lowe#ifdef HAVE_STDLIB_H
4249d3bc9Richard Lowe#include <stdlib.h>
4307dc194Richard Lowe#endif /* HAVE_STDLIB_H */
4407dc194Richard Lowe#ifdef HAVE_STRING_H
4507dc194Richard Lowe#include <string.h>
4607dc194Richard Lowe#endif /* HAVE_STRING_H */
4707dc194Richard Lowe#include <malloc.h>
4849d3bc9Richard Lowe
4949d3bc9Richard Lowe/*
5007dc194Richard Lowe When each block is allocated, there is a two-word structure
5107dc194Richard Lowe allocated at the beginning so the block can go on a list.
5207dc194Richard Lowe The address returned is the address *after* the two pointers
5307dc194Richard Lowe at the start.  But this allows us to be given a pointer to
5407dc194Richard Lowe a generic block, and go backwards to find the list-node.  Then
5507dc194Richard Lowe we can remove this block from it's list without the need to search
5607dc194Richard Lowe through a linked list in order to remove the node.  It also allows
5707dc194Richard Lowe us to 'delete' a memory block without needing the dbg structure.
5807dc194Richard Lowe We still need the dbg structure on allocation so that we know which
5907dc194Richard Lowe linked list to add the block to.
6007dc194Richard Lowe
6107dc194Richard Lowe Only the allocation of the dbg structure itself cannot use _dwarf_p_get_alloc.
6207dc194Richard Lowe That structure should be set up by hand, and the two list pointers
6307dc194Richard Lowe should be initialized to point at the node itself.  That initializes
6407dc194Richard Lowe the doubly linked list.
6549d3bc9Richard Lowe*/
6607dc194Richard Lowe
6707dc194Richard Lowe#define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t)))
6807dc194Richard Lowe#define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t)))
6907dc194Richard Lowe
7007dc194Richard Lowe
7107dc194Richard Lowe/*
7207dc194Richard Lowe  dbg should be NULL only when allocating dbg itself.  In that
7307dc194Richard Lowe  case we initialize it to an empty circular doubly-linked list.
7407dc194Richard Lowe*/
7507dc194Richard Lowe
7607dc194Richard LoweDwarf_Ptr
7707dc194Richard Lowe_dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size)
7849d3bc9Richard Lowe{
7949d3bc9Richard Lowe    void *sp;
8007dc194Richard Lowe    memory_list_t *lp = NULL;
8107dc194Richard Lowe    memory_list_t *dbglp = NULL;
8207dc194Richard Lowe    memory_list_t *nextblock = NULL;
8307dc194Richard Lowe
8407dc194Richard Lowe    /* alloc control struct and data block together for performance reasons */
8507dc194Richard Lowe    lp = (memory_list_t *) malloc(size + sizeof(memory_list_t));
8607dc194Richard Lowe    if (lp == NULL) {
8707dc194Richard Lowe        /* should throw an error */
8807dc194Richard Lowe        return NULL;
8907dc194Richard Lowe    }
9007dc194Richard Lowe
9107dc194Richard Lowe    /* point to 'size' bytes just beyond lp struct */
9207dc194Richard Lowe    sp = LIST_TO_BLOCK(lp);
9307dc194Richard Lowe    memset(sp, 0, size);
9407dc194Richard Lowe
9507dc194Richard Lowe    if (dbg == NULL) {
9607dc194Richard Lowe        lp->next = lp->prev = lp;
9707dc194Richard Lowe    } else {
9807dc194Richard Lowe        /* I always have to draw a picture to understand this part. */
9907dc194Richard Lowe
10007dc194Richard Lowe        dbglp = BLOCK_TO_LIST(dbg);
10107dc194Richard Lowe        nextblock = dbglp->next;
10207dc194Richard Lowe
10307dc194Richard Lowe        /* Insert between dbglp and nextblock */
10407dc194Richard Lowe        dbglp->next = lp;
10507dc194Richard Lowe        lp->prev = dbglp;
10607dc194Richard Lowe        lp->next = nextblock;
10707dc194Richard Lowe        nextblock->prev = lp;
10807dc194Richard Lowe    }
10949d3bc9Richard Lowe
11049d3bc9Richard Lowe    return sp;
11149d3bc9Richard Lowe}
11249d3bc9Richard Lowe
11307dc194Richard Lowe/*
11407dc194Richard Lowe  This routine is only here in case a caller of an older version of the
11507dc194Richard Lowe  library is calling this for some reason.
11607dc194Richard Lowe  We will clean up any stray blocks when the session is closed.
11707dc194Richard Lowe  No need to remove this block.  In theory the user might be
11807dc194Richard Lowe  depending on the fact that we used to just 'free' this.
11907dc194Richard Lowe  In theory they might also be
12007dc194Richard Lowe  passing a block that they got from libdwarf.  So we don't know if we
12107dc194Richard Lowe  should try to remove this block from our global list.  Safest just to
12207dc194Richard Lowe  do nothing at this point.
12307dc194Richard Lowe
12407dc194Richard Lowe  !!!
12507dc194Richard Lowe  This function is deprecated!  Don't call it inside libdwarf or outside of it.
12607dc194Richard Lowe  !!!
12707dc194Richard Lowe*/
12807dc194Richard Lowe
12907dc194Richard Lowevoid
13007dc194Richard Lowedwarf_p_dealloc(Dwarf_Small * ptr)
13149d3bc9Richard Lowe{
13249d3bc9Richard Lowe    return;
13349d3bc9Richard Lowe}
13449d3bc9Richard Lowe
13507dc194Richard Lowe/*
13607dc194Richard Lowe  The dbg structure is not needed here anymore.
13707dc194Richard Lowe*/
13849d3bc9Richard Lowe
13907dc194Richard Lowevoid
14007dc194Richard Lowe_dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr) /* ARGSUSED */
14149d3bc9Richard Lowe{
14207dc194Richard Lowe  memory_list_t *lp;
14307dc194Richard Lowe  lp = BLOCK_TO_LIST(ptr);
14407dc194Richard Lowe
14507dc194Richard Lowe  /*
14607dc194Richard Lowe    Remove from a doubly linked, circular list.
14707dc194Richard Lowe    Read carefully, use a white board if necessary.
14807dc194Richard Lowe    If this is an empty list, the following statements are no-ops, and
14907dc194Richard Lowe    will write to the same memory location they read from.
15007dc194Richard Lowe    This should only happen when we deallocate the dbg structure itself.
15107dc194Richard Lowe  */
15207dc194Richard Lowe
15307dc194Richard Lowe  lp->prev->next = lp->next;
15407dc194Richard Lowe  lp->next->prev = lp->prev;
15507dc194Richard Lowe
15607dc194Richard Lowe  free((void*)lp);
15749d3bc9Richard Lowe}
15807dc194Richard Lowe
15907dc194Richard Lowe
16007dc194Richard Lowe/*
16107dc194Richard Lowe  This routine deallocates all the nodes on the dbg list,
16207dc194Richard Lowe  and then deallocates the dbg structure itself.
16307dc194Richard Lowe*/
16407dc194Richard Lowe
16507dc194Richard Lowevoid
16607dc194Richard Lowe_dwarf_p_dealloc_all(Dwarf_P_Debug dbg)
16707dc194Richard Lowe{
16807dc194Richard Lowe    memory_list_t *dbglp;
16907dc194Richard Lowe
17007dc194Richard Lowe    if (dbg == NULL) {
17107dc194Richard Lowe        /* should throw an error */
17207dc194Richard Lowe        return;
17307dc194Richard Lowe    }
17407dc194Richard Lowe
17507dc194Richard Lowe    dbglp = BLOCK_TO_LIST(dbg);
17607dc194Richard Lowe    while (dbglp->next != dbglp) {
17707dc194Richard Lowe        _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp->next));
17807dc194Richard Lowe    }
17907dc194Richard Lowe    if (dbglp->next != dbglp ||
18007dc194Richard Lowe        dbglp->prev != dbglp) {
18107dc194Richard Lowe
18207dc194Richard Lowe        /* should throw error */
18307dc194Richard Lowe        /* For some reason we couldn't free all the blocks? */
18407dc194Richard Lowe        return;
18507dc194Richard Lowe    }
18607dc194Richard Lowe    _dwarf_p_dealloc(NULL, (void*)dbg);
18707dc194Richard Lowe}
18807dc194Richard Lowe