223 lines
6.6 KiB
C
Vendored
223 lines
6.6 KiB
C
Vendored
/*
|
|
Copyright (C) 2021 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.
|
|
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <string.h> /* memcmp() */
|
|
#include <stdio.h> /* printf() debugging */
|
|
|
|
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
|
|
#include "stdafx.h"
|
|
#endif /* HAVE_STDAFX_H */
|
|
|
|
#include "dwarf.h"
|
|
#include "libdwarf.h"
|
|
#include "libdwarf_private.h"
|
|
#include "dwarf_base_types.h"
|
|
#include "dwarf_opaque.h"
|
|
#include "dwarf_alloc.h"
|
|
#include "dwarf_error.h"
|
|
#include "dwarf_util.h"
|
|
#include "dwarf_string.h"
|
|
#if 0
|
|
static void
|
|
dump_bytes(const char *msg,int line,
|
|
Dwarf_Small * start, long len)
|
|
{
|
|
Dwarf_Small *end = start + len;
|
|
Dwarf_Small *cur = start;
|
|
printf("%s (0x%lx) line %d\n ",msg,(unsigned long)start,line);
|
|
for (; cur < end; cur++) {
|
|
printf("%02x", *cur);
|
|
}
|
|
printf("\n");
|
|
}
|
|
#endif /*0*/
|
|
|
|
static int
|
|
_dwarf_find_CU_Context_given_sig(Dwarf_Debug dbg,
|
|
int context_level,
|
|
Dwarf_Sig8 *sig_in,
|
|
Dwarf_CU_Context *cu_context_out,
|
|
Dwarf_Bool *is_info_out,
|
|
Dwarf_Error *error)
|
|
{
|
|
Dwarf_CU_Context cu_context = 0;
|
|
Dwarf_Bool is_info = FALSE;
|
|
int loopcount = 0;
|
|
int lres = 0;
|
|
Dwarf_Debug_InfoTypes dis = 0;
|
|
struct Dwarf_Section_s *secdp = 0;
|
|
|
|
/* Loop once with is_info, once with !is_info.
|
|
Then stop. */
|
|
for ( ; loopcount < 2; ++loopcount) {
|
|
Dwarf_CU_Context prev_cu_context = 0;
|
|
Dwarf_Unsigned section_size = 0;
|
|
Dwarf_Unsigned new_cu_offset = 0;
|
|
|
|
is_info = !is_info;
|
|
|
|
if (is_info) {
|
|
dis = &dbg->de_info_reading;
|
|
secdp = &dbg->de_debug_info;
|
|
} else {
|
|
dis = &dbg->de_types_reading;
|
|
secdp = &dbg->de_debug_types;
|
|
}
|
|
lres = _dwarf_load_die_containing_section(dbg,is_info,error);
|
|
if (lres == DW_DLV_ERROR) {
|
|
return lres;
|
|
}
|
|
if (lres == DW_DLV_NO_ENTRY ) {
|
|
continue;
|
|
}
|
|
/* Lets see if we already have the CU we need. */
|
|
for (cu_context = dis->de_cu_context_list;
|
|
cu_context; cu_context = cu_context->cc_next) {
|
|
prev_cu_context = cu_context;
|
|
|
|
if (memcmp(sig_in,&cu_context->cc_signature,
|
|
sizeof(Dwarf_Sig8))) {
|
|
continue;
|
|
}
|
|
if (cu_context->cc_unit_type == DW_UT_split_type||
|
|
cu_context->cc_unit_type == DW_UT_type) {
|
|
*cu_context_out = cu_context;
|
|
*is_info_out = cu_context->cc_is_info;
|
|
return DW_DLV_OK;
|
|
}
|
|
}
|
|
if (context_level > 0) {
|
|
/* Make no attempt to create new context,
|
|
we are finishing cu die base fields
|
|
on one already.
|
|
Just look for the other context,
|
|
DWARF4 debug_types */
|
|
continue;
|
|
}
|
|
if (prev_cu_context) {
|
|
Dwarf_CU_Context lcu_context = prev_cu_context;
|
|
new_cu_offset =
|
|
_dwarf_calculate_next_cu_context_offset(
|
|
lcu_context);
|
|
} else {
|
|
new_cu_offset = 0;
|
|
}
|
|
section_size = secdp->dss_size;
|
|
for ( ; new_cu_offset < section_size;
|
|
new_cu_offset =
|
|
_dwarf_calculate_next_cu_context_offset(
|
|
cu_context)) {
|
|
#if 0
|
|
lres = _dwarf_load_die_containing_section(dbg,
|
|
is_info,error);
|
|
if (lres == DW_DLV_ERROR) {
|
|
return lres;
|
|
}
|
|
if (lres == DW_DLV_NO_ENTRY) {
|
|
continue;
|
|
}
|
|
#endif /*0*/
|
|
lres = _dwarf_create_a_new_cu_context_record_on_list(
|
|
dbg, dis,is_info,section_size,new_cu_offset,
|
|
&cu_context,error);
|
|
if (lres == DW_DLV_ERROR) {
|
|
return lres;
|
|
}
|
|
if (lres == DW_DLV_NO_ENTRY) {
|
|
break;
|
|
}
|
|
if (memcmp(sig_in,&cu_context->cc_signature,
|
|
sizeof(Dwarf_Sig8))) {
|
|
continue;
|
|
}
|
|
if (cu_context->cc_unit_type == DW_UT_split_type||
|
|
cu_context->cc_unit_type == DW_UT_type) {
|
|
*cu_context_out = cu_context;
|
|
*is_info_out = cu_context->cc_is_info;
|
|
return DW_DLV_OK;
|
|
}
|
|
}
|
|
} /* Loop-end. */
|
|
/* Not found */
|
|
return DW_DLV_NO_ENTRY;
|
|
}
|
|
|
|
/* We will search to find a CU with the indicated signature
|
|
The attribute leading us here is often
|
|
We are looking for a DW_UT_split_type or DW_UT_type
|
|
CU.
|
|
DW_AT_type and if DWARF4 that means our first look is
|
|
to !is_info */
|
|
int
|
|
dwarf_find_die_given_sig8(Dwarf_Debug dbg,
|
|
Dwarf_Sig8 *ref,
|
|
Dwarf_Die *die_out,
|
|
Dwarf_Bool *is_info,
|
|
Dwarf_Error *error)
|
|
{
|
|
int res = 0;
|
|
res = _dwarf_internal_find_die_given_sig8(
|
|
dbg,0,ref,die_out,is_info,error);
|
|
return res;
|
|
}
|
|
|
|
/* If context level > 0 restrict what we will do
|
|
to avoid recursion creating CU Contexts */
|
|
int
|
|
_dwarf_internal_find_die_given_sig8(Dwarf_Debug dbg,
|
|
int context_level,
|
|
Dwarf_Sig8 *ref,
|
|
Dwarf_Die *die_out,
|
|
Dwarf_Bool *is_info,
|
|
Dwarf_Error *error)
|
|
{
|
|
int res = 0;
|
|
Dwarf_Die ndi = 0;
|
|
Dwarf_CU_Context context = 0;
|
|
Dwarf_Bool result_is_info = FALSE;
|
|
Dwarf_Unsigned dieoffset = 0;
|
|
|
|
res =_dwarf_find_CU_Context_given_sig(dbg,
|
|
context_level,
|
|
ref, &context, &result_is_info,error);
|
|
if (res != DW_DLV_OK) {
|
|
return res;
|
|
}
|
|
dieoffset = context->cc_debug_offset +
|
|
context->cc_signature_offset;
|
|
res = dwarf_offdie_b(dbg,dieoffset,result_is_info,
|
|
&ndi,error);
|
|
if (res == DW_DLV_OK) {
|
|
*die_out = ndi;
|
|
*is_info = result_is_info;
|
|
}
|
|
return res;
|
|
}
|