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