/* 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 #include /* memcmp() */ #include /* 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; }