int dwarf_offdie_b(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Bool is_info, Dwarf_Die * new_die, Dwarf_Error * error) { Dwarf_CU_Context cu_context = 0; Dwarf_Off new_cu_offset = 0; Dwarf_Die die = 0; Dwarf_Byte_Ptr info_ptr = 0; Dwarf_Unsigned abbrev_code = 0; Dwarf_Unsigned utmp = 0; Dwarf_Debug_InfoTypes dis = 0; if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } dis = is_info? &dbg->de_info_reading: &dbg->de_types_reading; cu_context = _dwarf_find_CU_Context(dbg, offset,is_info); if (cu_context == NULL) cu_context = _dwarf_find_offdie_CU_Context(dbg, offset,is_info); if (cu_context == NULL) { Dwarf_Unsigned section_size = is_info? dbg->de_debug_info.dss_size: dbg->de_debug_types.dss_size; int res = is_info?_dwarf_load_debug_info(dbg, error): _dwarf_load_debug_types(dbg,error); if (res != DW_DLV_OK) { return res; } if (dis->de_offdie_cu_context_end != NULL) { Dwarf_CU_Context lcu_context = dis->de_offdie_cu_context_end; new_cu_offset = lcu_context->cc_debug_offset + lcu_context->cc_length + lcu_context->cc_length_size + lcu_context->cc_extension_size; } do { if ((new_cu_offset + _dwarf_length_of_cu_header_simple(dbg,is_info)) >= section_size) { _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD); return (DW_DLV_ERROR); } cu_context = _dwarf_make_CU_Context(dbg, new_cu_offset,is_info, error); if (cu_context == NULL) { /* Error if CU Context could not be made. Since _dwarf_make_CU_Context has already registered an error we do not do that here: we let the lower error pass thru. */ return (DW_DLV_ERROR); } if (dis->de_offdie_cu_context == NULL) { dis->de_offdie_cu_context = cu_context; dis->de_offdie_cu_context_end = cu_context; } else { dis->de_offdie_cu_context_end->cc_next = cu_context; dis->de_offdie_cu_context_end = cu_context; } new_cu_offset = new_cu_offset + cu_context->cc_length + cu_context->cc_length_size; } while (offset >= new_cu_offset); } die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); if (die == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } die->di_cu_context = cu_context; die->di_is_info = is_info; { Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data: dbg->de_debug_types.dss_data; info_ptr = dataptr + offset; } die->di_debug_ptr = info_ptr; DECODE_LEB128_UWORD(info_ptr, utmp); abbrev_code = utmp; if (abbrev_code == 0) { /* we are at a null DIE (or there is a bug). */ *new_die = 0; dwarf_dealloc(dbg, die, DW_DLA_DIE); return DW_DLV_NO_ENTRY; } die->di_abbrev_code = abbrev_code; die->di_abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code); if (die->di_abbrev_list == NULL) { dwarf_dealloc(dbg, die, DW_DLA_DIE); _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL); return (DW_DLV_ERROR); } *new_die = die; return (DW_DLV_OK); }
/* Given a die offset, this returns a pointer to a DIE thru *new_die. It is up to the caller to do a dwarf_dealloc(dbg,*new_die,DW_DLE_DIE); */ int dwarf_offdie(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Die * new_die, Dwarf_Error * error) { Dwarf_CU_Context cu_context; Dwarf_Off new_cu_offset = 0; Dwarf_Die die; Dwarf_Byte_Ptr info_ptr; Dwarf_Half abbrev_code; Dwarf_Unsigned utmp; if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } cu_context = _dwarf_find_CU_Context(dbg, offset); if (cu_context == NULL) cu_context = _dwarf_find_offdie_CU_Context(dbg, offset); if (cu_context == NULL) { int res = _dwarf_load_debug_info(dbg, error); if (res != DW_DLV_OK) { return res; } if (dbg->de_cu_context_list_end != NULL) new_cu_offset = dbg->de_cu_context_list_end->cc_debug_info_offset + dbg->de_cu_context_list_end->cc_length + dbg->de_cu_context_list_end->cc_length_size + dbg->de_cu_context_list_end->cc_extension_size; do { if ((new_cu_offset + _dwarf_length_of_cu_header_simple(dbg)) >= dbg->de_debug_info_size) { _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD); return (DW_DLV_ERROR); } cu_context = _dwarf_make_CU_Context(dbg, new_cu_offset, error); if (cu_context == NULL) { /* Error if CU Context could not be made. Since _dwarf_make_CU_Context has already registered an error we do not do that here: we let the lower error pass thru. */ return (DW_DLV_ERROR); } if (dbg->de_offdie_cu_context == NULL) { dbg->de_offdie_cu_context = cu_context; dbg->de_offdie_cu_context_end = cu_context; } else { dbg->de_offdie_cu_context_end->cc_next = cu_context; dbg->de_offdie_cu_context_end = cu_context; } new_cu_offset = new_cu_offset + cu_context->cc_length + cu_context->cc_length_size; } while (offset >= new_cu_offset); } die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1); if (die == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } die->di_cu_context = cu_context; info_ptr = dbg->de_debug_info + offset; die->di_debug_info_ptr = info_ptr; DECODE_LEB128_UWORD(info_ptr, utmp) abbrev_code = (Dwarf_Half) utmp; if (abbrev_code == 0) { /* we are at a null DIE (or there is a bug). */ *new_die = 0; return DW_DLV_NO_ENTRY; } die->di_abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code); if (die->di_abbrev_list == NULL) { _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL); return (DW_DLV_ERROR); } *new_die = die; return (DW_DLV_OK); }