static int dwarf_next_cu_header_internal(Dwarf_Debug dbg, Dwarf_Bool is_info, Dwarf_Unsigned * cu_header_length, Dwarf_Half * version_stamp, Dwarf_Unsigned * abbrev_offset, Dwarf_Half * address_size, Dwarf_Half * offset_size, Dwarf_Half * extension_size, Dwarf_Sig8 * signature, Dwarf_Unsigned *typeoffset, Dwarf_Unsigned * next_cu_offset, Dwarf_Error * error) { /* Offset for current and new CU. */ Dwarf_Unsigned new_offset = 0; /* CU Context for current CU. */ Dwarf_CU_Context cu_context = 0; Dwarf_Debug_InfoTypes dis = 0; Dwarf_Unsigned section_size = 0; /* ***** BEGIN CODE ***** */ 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; /* Get offset into .debug_info of next CU. If dbg has no context, this has to be the first one. */ if (dis->de_cu_context == NULL) { new_offset = 0; Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data: dbg->de_debug_types.dss_data; if (!dataptr) { Dwarf_Error err2= 0; int res = is_info?_dwarf_load_debug_info(dbg, &err2): _dwarf_load_debug_types(dbg,&err2); if (res != DW_DLV_OK) { if(reloc_incomplete(err2)) { /* We will assume all is ok, though it is not. Relocation errors need not be fatal. */ char msg_buf[200]; snprintf(msg_buf,sizeof(msg_buf), "Relocations did not complete successfully, but we are " " ignoring error: %s",dwarf_errmsg(err2)); dwarf_insert_harmless_error(dbg,msg_buf); res = DW_DLV_OK; } else { if( error) { *error = err2; } return res; } } } } else { new_offset = dis->de_cu_context->cc_debug_offset + dis->de_cu_context->cc_length + dis->de_cu_context->cc_length_size + dis->de_cu_context->cc_extension_size; } /* Check that there is room in .debug_info beyond the new offset for at least a new cu header. If not, return 0 to indicate end of debug_info section, and reset de_cu_debug_info_offset to enable looping back through the cu's. */ section_size = is_info? dbg->de_debug_info.dss_size: dbg->de_debug_types.dss_size; if ((new_offset + _dwarf_length_of_cu_header_simple(dbg,is_info)) >= section_size) { dis->de_cu_context = NULL; return (DW_DLV_NO_ENTRY); } /* Check if this CU has been read before. */ cu_context = _dwarf_find_CU_Context(dbg, new_offset,is_info); /* If not, make CU Context for it. */ if (cu_context == NULL) { cu_context = _dwarf_make_CU_Context(dbg, new_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); } } dis->de_cu_context = cu_context; if (cu_header_length != NULL) { *cu_header_length = cu_context->cc_length; } if (version_stamp != NULL) { *version_stamp = cu_context->cc_version_stamp; } if (abbrev_offset != NULL) { *abbrev_offset = cu_context->cc_abbrev_offset; } if (address_size != NULL) { *address_size = cu_context->cc_address_size; } if (offset_size != NULL) { *offset_size = cu_context->cc_length_size; } if (extension_size != NULL) { *extension_size = cu_context->cc_extension_size; } if(!is_info) { if(signature) { *signature = cu_context->cc_signature; } if(typeoffset) { *typeoffset = cu_context->cc_typeoffset; } } new_offset = new_offset + cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size; *next_cu_offset = new_offset; 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); }
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); }
/* Returns offset of next compilation-unit thru next_cu_offset pointer. It basically sequentially moves from one cu to the next. The current cu is recorded internally by libdwarf. */ int dwarf_next_cu_header(Dwarf_Debug dbg, Dwarf_Unsigned * cu_header_length, Dwarf_Half * version_stamp, Dwarf_Unsigned * abbrev_offset, Dwarf_Half * address_size, Dwarf_Unsigned * next_cu_offset, Dwarf_Error * error) { /* Offset for current and new CU. */ Dwarf_Unsigned new_offset; /* CU Context for current CU. */ Dwarf_CU_Context cu_context; /* ***** BEGIN CODE ***** */ if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } /* Get offset into .debug_info of next CU. If dbg has no context, this has to be the first one. */ if (dbg->de_cu_context == NULL) { new_offset = 0; if (!dbg->de_debug_info) { int res = _dwarf_load_debug_info(dbg, error); if (res != DW_DLV_OK) { return res; } } } else { new_offset = dbg->de_cu_context->cc_debug_info_offset + dbg->de_cu_context->cc_length + dbg->de_cu_context->cc_length_size + dbg->de_cu_context->cc_extension_size; } /* Check that there is room in .debug_info beyond the new offset for at least a new cu header. If not, return 0 to indicate end of debug_info section, and reset de_cu_debug_info_offset to enable looping back through the cu's. */ if ((new_offset + _dwarf_length_of_cu_header_simple(dbg)) >= dbg->de_debug_info_size) { dbg->de_cu_context = NULL; return (DW_DLV_NO_ENTRY); } /* Check if this CU has been read before. */ cu_context = _dwarf_find_CU_Context(dbg, new_offset); /* If not, make CU Context for it. */ if (cu_context == NULL) { cu_context = _dwarf_make_CU_Context(dbg, new_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); } } dbg->de_cu_context = cu_context; if (cu_header_length != NULL) *cu_header_length = cu_context->cc_length; if (version_stamp != NULL) *version_stamp = cu_context->cc_version_stamp; if (abbrev_offset != NULL) *abbrev_offset = cu_context->cc_abbrev_offset; if (address_size != NULL) *address_size = cu_context->cc_address_size; new_offset = new_offset + cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size; *next_cu_offset = new_offset; return (DW_DLV_OK); }