Blame libdwarf/dwarf_alloc.c

Packit cdaae3
/*
Packit cdaae3
  Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
Packit cdaae3
  Portions Copyright (C) 2007-2011  David Anderson. All Rights Reserved.
Packit cdaae3
Packit cdaae3
  This program is free software; you can redistribute it and/or modify it
Packit cdaae3
  under the terms of version 2.1 of the GNU Lesser General Public License
Packit cdaae3
  as published by the Free Software Foundation.
Packit cdaae3
Packit cdaae3
  This program is distributed in the hope that it would be useful, but
Packit cdaae3
  WITHOUT ANY WARRANTY; without even the implied warranty of
Packit cdaae3
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Packit cdaae3
Packit cdaae3
  Further, this software is distributed without any warranty that it is
Packit cdaae3
  free of the rightful claim of any third person regarding infringement
Packit cdaae3
  or the like.  Any license provided herein, whether implied or
Packit cdaae3
  otherwise, applies only to this software file.  Patent licenses, if
Packit cdaae3
  any, provided herein do not apply to combinations of this program with
Packit cdaae3
  other software, or any other product whatsoever.
Packit cdaae3
Packit cdaae3
  You should have received a copy of the GNU Lesser General Public
Packit cdaae3
  License along with this program; if not, write the Free Software
Packit cdaae3
  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
Packit cdaae3
  USA.
Packit cdaae3
Packit cdaae3
*/
Packit cdaae3
Packit cdaae3
#undef  DEBUG
Packit cdaae3
Packit cdaae3
#include "config.h"
Packit cdaae3
#include "dwarf_incl.h"
Packit cdaae3
#include <sys/types.h>
Packit cdaae3
Packit cdaae3
#include <stdlib.h>
Packit cdaae3
#include <stdio.h>
Packit cdaae3
Packit cdaae3
/*  These files are included to get the sizes
Packit cdaae3
    of structs for malloc.
Packit cdaae3
*/
Packit cdaae3
#include "dwarf_line.h"
Packit cdaae3
#include "dwarf_global.h"
Packit cdaae3
#include "dwarf_arange.h"
Packit cdaae3
#include "dwarf_abbrev.h"
Packit cdaae3
#include "dwarf_die_deliv.h"
Packit cdaae3
#include "dwarf_frame.h"
Packit cdaae3
#include "dwarf_loc.h"
Packit cdaae3
#include "dwarf_funcs.h"
Packit cdaae3
#include "dwarf_types.h"
Packit cdaae3
#include "dwarf_vars.h"
Packit cdaae3
#include "dwarf_weaks.h"
Packit cdaae3
#include "dwarf_harmless.h"
Packit cdaae3
#include "dwarf_tsearch.h"
Packit cdaae3
#include "dwarf_gdbindex.h"
Packit cdaae3
#include "dwarf_xu_index.h"
Packit cdaae3
#include "dwarf_macro5.h"
Packit cdaae3
#include "dwarf_dnames.h"
Packit cdaae3
#include "dwarf_dsc.h"
Packit cdaae3
Packit cdaae3
#define TRUE 1
Packit cdaae3
#define FALSE 0
Packit cdaae3
/*  Some allocations are simple some not. These reduce
Packit cdaae3
    the issue of determining which sort of thing to a simple
Packit cdaae3
    test. See ia_multiply_count
Packit cdaae3
    Usually when MULTIPLY_NO is set the count
Packit cdaae3
    is 1, so MULTIPY_CT would work as well.  */
Packit cdaae3
#define MULTIPLY_NO 0
Packit cdaae3
#define MULTIPLY_CT 1
Packit cdaae3
#define MULTIPLY_SP 2
Packit cdaae3
/*  This translates into de_alloc_hdr into a per-instance size
Packit cdaae3
    and allows room for a constructor/destructor pointer.
Packit cdaae3
    Rearranging the DW_DLA values would break binary compatibility
Packit cdaae3
    so that is not an option.
Packit cdaae3
*/
Packit cdaae3
struct ial_s {
Packit cdaae3
    /*  In bytes, one struct instance.  */
Packit cdaae3
    short ia_struct_size;
Packit cdaae3
Packit cdaae3
    /*  Not a count, but a MULTIPLY{_NO,_CT,_SP} value. */
Packit cdaae3
    short ia_multiply_count;
Packit cdaae3
Packit cdaae3
    /*  When we really need a constructor/destructor
Packit cdaae3
        these make applying such quite simple. */
Packit cdaae3
    int (*specialconstructor) (Dwarf_Debug, void *);
Packit cdaae3
    void (*specialdestructor) (void *);
Packit cdaae3
};
Packit cdaae3
Packit cdaae3
/*  Used as a way to return meaningful errors when
Packit cdaae3
    the malloc arena is exhausted (when malloc returns NULL).
Packit cdaae3
    Not normally used.
Packit cdaae3
    New in December 2014.*/
Packit cdaae3
struct Dwarf_Error_s _dwarf_failsafe_error = {
Packit cdaae3
    DW_DLE_FAILSAFE_ERRVAL,
Packit cdaae3
    1
Packit cdaae3
};
Packit cdaae3
Packit cdaae3
Packit cdaae3
/*  To do destructors we need some extra data in every
Packit cdaae3
    _dwarf_get_alloc situation. */
Packit cdaae3
/* Here is the extra we malloc for a prefix. */
Packit cdaae3
struct reserve_size_s {
Packit cdaae3
   void *dummy_rsv1;
Packit cdaae3
   void *dummy_rsv2;
Packit cdaae3
};
Packit cdaae3
/* Here is how we use the extra prefix area. */
Packit cdaae3
struct reserve_data_s {
Packit cdaae3
   void *rd_dbg;
Packit cdaae3
   unsigned short rd_length;
Packit cdaae3
   unsigned short rd_type;
Packit cdaae3
};
Packit cdaae3
#define DW_RESERVE sizeof(struct reserve_size_s)
Packit cdaae3
Packit cdaae3
Packit cdaae3
static const
Packit cdaae3
struct ial_s alloc_instance_basics[ALLOC_AREA_INDEX_TABLE_MAX] = {
Packit cdaae3
    { 1,MULTIPLY_NO, 0, 0},            /* 0  none */
Packit cdaae3
    { 1,MULTIPLY_CT, 0, 0},            /* 1 DW_DLA_STRING */
Packit cdaae3
    { sizeof(Dwarf_Loc),MULTIPLY_NO, 0, 0} ,/* 2 DW_DLA_LOC */
Packit cdaae3
    { sizeof(Dwarf_Locdesc),MULTIPLY_NO, 0, 0} , /* 3 DW_DLA_LOCDESC */
Packit cdaae3
    { 1,MULTIPLY_NO, 0, 0} , /* not used *//* 4 DW_DLA_ELLIST */
Packit cdaae3
    { 1,MULTIPLY_NO, 0, 0} , /* not used *//* 5 DW_DLA_BOUNDS */
Packit cdaae3
    { sizeof(Dwarf_Block),MULTIPLY_NO,  0, 0} , /* 6 DW_DLA_BLOCK */
Packit cdaae3
Packit cdaae3
    /* the actual dwarf_debug structure */ /* 7 DW_DLA_DEBUG */
Packit cdaae3
    { 1,MULTIPLY_NO, 0, 0} ,
Packit cdaae3
Packit cdaae3
    {sizeof(struct Dwarf_Die_s),MULTIPLY_NO, 0, 0},/* 8 DW_DLA_DIE */
Packit cdaae3
    {sizeof(struct Dwarf_Line_s),MULTIPLY_NO, 0, 0},/* 9 DW_DLA_LINE */
Packit cdaae3
Packit cdaae3
    /* 10 DW_DLA_ATTR */
Packit cdaae3
    {sizeof(struct Dwarf_Attribute_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    {1,MULTIPLY_NO,  0, 0}, /* not used */ /* 11 DW_DLA_TYPE */
Packit cdaae3
    {1,MULTIPLY_NO,  0, 0}, /* not used */ /* 12 DW_DLA_SUBSCR */
Packit cdaae3
Packit cdaae3
    /* 13 DW_DLA_GLOBAL */
Packit cdaae3
    {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 14 DW_DLA_ERROR */
Packit cdaae3
    {sizeof(struct Dwarf_Error_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    {sizeof(Dwarf_Ptr),MULTIPLY_CT, 0, 0},  /* 15 DW_DLA_LIST */
Packit cdaae3
    {1,MULTIPLY_NO, 0, 0},    /* not used *//* 16 DW_DLA_LINEBUF */
Packit cdaae3
Packit cdaae3
    /* 17 DW_DLA_ARANGE */
Packit cdaae3
    {sizeof(struct Dwarf_Arange_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 18 DW_DLA_ABBREV */
Packit cdaae3
    {sizeof(struct Dwarf_Abbrev_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 19 DW_DLA_FRAME_OP */
Packit cdaae3
    {sizeof(Dwarf_Frame_Op),MULTIPLY_NO,  0, 0} ,
Packit cdaae3
Packit cdaae3
    /* 20 DW_DLA_CIE */
Packit cdaae3
    {sizeof(struct Dwarf_Cie_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    {sizeof(struct Dwarf_Fde_s),MULTIPLY_NO,  0,
Packit cdaae3
        _dwarf_fde_destructor},/* 21 DW_DLA_FDE */
Packit cdaae3
    {sizeof(Dwarf_Loc),MULTIPLY_CT, 0, 0},          /* 22 DW_DLA_LOC_BLOCK */
Packit cdaae3
    {sizeof(Dwarf_Frame_Op),MULTIPLY_CT, 0, 0},     /* 23 DW_DLA_FRAME_BLOCK */
Packit cdaae3
Packit cdaae3
    /* 24 DW_DLA_FUNC UNUSED */
Packit cdaae3
    {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 25 DW_DLA_TYPENAME UNUSED */
Packit cdaae3
    {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 26 DW_DLA_VAR UNUSED */
Packit cdaae3
    {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 27 DW_DLA_WEAK UNUSED */
Packit cdaae3
    {sizeof(struct Dwarf_Global_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    {1,MULTIPLY_SP, 0, 0},                    /* 28 DW_DLA_ADDR */
Packit cdaae3
    {sizeof(Dwarf_Ranges),MULTIPLY_CT, 0,0 }, /* 29 DW_DLA_RANGES */
Packit cdaae3
Packit cdaae3
    /*  The following DW_DLA data types
Packit cdaae3
        are known only inside libdwarf.  */
Packit cdaae3
Packit cdaae3
    /* 30 DW_DLA_ABBREV_LIST */
Packit cdaae3
    { sizeof(struct Dwarf_Abbrev_List_s),MULTIPLY_NO, 0, 0},
Packit cdaae3
Packit cdaae3
    /* 31 DW_DLA_CHAIN */
Packit cdaae3
    {sizeof(struct Dwarf_Chain_s),MULTIPLY_NO, 0, 0},
Packit cdaae3
Packit cdaae3
    /* 32 DW_DLA_CU_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_CU_Context_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    {sizeof(struct Dwarf_Frame_s),MULTIPLY_NO,
Packit cdaae3
        _dwarf_frame_constructor,
Packit cdaae3
        _dwarf_frame_destructor},  /* 33 DW_DLA_FRAME */
Packit cdaae3
Packit cdaae3
    /* 34 DW_DLA_GLOBAL_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 35 DW_DLA_FILE_ENTRY */
Packit cdaae3
    {sizeof(struct Dwarf_File_Entry_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 36 DW_DLA_LINE_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_Line_Context_s),MULTIPLY_NO,
Packit cdaae3
        _dwarf_line_context_constructor,
Packit cdaae3
        _dwarf_line_context_destructor},
Packit cdaae3
Packit cdaae3
    /* 37 DW_DLA_LOC_CHAIN */
Packit cdaae3
    {sizeof(struct Dwarf_Loc_Chain_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 38 0x26 DW_DLA_HASH_TABLE */
Packit cdaae3
    {sizeof(struct Dwarf_Hash_Table_s),MULTIPLY_NO, 0, 0},
Packit cdaae3
Packit cdaae3
    /*  The following really use Global struct: used to be unique struct
Packit cdaae3
    per type, but now merged (11/99).  The opaque types
Packit cdaae3
    are visible in the interface. The types  for
Packit cdaae3
    DW_DLA_FUNC, DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK also use
Packit cdaae3
    the global types.  */
Packit cdaae3
Packit cdaae3
    /* 39 0x27 DW_DLA_FUNC_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 40 0x28 DW_DLA_TYPENAME_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 41 0x29 DW_DLA_VAR_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 42 0x2a DW_DLA_WEAK_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 43 0x2b DW_DLA_PUBTYPES_CONTEXT DWARF3 */
Packit cdaae3
    {sizeof(struct Dwarf_Global_Context_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 44 0x2c DW_DLA_HASH_TABLE_ENTRY */
Packit cdaae3
    {sizeof(struct Dwarf_Hash_Table_Entry_s),MULTIPLY_CT,0,0 },
Packit cdaae3
    /* 0x2d - 0x2f, reserved for future internal use. */
Packit cdaae3
Packit cdaae3
    /* 45 0x2d  DW_DLA_FISSION_PERCU  */
Packit cdaae3
    {sizeof(struct Dwarf_Fission_Per_CU_s),MULTIPLY_CT,  0, 0},
Packit cdaae3
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    /* 0x30-0x36 reserved for future internal use. */
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
    {sizeof(int),MULTIPLY_NO,  0, 0}, /* reserved for future internal  types*/
Packit cdaae3
Packit cdaae3
    /*  now,  we have types that are public. */
Packit cdaae3
    /* 0x37 55.  New in June 2014. Gdb. */
Packit cdaae3
    {sizeof(struct Dwarf_Gdbindex_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /* 0x38 56.  New in July 2014. DWARF5 DebugFission dwp file sections
Packit cdaae3
        .debug_cu_index and .debug_tu_index . */
Packit cdaae3
    {sizeof(struct Dwarf_Xu_Index_Header_s),MULTIPLY_NO,  0, 0},
Packit cdaae3
Packit cdaae3
    /*  These required by new features in DWARF5. Also usable
Packit cdaae3
        for DWARF2,3,4. */
Packit cdaae3
    /* 57 DW_DLA_LOC_BLOCK_C */
Packit cdaae3
    {sizeof(struct Dwarf_Loc_c_s),MULTIPLY_CT, 0, 0},
Packit cdaae3
    /* 58 DW_DLA_LOCDESC_C */
Packit cdaae3
    {sizeof(struct Dwarf_Locdesc_c_s),MULTIPLY_CT, 0, 0},
Packit cdaae3
    /* 59 DW_DLA_LOC_HEAD_C */
Packit cdaae3
    {sizeof(struct Dwarf_Loc_Head_c_s),MULTIPLY_NO, 0, 0},
Packit cdaae3
    /* 60 DW_DLA_MACRO_CONTEXT */
Packit cdaae3
    {sizeof(struct Dwarf_Macro_Context_s),MULTIPLY_NO,
Packit cdaae3
        _dwarf_macro_constructor,
Packit cdaae3
        _dwarf_macro_destructor},
Packit cdaae3
Packit cdaae3
    /* 61 DW_DLA_CHAIN_2 */
Packit cdaae3
    {sizeof(struct Dwarf_Chain_o),MULTIPLY_NO, 0, 0},
Packit cdaae3
    /* 62 DW_DLA_DSC_HEAD 0x3e */
Packit cdaae3
    {sizeof(struct Dwarf_Dsc_Head_s),MULTIPLY_NO, 0,
Packit cdaae3
        _dwarf_dsc_destructor},
Packit cdaae3
    /* 63 DW_DLA_DNAMES_HEAD 0x3f */
Packit cdaae3
    {sizeof(struct Dwarf_Dnames_Head_s),MULTIPLY_NO, 0,
Packit cdaae3
        _dwarf_debugnames_destructor},
Packit cdaae3
};
Packit cdaae3
Packit cdaae3
/*  We are simply using the incoming pointer as the key-pointer.
Packit cdaae3
*/
Packit cdaae3
Packit cdaae3
static DW_TSHASHTYPE
Packit cdaae3
simple_value_hashfunc(const void *keyp)
Packit cdaae3
{
Packit cdaae3
    DW_TSHASHTYPE up = (DW_TSHASHTYPE)keyp;
Packit cdaae3
    return up;
Packit cdaae3
}
Packit cdaae3
/*  We did alloc something but not a fixed-length thing.
Packit cdaae3
    Instead, it starts with some special data we noted.
Packit cdaae3
    The incoming pointer is to the caller data, we
Packit cdaae3
    destruct based on caller, but find the special
Packit cdaae3
    extra data in a prefix area. */
Packit cdaae3
static void
Packit cdaae3
tdestroy_free_node(void *nodep)
Packit cdaae3
{
Packit cdaae3
    char * m = (char *)nodep;
Packit cdaae3
    char * malloc_addr = m - DW_RESERVE;
Packit cdaae3
    struct reserve_data_s * reserve =(struct reserve_data_s *)malloc_addr;
Packit cdaae3
    unsigned type = reserve->rd_type;
Packit cdaae3
    if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
Packit cdaae3
        /* Internal error, corrupted data. */
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
    if(!reserve->rd_dbg) {
Packit cdaae3
        /*  Unused (corrupted?) node in the tree.
Packit cdaae3
            Should never happen. */
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
    if(!reserve->rd_type) {
Packit cdaae3
        /*  Unused (corrupted?) node in the tree.
Packit cdaae3
            Should never happen. */
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
    if (alloc_instance_basics[type].specialdestructor) {
Packit cdaae3
        alloc_instance_basics[type].specialdestructor(m);
Packit cdaae3
    }
Packit cdaae3
    free(malloc_addr);
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/* The sort of hash table entries result in very simple helper functions. */
Packit cdaae3
static int
Packit cdaae3
simple_compare_function(const void *l, const void *r)
Packit cdaae3
{
Packit cdaae3
    DW_TSHASHTYPE lp = (DW_TSHASHTYPE)l;
Packit cdaae3
    DW_TSHASHTYPE rp = (DW_TSHASHTYPE)r;
Packit cdaae3
    if(lp < rp) {
Packit cdaae3
        return -1;
Packit cdaae3
    }
Packit cdaae3
    if(lp > rp) {
Packit cdaae3
        return 1;
Packit cdaae3
    }
Packit cdaae3
    return 0;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  This function returns a pointer to a region
Packit cdaae3
    of memory.  For alloc_types that are not
Packit cdaae3
    strings or lists of pointers, only 1 struct
Packit cdaae3
    can be requested at a time.  This is indicated
Packit cdaae3
    by an input count of 1.  For strings, count
Packit cdaae3
    equals the length of the string it will
Packit cdaae3
    contain, i.e it the length of the string
Packit cdaae3
    plus 1 for the terminating null.  For lists
Packit cdaae3
    of pointers, count is equal to the number of
Packit cdaae3
    pointers.  For DW_DLA_FRAME_BLOCK, DW_DLA_RANGES, and
Packit cdaae3
    DW_DLA_LOC_BLOCK allocation types also, count
Packit cdaae3
    is the count of the number of structs needed.
Packit cdaae3
Packit cdaae3
    This function cannot be used to allocate a
Packit cdaae3
    Dwarf_Debug_s struct.  */
Packit cdaae3
Packit cdaae3
char *
Packit cdaae3
_dwarf_get_alloc(Dwarf_Debug dbg,
Packit cdaae3
    Dwarf_Small alloc_type, Dwarf_Unsigned count)
Packit cdaae3
{
Packit cdaae3
    char * alloc_mem = 0;
Packit cdaae3
    Dwarf_Signed basesize = 0;
Packit cdaae3
    Dwarf_Signed size = 0;
Packit cdaae3
    unsigned int type = alloc_type;
Packit cdaae3
    short action = 0;
Packit cdaae3
Packit cdaae3
    if (dbg == NULL) {
Packit cdaae3
        return NULL;
Packit cdaae3
    }
Packit cdaae3
    if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
Packit cdaae3
        /* internal error */
Packit cdaae3
        return NULL;
Packit cdaae3
    }
Packit cdaae3
    basesize = alloc_instance_basics[alloc_type].ia_struct_size;
Packit cdaae3
    action = alloc_instance_basics[alloc_type].ia_multiply_count;
Packit cdaae3
    if(action == MULTIPLY_NO) {
Packit cdaae3
        /* Usually count is 1, but do not assume it. */
Packit cdaae3
        size = basesize;
Packit cdaae3
    } else if (action == MULTIPLY_CT) {
Packit cdaae3
        size = basesize * count;
Packit cdaae3
    }  else {
Packit cdaae3
        /* MULTIPLY_SP */
Packit cdaae3
        /* DW_DLA_ADDR.. count * largest size */
Packit cdaae3
        size = count *
Packit cdaae3
            (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ?
Packit cdaae3
            sizeof(Dwarf_Addr) : sizeof(Dwarf_Off));
Packit cdaae3
    }
Packit cdaae3
    size += DW_RESERVE;
Packit cdaae3
    alloc_mem = malloc(size);
Packit cdaae3
    if (!alloc_mem) {
Packit cdaae3
        return NULL;
Packit cdaae3
    }
Packit cdaae3
    {
Packit cdaae3
        char * ret_mem = alloc_mem + DW_RESERVE;
Packit cdaae3
        void *key = ret_mem;
Packit cdaae3
        struct reserve_data_s *r = (struct reserve_data_s*)alloc_mem;
Packit cdaae3
        void *result = 0;
Packit cdaae3
Packit cdaae3
        memset(alloc_mem, 0, size);
Packit cdaae3
        /* We are not actually using rd_dbg, we are using rd_type. */
Packit cdaae3
        r->rd_dbg = dbg;
Packit cdaae3
        r->rd_type = alloc_type;
Packit cdaae3
        r->rd_length = size;
Packit cdaae3
        if (alloc_instance_basics[type].specialconstructor) {
Packit cdaae3
            int res =
Packit cdaae3
                alloc_instance_basics[type].specialconstructor(dbg, ret_mem);
Packit cdaae3
            if (res != DW_DLV_OK) {
Packit cdaae3
                /*  We leak what we allocated in _dwarf_find_memory when
Packit cdaae3
                    constructor fails. */
Packit cdaae3
                return NULL;
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
        result = dwarf_tsearch((void *)key,
Packit cdaae3
            &dbg->de_alloc_tree,simple_compare_function);
Packit cdaae3
        if(!result) {
Packit cdaae3
            /*  Something badly wrong. Out of memory.
Packit cdaae3
                pretend all is well. */
Packit cdaae3
        }
Packit cdaae3
        return (ret_mem);
Packit cdaae3
    }
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  This was once a long list of tests using dss_data
Packit cdaae3
    and dss_size to see if 'space' was inside a debug section.
Packit cdaae3
    This tfind approach removes that maintenance headache. */
Packit cdaae3
static int
Packit cdaae3
string_is_in_debug_section(Dwarf_Debug dbg,void * space)
Packit cdaae3
{
Packit cdaae3
    /*  See dwarf_line.c dwarf_srcfiles()
Packit cdaae3
        for one way we can wind up with
Packit cdaae3
        a DW_DLA_STRING string that may or may not be malloc-ed
Packit cdaae3
        by _dwarf_get_alloc().
Packit cdaae3
Packit cdaae3
        dwarf_formstring(), for example, returns strings
Packit cdaae3
        which point into .debug_info or .debug_types but
Packit cdaae3
        dwarf_dealloc is never supposed to be applied
Packit cdaae3
        to strings dwarf_formstring() returns!
Packit cdaae3
Packit cdaae3
        Lots of calls returning strings
Packit cdaae3
        have always been documented as requiring
Packit cdaae3
        dwarf_dealloc(...DW_DLA_STRING) when the code
Packit cdaae3
        just returns a pointer to a portion of a loaded section!
Packit cdaae3
        It is too late to change the documentation. */
Packit cdaae3
Packit cdaae3
    void *result = 0;
Packit cdaae3
    result = dwarf_tfind((void *)space,
Packit cdaae3
        &dbg->de_alloc_tree,simple_compare_function);
Packit cdaae3
    if(!result) {
Packit cdaae3
        /*  Not in the tree, so not malloc-ed
Packit cdaae3
            Nothing to delete. */
Packit cdaae3
        return TRUE;
Packit cdaae3
    }
Packit cdaae3
    /*  We found the address in the tree, so it is NOT
Packit cdaae3
        part of .debug_info or any other dwarf section,
Packit cdaae3
        but is space malloc-d in _dwarf_get_alloc(). */
Packit cdaae3
    return FALSE;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*
Packit cdaae3
    This function is used to deallocate a region of memory
Packit cdaae3
    that was obtained by a call to _dwarf_get_alloc.  Note
Packit cdaae3
    that though dwarf_dealloc() is a public function,
Packit cdaae3
    _dwarf_get_alloc() isn't.
Packit cdaae3
Packit cdaae3
    For lists, typically arrays of pointers, it is assumed
Packit cdaae3
    that the space was allocated by a direct call to malloc,
Packit cdaae3
    and so a straight free() is done.  This is also the case
Packit cdaae3
    for variable length blocks such as DW_DLA_FRAME_BLOCK
Packit cdaae3
    and DW_DLA_LOC_BLOCK and DW_DLA_RANGES.
Packit cdaae3
Packit cdaae3
    For strings, the pointer might point to a string in
Packit cdaae3
    .debug_info or .debug_string.  After this is checked,
Packit cdaae3
    and if found not to be the case, a free() is done,
Packit cdaae3
    again on the assumption that a malloc was used to
Packit cdaae3
    obtain the space.
Packit cdaae3
Packit cdaae3
    This function does not return anything.
Packit cdaae3
*/
Packit cdaae3
void
Packit cdaae3
dwarf_dealloc(Dwarf_Debug dbg,
Packit cdaae3
    Dwarf_Ptr space, Dwarf_Unsigned alloc_type)
Packit cdaae3
{
Packit cdaae3
    unsigned int type = 0;
Packit cdaae3
    char * malloc_addr = 0;
Packit cdaae3
    struct reserve_data_s * r = 0;
Packit cdaae3
Packit cdaae3
    if (space == NULL) {
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
    if (dbg) {
Packit cdaae3
        /*  If it's a string in debug_info etc doing
Packit cdaae3
            (char *)space - DW_RESERVE is totally bogus. */
Packit cdaae3
        if (alloc_type == DW_DLA_STRING &&
Packit cdaae3
            string_is_in_debug_section(dbg,space)) {
Packit cdaae3
            /*  A string pointer may point into .debug_info or
Packit cdaae3
                .debug_string etc.
Packit cdaae3
                So must not be freed.  And strings have no need of a
Packit cdaae3
                specialdestructor().
Packit cdaae3
                Mostly a historical mistake here. */
Packit cdaae3
            return;
Packit cdaae3
        }
Packit cdaae3
        /*  Otherwise it might be allocated string so it is ok
Packit cdaae3
            do the (char *)space - DW_RESERVE  */
Packit cdaae3
    } else {
Packit cdaae3
        /*  App error, or an app that failed to succeed in a
Packit cdaae3
            dwarf_init() call. */
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
    if (alloc_type == DW_DLA_ERROR) {
Packit cdaae3
        Dwarf_Error ep = (Dwarf_Error)space;
Packit cdaae3
        if (ep->er_static_alloc == DE_STATIC) {
Packit cdaae3
            /*  This is special, malloc arena
Packit cdaae3
                was exhausted or a NULL dbg
Packit cdaae3
                was used for the error because the real
Packit cdaae3
                dbg was unavailable. There is nothing to delete, really.
Packit cdaae3
                Set er_errval to signal that the space was dealloc'd. */
Packit cdaae3
            _dwarf_failsafe_error.er_errval = DW_DLE_FAILSAFE_ERRVAL;
Packit cdaae3
            return;
Packit cdaae3
        }
Packit cdaae3
        if (ep->er_static_alloc == DE_MALLOC) {
Packit cdaae3
            /*  This is special, we had no arena
Packit cdaae3
                so just malloc'd a Dwarf_Error_s. */
Packit cdaae3
            free(space);
Packit cdaae3
            return;
Packit cdaae3
        }
Packit cdaae3
        /* Was normal alloc, use normal dealloc. */
Packit cdaae3
    }
Packit cdaae3
    type = alloc_type;
Packit cdaae3
    malloc_addr = (char *)space - DW_RESERVE;
Packit cdaae3
    r =(struct reserve_data_s *)malloc_addr;
Packit cdaae3
    if(dbg != r->rd_dbg) {
Packit cdaae3
        /*  Something is badly wrong. Better to leak than
Packit cdaae3
            to crash. */
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
    if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
Packit cdaae3
        /* internal or user app error */
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
Packit cdaae3
    if (alloc_instance_basics[type].specialdestructor) {
Packit cdaae3
        alloc_instance_basics[type].specialdestructor(space);
Packit cdaae3
    }
Packit cdaae3
    {
Packit cdaae3
        /*  The 'space' pointer we get points after the reserve space.
Packit cdaae3
            The key and address to free are just a few bytes before
Packit cdaae3
            'space'. */
Packit cdaae3
        void *key = space;
Packit cdaae3
        dwarf_tdelete(key,&dbg->de_alloc_tree,simple_compare_function);
Packit cdaae3
        /*  If dwarf_tdelete returns NULL it might mean
Packit cdaae3
            a) tree is empty.
Packit cdaae3
            b) If hashsearch, then a single chain might now be empty,
Packit cdaae3
                so we do not know of a 'parent node'.
Packit cdaae3
            c) We did not find that key, we did nothing.
Packit cdaae3
Packit cdaae3
            In any case, we simply don't worry about it.
Packit cdaae3
            Not Supposed To Happen. */
Packit cdaae3
Packit cdaae3
        free(malloc_addr);
Packit cdaae3
        return;
Packit cdaae3
    }
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
Packit cdaae3
/*
Packit cdaae3
    Allocates space for a Dwarf_Debug_s struct,
Packit cdaae3
    since one does not exist.
Packit cdaae3
*/
Packit cdaae3
Dwarf_Debug
Packit cdaae3
_dwarf_get_debug(void)
Packit cdaae3
{
Packit cdaae3
    Dwarf_Debug dbg;
Packit cdaae3
Packit cdaae3
    dbg = (Dwarf_Debug) malloc(sizeof(struct Dwarf_Debug_s));
Packit cdaae3
    if (dbg == NULL) {
Packit cdaae3
        return (NULL);
Packit cdaae3
    }
Packit cdaae3
    memset(dbg, 0, sizeof(struct Dwarf_Debug_s));
Packit cdaae3
    /* Set up for a dwarf_tsearch hash table */
Packit cdaae3
Packit cdaae3
    dwarf_initialize_search_hash(&dbg->de_alloc_tree,simple_value_hashfunc,0);
Packit cdaae3
Packit cdaae3
Packit cdaae3
    return (dbg);
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*
Packit cdaae3
    This function prints out the statistics
Packit cdaae3
    collected on allocation of memory chunks.
Packit cdaae3
    No longer used.
Packit cdaae3
*/
Packit cdaae3
void
Packit cdaae3
dwarf_print_memory_stats(UNUSEDARG Dwarf_Debug dbg)
Packit cdaae3
{
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
Packit cdaae3
Packit cdaae3
/* In the 'rela' relocation case we might have malloc'd
Packit cdaae3
   space to ensure it is read-write. In that case, free the space.  */
Packit cdaae3
static void
Packit cdaae3
rela_free(struct Dwarf_Section_s * sec)
Packit cdaae3
{
Packit cdaae3
    if (sec->dss_data_was_malloc) {
Packit cdaae3
        free(sec->dss_data);
Packit cdaae3
    }
Packit cdaae3
    sec->dss_data = 0;
Packit cdaae3
    sec->dss_data_was_malloc = 0;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
static void
Packit cdaae3
freecontextlist(Dwarf_Debug dbg, Dwarf_Debug_InfoTypes dis)
Packit cdaae3
{
Packit cdaae3
    Dwarf_CU_Context context = 0;
Packit cdaae3
    Dwarf_CU_Context nextcontext = 0;
Packit cdaae3
    for (context = dis->de_cu_context_list;
Packit cdaae3
        context; context = nextcontext) {
Packit cdaae3
        Dwarf_Hash_Table hash_table = context->cc_abbrev_hash_table;
Packit cdaae3
        _dwarf_free_abbrev_hash_table_contents(dbg,hash_table);
Packit cdaae3
        nextcontext = context->cc_next;
Packit cdaae3
        dwarf_dealloc(dbg, hash_table, DW_DLA_HASH_TABLE);
Packit cdaae3
        context->cc_abbrev_hash_table = 0;
Packit cdaae3
        dwarf_dealloc(dbg, context, DW_DLA_CU_CONTEXT);
Packit cdaae3
    }
Packit cdaae3
    dis->de_cu_context_list = 0;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*
Packit cdaae3
    Used to free all space allocated for this Dwarf_Debug.
Packit cdaae3
    The caller should assume that the Dwarf_Debug pointer
Packit cdaae3
    itself is no longer valid upon return from this function.
Packit cdaae3
Packit cdaae3
    In case of difficulty, this function simply returns quietly.
Packit cdaae3
*/
Packit cdaae3
int
Packit cdaae3
_dwarf_free_all_of_one_debug(Dwarf_Debug dbg)
Packit cdaae3
{
Packit cdaae3
    if (dbg == NULL) {
Packit cdaae3
        return (DW_DLV_ERROR);
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    /*  To do complete validation that we have no surprising missing or
Packit cdaae3
        erroneous deallocs it is advisable to do the dwarf_deallocs here
Packit cdaae3
        that are not things the user can otherwise request.
Packit cdaae3
        Housecleaning.  */
Packit cdaae3
    if (dbg->de_cu_hashindex_data) {
Packit cdaae3
        dwarf_xu_header_free(dbg->de_cu_hashindex_data);
Packit cdaae3
        dbg->de_cu_hashindex_data = 0;
Packit cdaae3
    }
Packit cdaae3
    if (dbg->de_tu_hashindex_data) {
Packit cdaae3
        dwarf_xu_header_free(dbg->de_tu_hashindex_data);
Packit cdaae3
        dbg->de_tu_hashindex_data = 0;
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    freecontextlist(dbg,&dbg->de_info_reading);
Packit cdaae3
    freecontextlist(dbg,&dbg->de_types_reading);
Packit cdaae3
Packit cdaae3
    /* Housecleaning done. Now really free all the space. */
Packit cdaae3
    rela_free(&dbg->de_debug_info);
Packit cdaae3
    rela_free(&dbg->de_debug_types);
Packit cdaae3
    rela_free(&dbg->de_debug_abbrev);
Packit cdaae3
    rela_free(&dbg->de_debug_line);
Packit cdaae3
    rela_free(&dbg->de_debug_line_str);
Packit cdaae3
    rela_free(&dbg->de_debug_loc);
Packit cdaae3
    rela_free(&dbg->de_debug_aranges);
Packit cdaae3
    rela_free(&dbg->de_debug_macinfo);
Packit cdaae3
    rela_free(&dbg->de_debug_macro);
Packit cdaae3
    rela_free(&dbg->de_debug_names);
Packit cdaae3
    rela_free(&dbg->de_debug_pubnames);
Packit cdaae3
    rela_free(&dbg->de_debug_str);
Packit cdaae3
    rela_free(&dbg->de_debug_sup);
Packit cdaae3
    rela_free(&dbg->de_debug_frame);
Packit cdaae3
    rela_free(&dbg->de_debug_frame_eh_gnu);
Packit cdaae3
    rela_free(&dbg->de_debug_pubtypes);
Packit cdaae3
    rela_free(&dbg->de_debug_funcnames);
Packit cdaae3
    rela_free(&dbg->de_debug_typenames);
Packit cdaae3
    rela_free(&dbg->de_debug_varnames);
Packit cdaae3
    rela_free(&dbg->de_debug_weaknames);
Packit cdaae3
    rela_free(&dbg->de_debug_ranges);
Packit cdaae3
    rela_free(&dbg->de_debug_str_offsets);
Packit cdaae3
    rela_free(&dbg->de_debug_addr);
Packit cdaae3
    rela_free(&dbg->de_debug_gdbindex);
Packit cdaae3
    rela_free(&dbg->de_debug_cu_index);
Packit cdaae3
    rela_free(&dbg->de_debug_tu_index);
Packit cdaae3
    dwarf_harmless_cleanout(&dbg->de_harmless_errors);
Packit cdaae3
Packit cdaae3
    if (dbg->de_printf_callback.dp_buffer &&
Packit cdaae3
        !dbg->de_printf_callback.dp_buffer_user_provided ) {
Packit cdaae3
        free(dbg->de_printf_callback.dp_buffer);
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    _dwarf_destroy_group_map(dbg);
Packit cdaae3
    dwarf_tdestroy(dbg->de_alloc_tree,tdestroy_free_node);
Packit cdaae3
    dbg->de_alloc_tree = 0;
Packit cdaae3
    if (dbg->de_tied_data.td_tied_search) {
Packit cdaae3
        dwarf_tdestroy(dbg->de_tied_data.td_tied_search,
Packit cdaae3
            _dwarf_tied_destroy_free_node);
Packit cdaae3
        dbg->de_tied_data.td_tied_search = 0;
Packit cdaae3
    }
Packit cdaae3
    memset(dbg, 0, sizeof(*dbg)); /* Prevent accidental use later. */
Packit cdaae3
    free(dbg);
Packit cdaae3
    return (DW_DLV_OK);
Packit cdaae3
}
Packit cdaae3
/*  A special case: we have no dbg, no alloc header etc.
Packit cdaae3
    So create something out of thin air that we can recognize
Packit cdaae3
    in dwarf_dealloc.
Packit cdaae3
    Something with the prefix (prefix space hidden from caller).
Packit cdaae3
Packit cdaae3
    Only applies to DW_DLA_ERROR, and  making up an error record.
Packit cdaae3
    The allocated space simply leaks.
Packit cdaae3
*/
Packit cdaae3
struct Dwarf_Error_s *
Packit cdaae3
_dwarf_special_no_dbg_error_malloc(void)
Packit cdaae3
{
Packit cdaae3
    Dwarf_Error e = 0;
Packit cdaae3
    /* The union unused things are to guarantee proper alignment */
Packit cdaae3
    char *mem = malloc(sizeof(struct Dwarf_Error_s));
Packit cdaae3
    if (mem == 0) {
Packit cdaae3
        return 0;
Packit cdaae3
    }
Packit cdaae3
    memset(mem, 0, sizeof(struct Dwarf_Error_s));
Packit cdaae3
    e = (Dwarf_Error)mem;
Packit cdaae3
    e->er_static_alloc = DE_MALLOC;
Packit cdaae3
    return e;
Packit cdaae3
}
Packit cdaae3