int dwarf_formaddr(Dwarf_Attribute attr, Dwarf_Addr * return_addr, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_Addr ret_addr = 0; Dwarf_CU_Context cu_context = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } if (attr->ar_attribute_form == DW_FORM_addr /* || attr->ar_attribute_form == DW_FORM_ref_addr Allowance of DW_FORM_ref_addr was a mistake. The value returned in that case is NOT an address it is a global debug_info offset (ie, not CU-relative offset within the CU in debug_info). The Dwarf document refers to it as an address (misleadingly) in sec 6.5.4 where it describes the reference form. It is address-sized so that the linker can easily update it, but it is a reference inside the debug_info section. No longer allowed. */ ) { READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr, attr->ar_debug_ptr, cu_context->cc_address_size); *return_addr = ret_addr; return (DW_DLV_OK); } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); return (DW_DLV_ERROR); }
int dwarf_formexprloc(Dwarf_Attribute attr, Dwarf_Unsigned * return_exprlen, Dwarf_Ptr * block_ptr, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_CU_Context cu_context = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); return (DW_DLV_ERROR); } if (attr->ar_attribute_form == DW_FORM_exprloc ) { Dwarf_Word leb_len = 0; Dwarf_Unsigned exprlen = (_dwarf_decode_u_leb128(attr->ar_debug_ptr, &leb_len)); Dwarf_Small * addr = attr->ar_debug_ptr; *return_exprlen = exprlen; *block_ptr = addr + leb_len; return DW_DLV_OK; } _dwarf_error(dbg, error, DW_DLE_ATTR_EXPRLOC_FORM_BAD); return (DW_DLV_ERROR); }
/* dwarf_formsig8 returns in the caller-provided 8 byte area the 8 bytes of a DW_FORM_ref_sig8 (copying the bytes directly to the caller). Not a string, an 8 byte MD5 hash. This function is new in DWARF4 libdwarf. */ int dwarf_formsig8(Dwarf_Attribute attr, Dwarf_Sig8 * returned_sig_bytes, Dwarf_Error* error) { Dwarf_Debug dbg = 0; Dwarf_Unsigned field_end_offset = 0; Dwarf_CU_Context cu_context = 0; Dwarf_Small *dataptr = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } if (attr->ar_attribute_form != DW_FORM_ref_sig8 ) { _dwarf_error(dbg, error, DW_DLE_BAD_REF_SIG8_FORM); return (DW_DLV_ERROR); } dataptr = cu_context->cc_is_info? dbg->de_debug_info.dss_data: dbg->de_debug_types.dss_data; field_end_offset = attr->ar_debug_ptr + sizeof(Dwarf_Sig8) - (dataptr + cu_context->cc_debug_offset); /* Check that offset is within current cu portion of .debug_info. */ if (field_end_offset > cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size) { _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); return (DW_DLV_ERROR); } memcpy(returned_sig_bytes, attr->ar_debug_ptr, sizeof(Dwarf_Sig8)); return DW_DLV_OK; }
/* Part of DebugFission. So a dwarf dumper application can get the index and print it for the user. A convenience function. New May 2014*/ int dwarf_get_debug_str_index(Dwarf_Attribute attr, Dwarf_Unsigned *return_index, Dwarf_Error *error) { int theform = attr->ar_attribute_form; if (theform == DW_FORM_strx || theform == DW_FORM_GNU_str_index) { Dwarf_Unsigned index = 0; Dwarf_Word uleblen = 0; Dwarf_Small *info_ptr = attr->ar_debug_ptr; index = _dwarf_decode_u_leb128(info_ptr,&uleblen); *return_index = index; return DW_DLV_OK; } { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_NOT_ADDR_INDEX); } return (DW_DLV_ERROR); }
int dwarf_get_debug_addr_index(Dwarf_Attribute attr, Dwarf_Unsigned * return_index, Dwarf_Error * error) { int theform = attr->ar_attribute_form; if (theform == DW_FORM_GNU_addr_index || theform == DW_FORM_addrx) { int res = 0; Dwarf_Unsigned index = 0; res = _dwarf_get_addr_index_itself(theform, attr->ar_debug_ptr,&index,error); *return_index = index; return res; } { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_NOT_ADDR_INDEX); return (DW_DLV_ERROR); } return DW_DLV_NO_ENTRY; }
/* This function is analogous to dwarf_whatform. It returns the attribute in attr instead of the form. */ int dwarf_whatattr(Dwarf_Attribute attr, Dwarf_Half * return_attr, Dwarf_Error * error) { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; int res =get_attr_dbg(&dbg,&cu_context, attr,error); if (res != DW_DLV_OK) { return res; } *return_attr = (attr->ar_attribute); return DW_DLV_OK; }
int dwarf_whatform(Dwarf_Attribute attr, Dwarf_Half * return_form, Dwarf_Error * error) { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; int res =get_attr_dbg(&dbg,&cu_context, attr,error); if (res != DW_DLV_OK) { return res; } *return_form = attr->ar_attribute_form; return (DW_DLV_OK); }
int dwarf_hasform(Dwarf_Attribute attr, Dwarf_Half form, Dwarf_Bool * return_bool, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_CU_Context cu_context = 0; int res =get_attr_dbg(&dbg,&cu_context, attr,error); if (res != DW_DLV_OK) { return res; } *return_bool = (attr->ar_attribute_form == form); return DW_DLV_OK; }
/* Convert an offset within the local CU into a section-relative debug_info (or debug_types) offset. See dwarf_global_formref() and dwarf_formref() for additional information on conversion rules. */ int dwarf_convert_to_global_offset(Dwarf_Attribute attr, Dwarf_Off offset, Dwarf_Off * ret_offset, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_CU_Context cu_context = 0; int res = 0; res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } switch (attr->ar_attribute_form) { case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: /* It is a cu-local offset. Convert to section-global. */ /* It would be nice to put some code to check legality of the offset */ /* cc_debug_offset always has any DWP Package File offset included (when the cu_context created) so there is no extra work for DWP. /* globalize the offset */ offset += cu_context->cc_debug_offset; break; case DW_FORM_ref_addr: /* This offset is defined to be debug_info global already, so use this value unaltered. Since a DWP package file is not relocated there is no way that this reference offset to an address in any other CU can be correct for a DWP Package File offset */ break; default: _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); return (DW_DLV_ERROR); } *ret_offset = (offset); return DW_DLV_OK; }
int dwarf_formexprloc(Dwarf_Attribute attr, Dwarf_Unsigned * return_exprlen, Dwarf_Ptr * block_ptr, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_CU_Context cu_context = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL); return (DW_DLV_ERROR); } if (attr->ar_attribute_form == DW_FORM_exprloc ) { Dwarf_Die die = 0; Dwarf_Word leb_len = 0; Dwarf_Unsigned exprlen = (_dwarf_decode_u_leb128(attr->ar_debug_ptr, &leb_len)); Dwarf_Small * addr = attr->ar_debug_ptr; /* Is the block entirely in the section, or is there bug somewhere? */ die = attr->ar_die; if (_dwarf_reference_outside_section(die, (Dwarf_Small *)addr, ((Dwarf_Small *)addr)+exprlen +leb_len)) { _dwarf_error(dbg, error,DW_DLE_ATTR_OUTSIDE_SECTION); return DW_DLV_ERROR; } *return_exprlen = exprlen; *block_ptr = addr + leb_len; return DW_DLV_OK; } _dwarf_error(dbg, error, DW_DLE_ATTR_EXPRLOC_FORM_BAD); return (DW_DLV_ERROR); }
/* Convert an offset within the local CU into a section-relative debug_info offset. See dwarf_global_formref() and dwarf_formref() for additional information on conversion rules. */ int dwarf_convert_to_global_offset(Dwarf_Attribute attr, Dwarf_Off offset, Dwarf_Off * ret_offset, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_CU_Context cu_context = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } switch (attr->ar_attribute_form) { case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: /* It would be nice to put some code to check legality of the offset */ /* globalize the offset */ offset += cu_context->cc_debug_offset; break; case DW_FORM_ref_addr: /* This offset is defined to be debug_info global already, so use this value unaltered. */ break; default: _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); return (DW_DLV_ERROR); } *ret_offset = (offset); return DW_DLV_OK; }
/* If the form is DW_FORM_constx and the .debug_addr section is missing, this returns DW_DLV_ERROR and the error number in the Dwarf_Error is DW_DLE_MISSING_NEEDED_DEBUG_ADDR_SECTION. When that arises, a consumer should call dwarf_get_debug_addr_index() and use that on the appropriate .debug_addr section in the executable or another object. */ int dwarf_formudata(Dwarf_Attribute attr, Dwarf_Unsigned * return_uval, Dwarf_Error * error) { Dwarf_Unsigned ret_value = 0; Dwarf_Debug dbg = 0; Dwarf_CU_Context cu_context = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } switch (attr->ar_attribute_form) { case DW_FORM_data1: READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Small)); *return_uval = ret_value; return DW_DLV_OK; /* READ_UNALIGNED does the right thing as it reads the right number bits and generates host order. So we can just assign to *return_uval. */ case DW_FORM_data2:{ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Half)); *return_uval = ret_value; return DW_DLV_OK; } case DW_FORM_data4:{ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_ufixed)); *return_uval = ret_value; return DW_DLV_OK; } case DW_FORM_data8:{ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Unsigned)); *return_uval = ret_value; return DW_DLV_OK; } break; /* real udata */ case DW_FORM_udata: ret_value = (_dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL)); *return_uval = ret_value; return DW_DLV_OK; /* IRIX bug 583450. We do not allow reading sdata from a udata value. Caller can retry, calling sdata */ default: break; } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); return (DW_DLV_ERROR); }
/* Contrary to long standing documentation, The string pointer returned thru return_str must never have dwarf_dealloc() applied to it. Documentation fixed July 2005. */ int dwarf_formstring(Dwarf_Attribute attr, char **return_str, Dwarf_Error * error) { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; Dwarf_Unsigned offset = 0; int res = DW_DLV_ERROR; res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } if (attr->ar_attribute_form == DW_FORM_string) { void *begin = attr->ar_debug_ptr; if (0 == dbg->de_assume_string_in_bounds) { /* Check that string lies within current cu in .debug_info. */ void *end = dbg->de_debug_info.dss_data + cu_context->cc_debug_offset + cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size; if (0 == _dwarf_string_valid(begin, end)) { _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD); return (DW_DLV_ERROR); } } *return_str = (char *) (begin); return DW_DLV_OK; } if (attr->ar_attribute_form == DW_FORM_strp) { READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, cu_context->cc_length_size); res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); if (res != DW_DLV_OK) { return res; } if (0 == dbg->de_assume_string_in_bounds) { /* Check that string lies within current cu in .debug_info. */ void *end = dbg->de_debug_str.dss_data + dbg->de_debug_str.dss_size; void*begin = dbg->de_debug_str.dss_data + offset; if (0 == _dwarf_string_valid(begin, end)) { _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD); return (DW_DLV_ERROR); } } /* Ensure the offset lies within the .debug_str */ if (offset >= dbg->de_debug_str.dss_size) { _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD); return (DW_DLV_ERROR); } *return_str = (char *) (dbg->de_debug_str.dss_data + offset); return DW_DLV_OK; } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); return (DW_DLV_ERROR); }
int dwarf_global_formref(Dwarf_Attribute attr, Dwarf_Off * ret_offset, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_Unsigned offset = 0; Dwarf_CU_Context cu_context = 0; Dwarf_Half context_version = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } context_version = cu_context->cc_version_stamp; switch (attr->ar_attribute_form) { case DW_FORM_ref1: offset = *(Dwarf_Small *) attr->ar_debug_ptr; goto fixoffset; case DW_FORM_ref2: READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Half)); goto fixoffset; case DW_FORM_ref4: READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_ufixed)); goto fixoffset; case DW_FORM_ref8: READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Unsigned)); goto fixoffset; case DW_FORM_ref_udata: { offset = _dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL); fixoffset: /* we have a local offset, make it global */ /* check legality of offset */ if (offset >= cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size) { _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); return (DW_DLV_ERROR); } /* globalize the offset */ offset += cu_context->cc_debug_offset; } break; /* The DWARF2 document did not make clear that DW_FORM_data4( and 8) were references with global offsets to some section. That was first clearly documented in DWARF3. In DWARF4 these two forms are no longer references. */ case DW_FORM_data4: if (context_version == DW_CU_VERSION4) { _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM); return (DW_DLV_ERROR); } READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_ufixed)); /* The offset is global. */ break; case DW_FORM_data8: if (context_version == DW_CU_VERSION4) { _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM); return (DW_DLV_ERROR); } READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Unsigned)); /* The offset is global. */ break; case DW_FORM_ref_addr: { /* In Dwarf V2 DW_FORM_ref_addr was defined as address-size even though it is a .debug_info offset. Fixed in Dwarf V3 to be offset-size. */ unsigned length_size = 0; if (context_version == 2) { length_size = cu_context->cc_address_size; } else { length_size = cu_context->cc_length_size; } if (length_size == 4) { READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_ufixed)); } else if (length_size == 8) { READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Unsigned)); } else { _dwarf_error(dbg, error, DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD); return (DW_DLV_ERROR); } } break; case DW_FORM_sec_offset: case DW_FORM_GNU_ref_alt: /* 2013 GNU extension */ case DW_FORM_GNU_strp_alt: /* 2013 GNU extension */ { /* DW_FORM_sec_offset first exists in DWARF4.*/ /* It is up to the caller to know what the offset of DW_FORM_sec_offset refers to, the offset is not going to refer to .debug_info! */ unsigned length_size = cu_context->cc_length_size; if (length_size == 4) { READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_ufixed)); } else if (length_size == 8) { READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Unsigned)); } else { _dwarf_error(dbg, error, DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD); return (DW_DLV_ERROR); } } break; case DW_FORM_ref_sig8: /* FIXME */ /* We cannot handle this yet. The reference is to .debug_types, and this function only returns an offset in .debug_info at this point. */ _dwarf_error(dbg, error, DW_DLE_REF_SIG8_NOT_HANDLED); return (DW_DLV_ERROR); default: _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); return (DW_DLV_ERROR); } /* We do not know what section the offset refers to, so we have no way to check it for correctness. */ *ret_offset = offset; return DW_DLV_OK; }
int dwarf_formref(Dwarf_Attribute attr, Dwarf_Off * ret_offset, Dwarf_Error * error) { Dwarf_Debug dbg = 0; Dwarf_Unsigned offset = 0; Dwarf_CU_Context cu_context = 0; Dwarf_Unsigned maximumoffset = 0; int res = DW_DLV_ERROR; *ret_offset = 0; res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } switch (attr->ar_attribute_form) { case DW_FORM_ref1: offset = *(Dwarf_Small *) attr->ar_debug_ptr; break; case DW_FORM_ref2: READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Half)); break; case DW_FORM_ref4: READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_ufixed)); break; case DW_FORM_ref8: READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Unsigned)); break; case DW_FORM_ref_udata: offset = _dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL); break; case DW_FORM_ref_sig8: /* We cannot handle this here. The reference is to .debug_types not a .debug_info CU local offset. */ _dwarf_error(dbg, error, DW_DLE_REF_SIG8_NOT_HANDLED); return (DW_DLV_ERROR); default: _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM); return (DW_DLV_ERROR); } /* Check that offset is within current cu portion of .debug_info. */ maximumoffset = cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size; if (offset >= maximumoffset) { /* For the DW_TAG_compile_unit is legal to have the DW_AT_sibling attribute outside the current cu portion of .debug_info. In other words, sibling points to the end of the CU. It is used for precompiled headers. The valid condition will be: 'offset == maximumoffset'. */ Dwarf_Half tag = 0; if (DW_DLV_OK != dwarf_tag(attr->ar_die,&tag,error)) { _dwarf_error(dbg, error, DW_DLE_DIE_BAD); return (DW_DLV_ERROR); } if (DW_TAG_compile_unit != tag && DW_AT_sibling != attr->ar_attribute && offset > maximumoffset) { _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD); /* Return the incorrect offset for better error reporting */ *ret_offset = (offset); return (DW_DLV_ERROR); } } *ret_offset = (offset); return DW_DLV_OK; }
/* Contrary to pre-2005 documentation, The string pointer returned thru return_str must never have dwarf_dealloc() applied to it. Documentation fixed July 2005. */ int dwarf_formstring(Dwarf_Attribute attr, char **return_str, Dwarf_Error * error) { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; Dwarf_Unsigned offset = 0; int res = DW_DLV_ERROR; Dwarf_Small *dataptr = 0; Dwarf_Small *infoptr = attr->ar_debug_ptr; res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } dataptr = cu_context->cc_is_info? dbg->de_debug_info.dss_data: dbg->de_debug_types.dss_data; if (attr->ar_attribute_form == DW_FORM_string) { void *begin = attr->ar_debug_ptr; if (0 == dbg->de_assume_string_in_bounds) { /* Check that string lies within current cu in .debug_info. */ void *end = dataptr + cu_context->cc_debug_offset + cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size; if (0 == _dwarf_string_valid(begin, end)) { _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD); return (DW_DLV_ERROR); } } *return_str = (char *) (begin); return DW_DLV_OK; } if (attr->ar_attribute_form == DW_FORM_GNU_strp_alt) { /* Unsure what this is really. FIXME */ *return_str = (char *)"<DW_FORM_GNU_strp_alt not handled>"; return DW_DLV_OK; } if (attr->ar_attribute_form == DW_FORM_GNU_str_index || attr->ar_attribute_form == DW_FORM_strx) { Dwarf_Unsigned offsettostr= 0; res = _dwarf_extract_string_offset_via_str_offsets(dbg, infoptr, attr->ar_attribute, attr->ar_attribute_form, cu_context, &offsettostr, error); offset = offsettostr; /* FALL THRU */ } else { if (attr->ar_attribute_form == DW_FORM_strp) { READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, infoptr, cu_context->cc_length_size); } } if (attr->ar_attribute_form == DW_FORM_strp || attr->ar_attribute_form == DW_FORM_GNU_str_index || attr->ar_attribute_form == DW_FORM_strx) { /* The 'offset' into .debug_str is set. */ res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); if (res != DW_DLV_OK) { return res; } if (offset >= dbg->de_debug_str.dss_size) { /* Badly damaged DWARF here. */ _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD); return (DW_DLV_ERROR); } if (0 == dbg->de_assume_string_in_bounds) { /* Check that string lies within its .debug_str. */ void *end = dbg->de_debug_str.dss_data + dbg->de_debug_str.dss_size; void*begin = dbg->de_debug_str.dss_data + offset; if (0 == _dwarf_string_valid(begin, end)) { _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD); return (DW_DLV_ERROR); } } /* Ensure the offset lies within the .debug_str */ if (offset >= dbg->de_debug_str.dss_size) { _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD); return (DW_DLV_ERROR); } *return_str = (char *) (dbg->de_debug_str.dss_data + offset); return DW_DLV_OK; } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); return (DW_DLV_ERROR); }
int dwarf_formsdata(Dwarf_Attribute attr, Dwarf_Signed * return_sval, Dwarf_Error * error) { Dwarf_Signed ret_value = 0; Dwarf_Debug dbg = 0; Dwarf_CU_Context cu_context = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } switch (attr->ar_attribute_form) { case DW_FORM_data1: *return_sval = (*(Dwarf_Sbyte *) attr->ar_debug_ptr); return DW_DLV_OK; /* READ_UNALIGNED does not sign extend. So we have to use a cast to get the value sign extended in the right way for each case. */ case DW_FORM_data2:{ READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, attr->ar_debug_ptr, sizeof(Dwarf_Shalf)); *return_sval = (Dwarf_Shalf) ret_value; return DW_DLV_OK; } case DW_FORM_data4:{ READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, attr->ar_debug_ptr, sizeof(Dwarf_sfixed)); *return_sval = (Dwarf_sfixed) ret_value; return DW_DLV_OK; } case DW_FORM_data8:{ READ_UNALIGNED(dbg, ret_value, Dwarf_Signed, attr->ar_debug_ptr, sizeof(Dwarf_Signed)); *return_sval = (Dwarf_Signed) ret_value; return DW_DLV_OK; } case DW_FORM_sdata: ret_value = (_dwarf_decode_s_leb128(attr->ar_debug_ptr, NULL)); *return_sval = ret_value; return DW_DLV_OK; /* IRIX bug 583450. We do not allow reading sdata from a udata value. Caller can retry, calling udata */ default: break; } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); return DW_DLV_ERROR; }
int dwarf_formblock(Dwarf_Attribute attr, Dwarf_Block ** return_block, Dwarf_Error * error) { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; Dwarf_Unsigned length = 0; Dwarf_Small *data = 0; Dwarf_Word leb128_length = 0; Dwarf_Block *ret_block = 0; Dwarf_Small *dataptr = 0; int res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } switch (attr->ar_attribute_form) { case DW_FORM_block1: length = *(Dwarf_Small *) attr->ar_debug_ptr; data = attr->ar_debug_ptr + sizeof(Dwarf_Small); break; case DW_FORM_block2: READ_UNALIGNED(dbg, length, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_Half)); data = attr->ar_debug_ptr + sizeof(Dwarf_Half); break; case DW_FORM_block4: READ_UNALIGNED(dbg, length, Dwarf_Unsigned, attr->ar_debug_ptr, sizeof(Dwarf_ufixed)); data = attr->ar_debug_ptr + sizeof(Dwarf_ufixed); break; case DW_FORM_block: length = _dwarf_decode_u_leb128(attr->ar_debug_ptr, &leb128_length); data = attr->ar_debug_ptr + leb128_length; break; default: _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD); return (DW_DLV_ERROR); } /* Check that block lies within current cu in .debug_info. */ dataptr = cu_context->cc_is_info? dbg->de_debug_info.dss_data: dbg->de_debug_types.dss_data; if (attr->ar_debug_ptr + length >= dataptr + cu_context->cc_debug_offset + cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size) { _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD); return (DW_DLV_ERROR); } ret_block = (Dwarf_Block *) _dwarf_get_alloc(dbg, DW_DLA_BLOCK, 1); if (ret_block == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } ret_block->bl_len = length; ret_block->bl_data = (Dwarf_Ptr) data; ret_block->bl_from_loclist = 0; ret_block->bl_section_offset = data - dataptr; *return_block = ret_block; return (DW_DLV_OK); }
/* Contrary to pre-2005 documentation, The string pointer returned thru return_str must never have dwarf_dealloc() applied to it. Documentation fixed July 2005. */ int dwarf_formstring(Dwarf_Attribute attr, char **return_str, Dwarf_Error * error) { Dwarf_CU_Context cu_context = 0; Dwarf_Debug dbg = 0; Dwarf_Unsigned offset = 0; int res = DW_DLV_ERROR; Dwarf_Small *secdataptr = 0; Dwarf_Small *secend = 0; Dwarf_Unsigned secdatalen = 0; Dwarf_Small *infoptr = attr->ar_debug_ptr; res = get_attr_dbg(&dbg,&cu_context,attr,error); if (res != DW_DLV_OK) { return res; } if (cu_context->cc_is_info) { secdataptr = (Dwarf_Small *)dbg->de_debug_info.dss_data; secdatalen = dbg->de_debug_info.dss_size; } else { secdataptr = (Dwarf_Small *)dbg->de_debug_types.dss_data; secdatalen = dbg->de_debug_types.dss_size; } switch(attr->ar_attribute_form) { case DW_FORM_string: { Dwarf_Small *begin = attr->ar_debug_ptr; Dwarf_Small *contextend = secdataptr + cu_context->cc_debug_offset + cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size; secend = secdataptr + secdatalen; if (contextend < secend) { secend = contextend; } res= _dwarf_check_string_valid(dbg,secdataptr,begin, secend,error); if (res != DW_DLV_OK) { return res; } *return_str = (char *) (begin); return DW_DLV_OK; } case DW_FORM_GNU_strp_alt: case DW_FORM_strp_sup: { Dwarf_Error alterr = 0; /* See dwarfstd.org issue 120604.1 This is the offset in the .debug_str section of another object file. The 'tied' file notion should apply. It is not clear whether both a supplementary and a split object might be needed at the same time (hence two 'tied' files simultaneously). */ Dwarf_Off soffset = 0; res = dwarf_global_formref(attr, &soffset,error); if (res != DW_DLV_OK) { return res; } res = _dwarf_get_string_from_tied(dbg, soffset, return_str, &alterr); if (res == DW_DLV_ERROR) { if (dwarf_errno(alterr) == DW_DLE_NO_TIED_FILE_AVAILABLE) { dwarf_dealloc(dbg,alterr,DW_DLA_ERROR); if( attr->ar_attribute_form == DW_FORM_GNU_strp_alt) { *return_str = (char *)"<DW_FORM_GNU_strp_alt-no-tied-file>"; } else { *return_str = (char *)"<DW_FORM_strp_sup-no-tied-file>"; } return DW_DLV_OK; } if (error) { *error = alterr; } return res; } if (res == DW_DLV_NO_ENTRY) { if( attr->ar_attribute_form == DW_FORM_GNU_strp_alt) { *return_str = (char *)"<DW_FORM_GNU_strp_alt-no-tied-file>"; }else { *return_str = (char *)"<DW_FORM_strp_sup-no-tied-file>"; } } return res; } case DW_FORM_GNU_str_index: case DW_FORM_strx: { Dwarf_Unsigned offsettostr= 0; res = _dwarf_extract_string_offset_via_str_offsets(dbg, infoptr, attr->ar_attribute, attr->ar_attribute_form, cu_context, &offsettostr, error); if (res != DW_DLV_OK) { return res; } offset = offsettostr; break; } case DW_FORM_strp: case DW_FORM_line_strp:{ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned, infoptr, cu_context->cc_length_size); break; } default: _dwarf_error(dbg, error, DW_DLE_STRING_FORM_IMPROPER); return DW_DLV_ERROR; } /* Now we have offset so read the string from debug_str or debug_line_str. */ res = _dwarf_extract_local_debug_str_string_given_offset(dbg, attr->ar_attribute_form, offset, return_str, error); return res; }