summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdwarf/common/dwarf_dnames.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdwarf/common/dwarf_dnames.c')
-rw-r--r--usr/src/lib/libdwarf/common/dwarf_dnames.c1359
1 files changed, 1359 insertions, 0 deletions
diff --git a/usr/src/lib/libdwarf/common/dwarf_dnames.c b/usr/src/lib/libdwarf/common/dwarf_dnames.c
new file mode 100644
index 0000000000..15276c1fb0
--- /dev/null
+++ b/usr/src/lib/libdwarf/common/dwarf_dnames.c
@@ -0,0 +1,1359 @@
+/*
+ Portions Copyright (C) 2017-2019 David Anderson. 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
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ 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., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+*/
+
+/* This provides access to the DWARF5 .debug_names section. */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include "dwarf_incl.h"
+#include "dwarf_alloc.h"
+#include "dwarf_error.h"
+#include "dwarf_util.h"
+#include "dwarf_global.h"
+#include "dwarf_dnames.h"
+#include "dwarfstring.h"
+
+#define FALSE 0
+#define TRUE 1
+
+/* freedabs attempts to do some cleanup in the face
+ of an error. */
+static void
+freedabs(struct Dwarf_D_Abbrev_s *dab)
+{
+ struct Dwarf_D_Abbrev_s *tmp = 0;
+ for(; dab; dab = tmp) {
+ tmp = dab->da_next;
+ free(dab);
+ }
+}
+
+/* Encapsulates DECODE_LEB128_UWORD_CK
+ so the caller can free resources
+ in case of problems. */
+static int
+read_uword_ab(Dwarf_Small **lp,
+ Dwarf_Unsigned *out_p,
+ Dwarf_Debug dbg,
+ Dwarf_Error *err,
+ Dwarf_Small *lpend)
+
+{
+ Dwarf_Small *inptr = *lp;
+ Dwarf_Unsigned out = 0;
+
+ /* The macro updates inptr */
+ DECODE_LEB128_UWORD_CK(inptr,
+ out, dbg,err,lpend);
+ *lp = inptr;
+ *out_p = out;
+ return DW_DLV_OK;
+}
+
+
+static int
+fill_in_abbrevs_table(struct Dwarf_Dnames_index_header_s * dn,
+ Dwarf_Error * error)
+{
+ Dwarf_Small *abdata = dn->din_abbreviations;
+ Dwarf_Unsigned ablen = dn->din_abbrev_table_size;
+ Dwarf_Small *tabend = abdata+ablen;
+ Dwarf_Small *abcur = 0;
+ Dwarf_Unsigned code = 0;
+ Dwarf_Unsigned tag = 0;
+ int foundabend = FALSE;
+ unsigned abcount = 0;
+ struct Dwarf_D_Abbrev_s *firstdab = 0;
+ struct Dwarf_D_Abbrev_s *lastdab = 0;
+ struct Dwarf_D_Abbrev_s *curdab = 0;
+ Dwarf_Debug dbg = dn->din_dbg;
+
+ for (abcur = abdata; abcur < tabend; ) {
+ Dwarf_Unsigned idx = 0;
+ Dwarf_Unsigned form = 0;
+ Dwarf_Small *inner = 0;
+ unsigned idxcount = 0;
+ int res = 0;
+
+ res = read_uword_ab(&abcur,&code,dbg,error,tabend);
+ if (res != DW_DLV_OK) {
+ freedabs(firstdab);
+ return res;
+ }
+ if (code == 0) {
+ foundabend = TRUE;
+ break;
+ }
+
+ res = read_uword_ab(&abcur,&tag,dbg,error,tabend);
+ if (res != DW_DLV_OK) {
+ freedabs(firstdab);
+ return res;
+ }
+ inner = abcur;
+ curdab = (struct Dwarf_D_Abbrev_s *)calloc(1,
+ sizeof(struct Dwarf_D_Abbrev_s));
+ if(!curdab) {
+ freedabs(firstdab);
+ firstdab = 0;
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return DW_DLV_ERROR;
+ }
+ curdab->da_tag = tag;
+ curdab->da_abbrev_code = code;
+ abcount++;
+ for(;;) {
+ res = read_uword_ab(&inner,&idx,dbg,error,tabend);
+ if (res != DW_DLV_OK) {
+ free(curdab);
+ freedabs(firstdab);
+ firstdab = 0;
+ return res;
+ }
+ res = read_uword_ab(&inner,&form,dbg,error,tabend);
+ if (res != DW_DLV_OK) {
+ free(curdab);
+ freedabs(firstdab);
+ firstdab = 0;
+ return res;
+ }
+ if (!idx && !form) {
+ break;
+ }
+ if (idxcount >= ABB_PAIRS_MAX) {
+ free(curdab);
+ freedabs(firstdab);
+ firstdab = 0;
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_NAMES_ABBREV_OVERFLOW);
+ return DW_DLV_ERROR;
+ }
+ curdab->da_pairs[idxcount].ap_index = idx;
+ curdab->da_pairs[idxcount].ap_form = form;
+ idxcount++;
+ }
+ curdab->da_pairs_count = idxcount;
+ abcur = inner +1;
+ if (!firstdab) {
+ firstdab = curdab;
+ lastdab = curdab;
+ } else {
+ /* Add new on the end, last */
+ lastdab->da_next = curdab;
+ }
+ }
+ if (!foundabend) {
+ freedabs(firstdab);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_NAMES_ABBREV_CORRUPTION);
+ return DW_DLV_OK;
+ }
+ {
+ unsigned ct = 0;
+ struct Dwarf_D_Abbrev_s *tmpa = 0;
+
+ dn->din_abbrev_list = (struct Dwarf_D_Abbrev_s *)calloc(
+ abcount,sizeof(struct Dwarf_D_Abbrev_s));
+ if(!dn->din_abbrev_list) {
+ freedabs(firstdab);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return DW_DLV_ERROR;
+ }
+ dn->din_abbrev_list_count = abcount;
+ tmpa = firstdab;
+ for(ct = 0; tmpa && ct < abcount; ++ct) {
+ struct Dwarf_D_Abbrev_s *tmpb =tmpa->da_next;
+ /* da_next no longer means anything */
+ dn->din_abbrev_list[ct] = *tmpa;
+ dn->din_abbrev_list[ct].da_next = 0;
+ tmpa = tmpb;
+ }
+ freedabs(firstdab);
+ tmpa = 0;
+ firstdab = 0;
+ lastdab = 0;
+ /* Now the list has turned into an array. We can ignore
+ the list aspect. */
+ }
+ return DW_DLV_OK;
+}
+
+static int
+get_inhdr_cur(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ struct Dwarf_Dnames_index_header_s **cur,
+ Dwarf_Error *error)
+{
+ Dwarf_Debug dbg = 0;
+
+ if (!dn) {
+ _dwarf_error(NULL, error,DW_DLE_DEBUG_NAMES_NULL_POINTER);
+ return DW_DLV_ERROR;
+ }
+ dbg = dn->dn_dbg;
+ if (index_number >= dn->dn_inhdr_count) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_NAMES_BAD_INDEX_ARG);
+ return DW_DLV_ERROR;
+ }
+ *cur = dn->dn_inhdr_first + index_number;
+ return DW_DLV_OK;
+}
+
+
+static int
+read_uword_val(Dwarf_Debug dbg,
+ Dwarf_Small **ptr_in,
+ Dwarf_Small *endptr,
+ int errcode,
+ Dwarf_Unsigned *val_out,
+ Dwarf_Unsigned area_length,
+ Dwarf_Error *error)
+{
+ Dwarf_Unsigned val = 0;
+ Dwarf_Small *ptr = *ptr_in;
+
+ READ_UNALIGNED_CK(dbg, val, Dwarf_Unsigned,
+ ptr, DWARF_32BIT_SIZE,
+ error,endptr);
+ ptr += DWARF_32BIT_SIZE;
+ if (ptr >= endptr) {
+ _dwarf_error(dbg, error,errcode);
+ return DW_DLV_ERROR;
+ }
+ /* Some of the fields are not length fields, but
+ if non-zero the size will be longer than
+ the value, so we do the following
+ overall sanity check to avoid overflows. */
+ if (val > area_length) {
+ _dwarf_error(dbg, error,errcode);
+ return DW_DLV_ERROR;
+ }
+ *val_out = val;
+ *ptr_in = ptr;
+ return DW_DLV_OK;
+}
+
+/* We do not alter the dn data here. */
+static int
+read_a_name_index(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned section_offset,
+ Dwarf_Small **curptr_in,
+ Dwarf_Small *end_section,
+ Dwarf_Unsigned remaining_section_size,
+ struct Dwarf_Dnames_index_header_s ** index_header_out,
+ Dwarf_Error *error)
+{
+ Dwarf_Unsigned area_length = 0;
+ int local_length_size;
+ int local_extension_size = 0;
+ Dwarf_Small *past_length = 0;
+ Dwarf_Small *end_dnames = 0;
+ Dwarf_Half version = 0;
+ Dwarf_Half padding = 0;
+ Dwarf_Unsigned comp_unit_count = 0;
+ Dwarf_Unsigned local_type_unit_count = 0;
+ Dwarf_Unsigned foreign_type_unit_count = 0;
+ Dwarf_Unsigned bucket_count = 0;
+ Dwarf_Unsigned name_count = 0;
+ Dwarf_Unsigned abbrev_table_size = 0; /* bytes */
+ Dwarf_Unsigned augmentation_string_size = 0; /* bytes */
+ int res = 0;
+ const char *str_utf8 = 0;
+ Dwarf_Small *curptr = *curptr_in;
+ struct Dwarf_Dnames_index_header_s *di_header = 0;
+ Dwarf_Debug dbg = dn->dn_dbg;
+
+ READ_AREA_LENGTH_CK(dbg, area_length, Dwarf_Unsigned,
+ curptr, local_length_size,
+ local_extension_size,error,
+ remaining_section_size,end_section);
+
+ /* curptr now points past the length field */
+ past_length = curptr;
+
+ /* Two stage length test so overflow is caught. */
+ if (area_length > remaining_section_size) {
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+ if ((area_length + local_length_size + local_extension_size) >
+ remaining_section_size) {
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+ end_dnames = curptr + area_length;
+
+ READ_UNALIGNED_CK(dbg, version, Dwarf_Half,
+ curptr, DWARF_HALF_SIZE,
+ error,end_dnames);
+ curptr += DWARF_HALF_SIZE;
+ if (curptr >= end_dnames) {
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+ if (version != DWARF_DNAMES_VERSION5) {
+ _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ READ_UNALIGNED_CK(dbg, padding, Dwarf_Half,
+ curptr, DWARF_HALF_SIZE,
+ error,end_dnames);
+ curptr += DWARF_HALF_SIZE;
+ if (curptr >= end_dnames) {
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+ if (padding) {
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ res = read_uword_val(dbg, &curptr,
+ end_dnames, DW_DLE_DEBUG_NAMES_HEADER_ERROR,
+ &comp_unit_count,area_length,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = read_uword_val(dbg, &curptr,
+ end_dnames, DW_DLE_DEBUG_NAMES_HEADER_ERROR,
+ &local_type_unit_count,area_length,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = read_uword_val(dbg, &curptr,
+ end_dnames, DW_DLE_DEBUG_NAMES_HEADER_ERROR,
+ &foreign_type_unit_count,area_length,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = read_uword_val(dbg, &curptr,
+ end_dnames, DW_DLE_DEBUG_NAMES_HEADER_ERROR,
+ &bucket_count,area_length,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = read_uword_val(dbg, &curptr,
+ end_dnames, DW_DLE_DEBUG_NAMES_HEADER_ERROR,
+ &name_count,area_length,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ res = read_uword_val(dbg, &curptr,
+ end_dnames, DW_DLE_DEBUG_NAMES_HEADER_ERROR,
+ &abbrev_table_size,area_length,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = read_uword_val(dbg, &curptr,
+ end_dnames, DW_DLE_DEBUG_NAMES_HEADER_ERROR,
+ &augmentation_string_size,area_length,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ str_utf8 = (const char *) curptr;
+
+ curptr+= augmentation_string_size;
+ if (curptr >= end_dnames) {
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+
+ di_header = (struct Dwarf_Dnames_index_header_s *)
+ calloc(1,sizeof(*di_header));
+ if(!di_header) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ di_header->din_dbg = dbg;
+ di_header->din_section_offset = section_offset;
+ di_header->din_indextable_data = past_length;
+ di_header->din_indextable_length = area_length;
+ di_header->din_version = version;
+ di_header->din_comp_unit_count = comp_unit_count;
+ di_header->din_local_type_unit_count = local_type_unit_count ;
+ di_header->din_foreign_type_unit_count = foreign_type_unit_count ;
+ di_header->din_bucket_count = bucket_count ;
+ di_header->din_name_count = name_count ;
+ di_header->din_abbrev_table_size = abbrev_table_size;
+ di_header->din_augmentation_string_size = augmentation_string_size;
+ di_header->din_augmentation_string = calloc(1,
+ augmentation_string_size +1);
+ strncpy(di_header->din_augmentation_string,str_utf8,
+ augmentation_string_size);
+
+ {
+ /* This deals with a zero length string too. */
+ Dwarf_Unsigned len = augmentation_string_size;
+ char *cp = 0;
+ char *cpend = 0;
+ Dwarf_Bool foundnull = FALSE;
+
+ cp = di_header->din_augmentation_string;
+ cpend = cp + len;
+ for( ; cp<cpend; ++cp) {
+ if (!*cp) {
+ foundnull = TRUE;
+ break;
+ }
+ }
+ if (!foundnull) {
+ /* Force a NUL terminator in the extra byte
+ we calloc-d. */
+ cp[len] = 0;
+ } else {
+ /* Ensure that there is no corruption in
+ the padding. */
+ for( ; cp < cpend; ++cp) {
+ if(*cp) {
+ free(di_header);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_NAMES_PAD_NON_ZERO);
+ return DW_DLV_ERROR;
+ }
+ }
+ }
+ }
+ di_header->din_cu_list = curptr;
+ curptr += dbg->de_length_size * comp_unit_count;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+ di_header->din_local_tu_list = curptr;
+
+ curptr += dbg->de_length_size * local_type_unit_count;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+ di_header->din_foreign_tu_list = curptr;
+ curptr += sizeof(Dwarf_Sig8) * foreign_type_unit_count;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+
+ di_header->din_buckets = curptr;
+ curptr += DWARF_32BIT_SIZE * bucket_count;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+
+ di_header->din_hash_table = curptr;
+ curptr += sizeof(Dwarf_Sig8) * name_count;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+
+ di_header->din_string_offsets = curptr;
+ curptr += DWARF_32BIT_SIZE * name_count;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+
+ di_header->din_entry_offsets = curptr;
+ curptr += DWARF_32BIT_SIZE * name_count;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+ di_header->din_abbreviations = curptr;
+ curptr += abbrev_table_size;
+ if(curptr > end_dnames) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_HEADER_ERROR);
+ return DW_DLV_ERROR;
+ }
+
+ di_header->din_entry_pool = curptr;
+ di_header->din_offset_size = local_length_size;
+
+ di_header->din_entry_pool_size = end_dnames - curptr;
+
+ *curptr_in = curptr;
+ *index_header_out = di_header;
+ res = fill_in_abbrevs_table(di_header,error);
+ if (res != DW_DLV_OK) {
+ free(di_header->din_augmentation_string);
+ free(di_header);
+ return res;
+ }
+ return DW_DLV_OK;
+}
+
+#define FAKE_LAST_USED 0xffffffff
+
+static void
+free_inhdr_content(struct Dwarf_Dnames_index_header_s *f)
+{
+ free(f->din_augmentation_string);
+ free(f->din_abbrev_list);
+}
+static void
+free_inhdr_list(struct Dwarf_Dnames_index_header_s *f)
+{
+ struct Dwarf_Dnames_index_header_s *tmp = 0;
+
+ for( ; f ; f = tmp) {
+ tmp = f->din_next;
+ free_inhdr_content(f);
+ free(f);
+ }
+}
+
+/* There may be one debug index for an entire object file,
+ for multiple CUs or there can be individual indexes
+ for some CUs.
+ see DWARF5 6.1.1.3 Per_CU versus Per-Module Indexes. */
+int
+dwarf_debugnames_header(Dwarf_Debug dbg,
+ Dwarf_Dnames_Head * dn_out,
+ Dwarf_Unsigned * dn_count_out,
+ Dwarf_Error *error)
+{
+ Dwarf_Unsigned remaining = 0;
+ Dwarf_Dnames_Head dn_header = 0;
+ Dwarf_Unsigned section_size;
+ Dwarf_Small *start_section = 0;
+ Dwarf_Small *end_section = 0;
+ Dwarf_Small *curptr = 0;
+ struct Dwarf_Dnames_index_header_s *inhdr_last = 0;
+ struct Dwarf_Dnames_index_header_s *inhdr_first = 0;
+ unsigned inhdr_count = 0;
+ int res = 0;
+
+ if(!dbg) {
+ _dwarf_error(dbg, error,DW_DLE_DBG_NULL);
+ return DW_DLV_ERROR;
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_names, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ section_size = dbg->de_debug_names.dss_size;
+ if(!section_size){
+ return DW_DLV_NO_ENTRY;
+ }
+ start_section = dbg->de_debug_names.dss_data;
+ curptr = start_section;
+ end_section = start_section + section_size;
+ remaining = section_size;
+ dn_header = (Dwarf_Dnames_Head)_dwarf_get_alloc(dbg,
+ DW_DLA_DNAMES_HEAD, 1);
+ if(!dn_header) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return DW_DLV_ERROR;
+ }
+ dn_header->dn_section_data = start_section;
+ dn_header->dn_section_size = section_size;
+ dn_header->dn_section_end = start_section + section_size;
+ dn_header->dn_dbg = dbg;
+ for( ; curptr < end_section; ) {
+ struct Dwarf_Dnames_index_header_s * index_header = 0;
+ Dwarf_Small *curptr_start = curptr;
+ Dwarf_Unsigned usedspace = 0;
+ Dwarf_Unsigned section_offset = curptr - start_section;
+
+ res = read_a_name_index(dn_header,
+ section_offset,
+ &curptr,
+ end_section,
+ remaining,
+ &index_header,
+ error);
+ if (res == DW_DLV_ERROR) {
+ free_inhdr_list(inhdr_first);
+ dwarf_dealloc(dbg,dn_header,DW_DLA_DNAMES_HEAD);
+ return res;
+ }
+ if (res == DW_DLV_NO_ENTRY) {
+ /* Impossible. A bug. Or possibly
+ a bunch of zero pad? */
+ free_inhdr_list(inhdr_first);
+ dwarf_dealloc(dbg,dn_header,DW_DLA_DNAMES_HEAD);
+ break;
+ }
+ /* Add the new one to the list. */
+ if(!inhdr_first) {
+ inhdr_count = 1;
+ inhdr_first = index_header;
+ inhdr_last = index_header;
+ } else {
+ struct Dwarf_Dnames_index_header_s *tmp = inhdr_last;
+ inhdr_last = index_header;
+ tmp->din_next = index_header;
+ inhdr_count++;
+ }
+ usedspace = curptr - curptr_start;
+ remaining -= - usedspace;
+ if (remaining < 5) {
+ /* No more in here, just padding. Check for zero
+ in padding. */
+ if ((curptr +remaining) < end_section) {
+ free_inhdr_list(inhdr_first);
+ dwarf_dealloc(dbg,dn_header,DW_DLA_DNAMES_HEAD);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_OFF_END);
+ return DW_DLV_ERROR;
+ }
+ for ( ; curptr < end_section; ++curptr) {
+ if(*curptr) {
+ /* One could argue this is a harmless error,
+ but for now assume it is real corruption. */
+ free_inhdr_list(inhdr_first);
+ dwarf_dealloc(dbg,dn_header,DW_DLA_DNAMES_HEAD);
+ _dwarf_error(dbg, error,DW_DLE_DEBUG_NAMES_PAD_NON_ZERO);
+ return DW_DLV_ERROR;
+ }
+ }
+ }
+ }
+ {
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ int n = 0;
+
+ dn_header->dn_inhdr_first =
+ (struct Dwarf_Dnames_index_header_s *)
+ calloc(inhdr_count,sizeof(struct Dwarf_Dnames_index_header_s));
+ for(n = 0,cur = inhdr_first; cur; ++n ) {
+ /* We are copying these structs so do not
+ free them at this time. */
+ struct Dwarf_Dnames_index_header_s *tmp = cur->din_next;
+ dn_header->dn_inhdr_first[n] = *cur;
+ cur = tmp;
+ }
+ }
+ *dn_out = dn_header;
+ *dn_count_out = inhdr_count;
+ return DW_DLV_OK;
+}
+
+
+int dwarf_debugnames_sizes(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+
+ Dwarf_Unsigned * section_offset,
+ Dwarf_Unsigned * version, /* 5 */
+ Dwarf_Unsigned * offset_size, /* 4 or 8 */
+
+ /* The counts are entry counts, not bye sizes. */
+ Dwarf_Unsigned * comp_unit_count,
+ Dwarf_Unsigned * local_type_unit_count,
+ Dwarf_Unsigned * foreign_type_unit_count,
+ Dwarf_Unsigned * bucket_count,
+ Dwarf_Unsigned * name_count,
+
+ /* The following are counted in bytes */
+ Dwarf_Unsigned * indextable_overall_length,
+ Dwarf_Unsigned * abbrev_table_size,
+ Dwarf_Unsigned * entry_pool_size,
+ Dwarf_Unsigned * augmentation_string_size,
+
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ int res = 0;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+
+ if (section_offset) {
+ *section_offset = cur->din_section_offset;
+ }
+ if (version) {
+ *version = cur->din_version;
+ }
+ if (offset_size) {
+ *offset_size = cur->din_offset_size;
+ }
+ if (comp_unit_count) {
+ *comp_unit_count = cur->din_comp_unit_count;
+ }
+ if (local_type_unit_count) {
+ *local_type_unit_count = cur->din_local_type_unit_count;
+ }
+ if (foreign_type_unit_count) {
+ *foreign_type_unit_count = cur->din_foreign_type_unit_count;
+ }
+ if (bucket_count) {
+ *bucket_count = cur->din_bucket_count;
+ }
+ if (name_count) {
+ *name_count = cur->din_name_count;
+ }
+ if (abbrev_table_size) {
+ *abbrev_table_size = cur->din_abbrev_table_size;
+ }
+ if (entry_pool_size) {
+ *entry_pool_size = cur->din_entry_pool_size;
+ }
+ if (augmentation_string_size) {
+ *augmentation_string_size = cur->din_augmentation_string_size;
+ }
+ if (indextable_overall_length) {
+ *indextable_overall_length = cur->din_indextable_length;
+ }
+ return DW_DLV_OK;
+}
+
+int
+dwarf_debugnames_cu_entry(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned offset_number,
+ Dwarf_Unsigned * offset_count,
+ Dwarf_Unsigned * offset,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ Dwarf_Debug dbg = 0;
+ int res;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ dbg = dn->dn_dbg;
+
+ if (offset_number >= cur->din_comp_unit_count) {
+ if (offset_count) {
+ *offset_count = cur->din_comp_unit_count;
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+
+
+ if (offset) {
+ Dwarf_Unsigned offsetval = 0;
+ Dwarf_Small *ptr = cur->din_cu_list +
+ offset_number *cur->din_offset_size;
+ Dwarf_Small *endptr = cur->din_local_tu_list;
+
+ READ_UNALIGNED_CK(dbg, offsetval, Dwarf_Unsigned,
+ ptr, cur->din_offset_size,
+ error,endptr);
+ *offset = offsetval;
+ }
+ if (offset_count) {
+ *offset_count = cur->din_comp_unit_count;
+ }
+ return DW_DLV_OK;
+}
+
+int
+dwarf_debugnames_local_tu_entry(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned offset_number,
+ Dwarf_Unsigned * offset_count,
+ Dwarf_Unsigned * offset,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ Dwarf_Debug dbg = 0;
+ int res;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ dbg = dn->dn_dbg;
+
+ if (offset_number >= cur->din_local_type_unit_count) {
+ if (offset_count) {
+ *offset_count = cur->din_local_type_unit_count;
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+
+
+ if (offset) {
+ Dwarf_Unsigned offsetval = 0;
+ Dwarf_Small *ptr = cur->din_local_tu_list +
+ offset_number *cur->din_offset_size;
+ Dwarf_Small *endptr = cur->din_foreign_tu_list;
+
+ READ_UNALIGNED_CK(dbg, offsetval, Dwarf_Unsigned,
+ ptr, cur->din_offset_size,
+ error,endptr);
+ *offset = offsetval;
+ }
+ if (offset_count) {
+ *offset_count = cur->din_local_type_unit_count;
+ }
+ return DW_DLV_OK;
+}
+
+
+
+/* Here the sig_number ranges from
+ local_type_unit_count to
+ local_type_unit_count+foreign_type_unit_count-1
+ because the foreign indices are a continuation
+ of the local tu indices.
+*/
+int
+dwarf_debugnames_foreign_tu_entry(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned sig_number,
+
+ /* these index starting at local_type_unit_count */
+ Dwarf_Unsigned * sig_minimum,
+ Dwarf_Unsigned * sig_count,
+ Dwarf_Sig8 * signature,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ Dwarf_Debug dbg = 0;
+ int res;
+ unsigned legal_low = 0;
+ unsigned legal_high = 0;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ dbg = dn->dn_dbg;
+ legal_low = cur->din_local_type_unit_count;
+ legal_high = legal_low + cur->din_foreign_type_unit_count;
+ if (sig_number < legal_low) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_NAMES_BAD_INDEX_ARG);
+ return DW_DLV_ERROR;
+ }
+ if (sig_number >= legal_high) {
+ if (sig_minimum) {
+ *sig_minimum = legal_low;
+ }
+ if (sig_count) {
+ *sig_count = cur->din_foreign_type_unit_count;
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+
+ if (signature) {
+ Dwarf_Small *ptr = cur->din_foreign_tu_list +
+ sig_number *cur->din_offset_size;
+ Dwarf_Small *endptr = cur->din_hash_table;
+ if((ptr +sizeof(Dwarf_Sig8)) > endptr) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_NAMES_BAD_INDEX_ARG);
+ return DW_DLV_ERROR;
+ }
+ memcpy(signature,ptr,sizeof(Dwarf_Sig8));
+ }
+ if (sig_minimum) {
+ *sig_minimum = legal_low;
+ }
+ if (sig_count) {
+ *sig_count = cur->din_foreign_type_unit_count;
+ }
+ return DW_DLV_OK;
+}
+
+/* The hash table is composed of the buckets table
+ and the hashes table.
+ If there is no buckets table (bucket_count == 0)
+ the hashes part still exists. */
+int dwarf_debugnames_bucket(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned bucket_number,
+ Dwarf_Unsigned * bucket_count,
+ Dwarf_Unsigned * index_of_name_entry,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ Dwarf_Debug dbg = 0;
+ int res;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ dbg = dn->dn_dbg;
+
+ if (bucket_number >= cur->din_bucket_count) {
+ if (bucket_count) {
+ *bucket_count = cur->din_bucket_count;
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+
+ if (index_of_name_entry) {
+ Dwarf_Unsigned offsetval = 0;
+ Dwarf_Small *ptr = cur->din_buckets +
+ bucket_number * DWARF_32BIT_SIZE;
+ Dwarf_Small *endptr = cur->din_hash_table;
+
+ READ_UNALIGNED_CK(dbg, offsetval, Dwarf_Unsigned,
+ ptr, DWARF_32BIT_SIZE,
+ error,endptr);
+ *index_of_name_entry = offsetval;
+ }
+ if (bucket_count) {
+ *bucket_count = cur->din_bucket_count;
+ }
+ return DW_DLV_OK;
+}
+
+/* Access to the .debug_names name table. */
+int
+dwarf_debugnames_name(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned name_entry,
+ Dwarf_Unsigned * names_count,
+ Dwarf_Sig8 * signature,
+ Dwarf_Unsigned * offset_to_debug_str,
+ Dwarf_Unsigned * offset_in_entrypool,
+ Dwarf_Error * error)
+
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ Dwarf_Debug dbg = 0;
+ int res;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ dbg = dn->dn_dbg;
+
+ if (name_entry >= cur->din_name_count) {
+ if (names_count) {
+ *names_count = cur->din_bucket_count;
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+
+ if (signature) {
+ Dwarf_Small *ptr = cur->din_hash_table +
+ name_entry *sizeof(Dwarf_Sig8);
+ Dwarf_Small *endptr = cur->din_string_offsets;
+ if ((ptr + sizeof(Dwarf_Sig8)) > endptr) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_NAMES_BAD_INDEX_ARG);
+ return DW_DLV_ERROR;
+ }
+ memcpy(signature,ptr,sizeof(Dwarf_Sig8));
+ }
+
+ if (offset_to_debug_str) {
+ Dwarf_Unsigned offsetval = 0;
+ Dwarf_Small *ptr = cur->din_string_offsets +
+ name_entry * DWARF_32BIT_SIZE;
+ Dwarf_Small *endptr = cur->din_abbreviations;
+
+ READ_UNALIGNED_CK(dbg, offsetval, Dwarf_Unsigned,
+ ptr, DWARF_32BIT_SIZE,
+ error,endptr);
+ *offset_to_debug_str = offsetval;
+ }
+ if (offset_in_entrypool) {
+ Dwarf_Unsigned offsetval = 0;
+ Dwarf_Small *ptr = cur->din_entry_offsets +
+ name_entry * DWARF_32BIT_SIZE;
+ Dwarf_Small *endptr = cur->din_abbreviations;
+
+ READ_UNALIGNED_CK(dbg, offsetval, Dwarf_Unsigned,
+ ptr, DWARF_32BIT_SIZE,
+ error,endptr);
+ *offset_in_entrypool = offsetval;
+ }
+
+ if (names_count) {
+ *names_count = cur->din_name_count;
+ }
+ return DW_DLV_OK;
+}
+
+
+
+
+
+
+/* If abbrev_code returned is zero there is no tag returned
+ and we are at the end of the entry pool set for this name
+ entry.
+ abbrev code, tag
+ nameindexattr,form
+ ...
+ 0,0
+ ... repeat like the above
+ 0
+*/
+
+/* This provides a way to print the abbrev table by
+ indexing from 0. */
+int
+dwarf_debugnames_abbrev_by_index(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned abbrev_entry,
+ Dwarf_Unsigned * abbrev_code,
+ Dwarf_Unsigned * tag,
+
+ /* The number of valid abbrev_entry values: 0 to number_of_abbrev-1
+ */
+ Dwarf_Unsigned * number_of_abbrev,
+
+ /* The number of attr/form pairs, not counting the trailing
+ 0,0 pair. */
+ Dwarf_Unsigned * number_of_attr_form_entries,
+ Dwarf_Error *error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ struct Dwarf_D_Abbrev_s * abbrev = 0;
+ int res = 0;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ if (abbrev_entry >= cur->din_abbrev_list_count) {
+ if (number_of_abbrev) {
+ *number_of_abbrev = cur->din_abbrev_list_count;
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+ abbrev = cur->din_abbrev_list + abbrev_entry;
+ if(abbrev_code) {
+ *abbrev_code = abbrev->da_abbrev_code;
+ }
+ if(tag) {
+ *tag = abbrev->da_tag;
+ }
+ if(number_of_abbrev) {
+ *number_of_abbrev = cur->din_abbrev_list_count;
+ }
+ if(number_of_attr_form_entries) {
+ *number_of_attr_form_entries = abbrev->da_pairs_count;
+ }
+ return DW_DLV_OK;
+}
+
+static int
+_dwarf_internal_abbrev_by_code(struct Dwarf_Dnames_index_header_s *cur,
+ Dwarf_Unsigned abbrev_code,
+ Dwarf_Unsigned * tag,
+ Dwarf_Unsigned * index_of_abbrev,
+ Dwarf_Unsigned * number_of_attr_form_entries)
+{
+ unsigned n = 0;
+ struct Dwarf_D_Abbrev_s * abbrev = 0;
+
+ abbrev = cur->din_abbrev_list;
+ for(n = 0; n < cur->din_abbrev_list_count; ++n,++abbrev) {
+ if (abbrev_code == abbrev->da_abbrev_code) {
+ if (tag) {
+ *tag = abbrev->da_tag;
+ }
+ if (index_of_abbrev) {
+ *index_of_abbrev = n;
+ }
+ if (number_of_attr_form_entries) {
+ *number_of_attr_form_entries = abbrev->da_pairs_count;
+ }
+ return DW_DLV_OK;
+ }
+ }
+ /* Something is wrong, not found! */
+ return DW_DLV_NO_ENTRY;
+
+}
+
+/* Access the abbrev by abbrev code (instead of index). */
+int
+dwarf_debugnames_abbrev_by_code(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned abbrev_code,
+ Dwarf_Unsigned * tag,
+
+ /* The number of this code/tag as an array index. */
+ Dwarf_Unsigned * index_of_abbrev,
+
+ /* The number of attr/form pairs, not counting the trailing
+ 0,0 pair. */
+ Dwarf_Unsigned * number_of_attr_form_entries,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ int res;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = _dwarf_internal_abbrev_by_code(cur,
+ abbrev_code,
+ tag, index_of_abbrev,
+ number_of_attr_form_entries);
+ return res;
+}
+
+
+int
+dwarf_debugnames_abbrev_form_by_index(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned abbrev_entry_index,
+ Dwarf_Unsigned abbrev_form_index,
+ Dwarf_Unsigned * name_index_attr,
+ Dwarf_Unsigned * form,
+ Dwarf_Unsigned * number_of_attr_form_entries,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ struct Dwarf_D_Abbrev_s * abbrev = 0;
+ struct abbrev_pair_s *ap = 0;
+ int res;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ if (abbrev_entry_index >= cur->din_abbrev_list_count) {
+ if (number_of_attr_form_entries) {
+ *number_of_attr_form_entries = cur->din_bucket_count;
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+ abbrev = cur->din_abbrev_list + abbrev_entry_index;
+ if (abbrev_form_index >= abbrev->da_pairs_count) {
+ return DW_DLV_NO_ENTRY;
+ }
+ ap = abbrev->da_pairs + abbrev_entry_index;
+ if(name_index_attr) {
+ *name_index_attr = ap->ap_index;
+ }
+ if(form) {
+ *form = ap->ap_form;
+ }
+ if(number_of_attr_form_entries) {
+ *number_of_attr_form_entries = abbrev->da_pairs_count;
+ }
+ return DW_DLV_OK;
+}
+
+/* This, combined with dwarf_debugnames_entrypool_values(),
+ lets one examine as much or as little of an entrypool
+ as one wants to by alternately calling these two
+ functions. */
+
+int dwarf_debugnames_entrypool(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned offset_in_entrypool,
+ Dwarf_Unsigned * abbrev_code,
+ Dwarf_Unsigned * tag,
+ Dwarf_Unsigned * value_count,
+ Dwarf_Unsigned * index_of_abbrev,
+ Dwarf_Unsigned * offset_of_initial_value,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ Dwarf_Debug dbg = 0;
+ int res = 0;
+ Dwarf_Small *entrypool = 0;
+ Dwarf_Small *endentrypool = 0;
+ Dwarf_Unsigned abcode = 0;
+ Dwarf_Unsigned leblen = 0;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ dbg = dn->dn_dbg;
+
+ if (offset_in_entrypool >= cur->din_entry_pool_size) {
+ _dwarf_error(NULL, error,DW_DLE_DEBUG_NAMES_ENTRYPOOL_OFFSET);
+ return DW_DLV_ERROR;
+ }
+ endentrypool = cur->din_entry_pool +cur->din_entry_pool_size;
+ entrypool = cur->din_entry_pool + offset_in_entrypool;
+
+ DECODE_LEB128_UWORD_LEN_CK(entrypool,abcode,leblen,
+ dbg,error,endentrypool);
+
+ res = _dwarf_internal_abbrev_by_code(cur,
+ abcode,
+ tag, index_of_abbrev,
+ value_count);
+ if (res != DW_DLV_OK) {
+ /* Never DW_DLV_ERROR (so far) */
+ return res;
+ }
+ *offset_of_initial_value = offset_in_entrypool + leblen;
+ *abbrev_code = abcode;
+ return DW_DLV_OK;
+}
+
+
+/* Caller, knowing array size needed, passes in arrays
+ it allocates of for idx, form, offset-size-values,
+ and signature values. Caller must examine idx-number
+ and form to decide, for each array element, whether
+ the offset or the signature contains the value.
+ So this returns all the values for the abbrev code.
+ And points via offset_of_next to the next abbrev code.
+
+ While an array of structs would be easier for the caller
+ to allocate than parallel arrays, public structs have
+ turned out to be difficult to work with as interfaces
+ (as formats change over time).
+ */
+int dwarf_debugnames_entrypool_values(Dwarf_Dnames_Head dn,
+ Dwarf_Unsigned index_number,
+ Dwarf_Unsigned index_of_abbrev,
+ Dwarf_Unsigned offset_in_entrypool_of_values,
+ Dwarf_Unsigned * array_dw_idx_number,
+ Dwarf_Unsigned * array_form,
+ Dwarf_Unsigned * array_of_offsets,
+ Dwarf_Sig8 * array_of_signatures,
+
+ /* offset of the next entrypool entry. */
+ Dwarf_Unsigned * offset_of_next_entrypool,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ struct Dwarf_D_Abbrev_s * abbrev = 0;
+ Dwarf_Debug dbg = 0;
+ unsigned n = 0;
+ int res = 0;
+ Dwarf_Unsigned abcount = 0;
+ Dwarf_Unsigned pooloffset = offset_in_entrypool_of_values;
+ Dwarf_Small * endpool = 0;
+ Dwarf_Small * poolptr = 0;
+
+ res = get_inhdr_cur(dn,index_number,&cur,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ dbg = dn->dn_dbg;
+ endpool = cur->din_entry_pool + cur->din_entry_pool_size;
+
+ if (index_of_abbrev >= cur->din_abbrev_list_count) {
+ _dwarf_error(dbg,error,DW_DLE_DEBUG_NAMES_ABBREV_CORRUPTION);
+ return DW_DLV_ERROR;
+ }
+ poolptr = cur->din_entry_pool + offset_in_entrypool_of_values;
+ abbrev = cur->din_abbrev_list + index_of_abbrev;
+ abcount = cur->din_abbrev_list_count;
+ for(n = 0; n < abcount ; ++n) {
+ struct abbrev_pair_s *abp = abbrev->da_pairs +n;
+ unsigned idxtype = abp->ap_index;
+ unsigned form = abp->ap_form;
+ array_dw_idx_number[n] = idxtype;
+ array_form[n] = form;
+
+ if(form == DW_FORM_data8 && idxtype == DW_IDX_type_hash) {
+ if ((poolptr + sizeof(Dwarf_Sig8)) > endpool){
+ _dwarf_error(dbg,error,
+ DW_DLE_DEBUG_NAMES_ENTRYPOOL_OFFSET);
+ return DW_DLV_ERROR;
+ }
+ memcpy(array_of_signatures+n,
+ poolptr,sizeof(Dwarf_Sig8));
+ poolptr += sizeof(Dwarf_Sig8);
+ pooloffset += sizeof(Dwarf_Sig8);
+ continue;
+ } else if (_dwarf_allow_formudata(form)) {
+ Dwarf_Unsigned val = 0;
+ Dwarf_Unsigned bytesread = 0;
+ res = _dwarf_formudata_internal(dbg,form,poolptr,
+ endpool,&val,&bytesread,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ poolptr += bytesread;
+ pooloffset += bytesread;
+ array_of_offsets[n] = val;
+ continue;
+ }
+ /* There is some mistake/omission in our code here or in
+ the data. */
+ {
+ dwarfstring m;
+ const char *name = "<unknown form>";
+
+ dwarfstring_constructor(&m);
+ dwarfstring_append_printf_u(&m,
+ "DW_DLE_DEBUG_NAMES_UNHANDLED_FORM: Form 0x%x",
+ form);
+ dwarf_get_FORM_name(form,&name);
+ dwarfstring_append_printf_s(&m,
+ " %s is not currently supported in .debug_names ",
+ (char *)name);
+ _dwarf_error_string(dbg,error,
+ DW_DLE_DEBUG_NAMES_UNHANDLED_FORM,
+ dwarfstring_string(&m));
+ dwarfstring_destructor(&m);
+ }
+ return DW_DLV_ERROR;
+ }
+ *offset_of_next_entrypool = pooloffset;
+ return DW_DLV_OK;
+}
+
+
+
+
+/* Frees any Dwarf_Dnames_Head_s data that is directly
+ mallocd. */
+void
+_dwarf_debugnames_destructor(void *m)
+{
+ struct Dwarf_Dnames_Head_s *h = (struct Dwarf_Dnames_Head_s *)m;
+
+ struct Dwarf_Dnames_index_header_s *cur = 0;
+ unsigned n = 0;
+
+ cur = h->dn_inhdr_first;
+ for( ;n < h->dn_inhdr_count ; ++n,++cur) {
+ free_inhdr_content(cur);
+ }
+ free(h->dn_inhdr_first);
+ h->dn_inhdr_first = 0;
+ h->dn_inhdr_count = 0;
+}