int _dwarf_get_string_from_tied(Dwarf_Debug dbg, Dwarf_Unsigned offset, char **return_str, Dwarf_Error*error) { Dwarf_Debug tieddbg = 0; Dwarf_Small *secend = 0; Dwarf_Small *secbegin = 0; Dwarf_Small *strbegin = 0; int res = DW_DLV_ERROR; Dwarf_Error localerror = 0; /* Attach errors to dbg, not tieddbg. */ tieddbg = dbg->de_tied_data.td_tied_object; if (!tieddbg) { _dwarf_error(dbg, error, DW_DLE_NO_TIED_FILE_AVAILABLE); return DW_DLV_ERROR; } /* The 'offset' into .debug_str is set. */ res = _dwarf_load_section(tieddbg, &tieddbg->de_debug_str,&localerror); if (res == DW_DLV_ERROR) { Dwarf_Unsigned lerrno = dwarf_errno(localerror); dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR); _dwarf_error(dbg,error,lerrno); return res; } else if (res == DW_DLV_NO_ENTRY) { return res; } if (offset >= tieddbg->de_debug_str.dss_size) { /* Badly damaged DWARF here. */ _dwarf_error(dbg, error, DW_DLE_NO_TIED_STRING_AVAILABLE); return (DW_DLV_ERROR); } secbegin = tieddbg->de_debug_str.dss_data; strbegin= tieddbg->de_debug_str.dss_data + offset; secend = tieddbg->de_debug_str.dss_data + tieddbg->de_debug_str.dss_size; /* Ensure the offset lies within the .debug_str */ if (offset >= tieddbg->de_debug_str.dss_size) { _dwarf_error(dbg, error, DW_DLE_NO_TIED_STRING_AVAILABLE); return (DW_DLV_ERROR); } res= _dwarf_check_string_valid(tieddbg,secbegin,strbegin, secend, &localerror); if (res == DW_DLV_ERROR) { Dwarf_Unsigned lerrno = dwarf_errno(localerror); dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR); _dwarf_error(dbg,error,lerrno); return res; } else if (res == DW_DLV_NO_ENTRY) { return res; } *return_str = (char *) (tieddbg->de_debug_str.dss_data + offset); return DW_DLV_OK; }
int _dwarf_extract_local_debug_str_string_given_offset(Dwarf_Debug dbg, unsigned attrform, Dwarf_Unsigned offset, char ** return_str, Dwarf_Error * error) { if (attrform == DW_FORM_strp || attrform == DW_FORM_line_strp || attrform == DW_FORM_GNU_str_index || attrform == DW_FORM_strx) { /* The 'offset' into .debug_str or .debug_line_str is given, here we turn that into a pointer. */ Dwarf_Small *secend = 0; Dwarf_Small *secbegin = 0; Dwarf_Small *strbegin = 0; Dwarf_Unsigned secsize = 0; int errcode = 0; int res = 0; if(attrform == DW_FORM_line_strp) { res = _dwarf_load_section(dbg, &dbg->de_debug_line_str,error); if (res != DW_DLV_OK) { return res; } errcode = DW_DLE_STRP_OFFSET_BAD; secsize = dbg->de_debug_line_str.dss_size; secbegin = dbg->de_debug_line_str.dss_data; strbegin= dbg->de_debug_line_str.dss_data + offset; } else { res = _dwarf_load_section(dbg, &dbg->de_debug_str,error); if (res != DW_DLV_OK) { return res; } errcode = DW_DLE_STRP_OFFSET_BAD; secsize = dbg->de_debug_str.dss_size; secbegin = dbg->de_debug_str.dss_data; strbegin= dbg->de_debug_str.dss_data + offset; secend = dbg->de_debug_str.dss_data + secsize; } if (offset >= secsize) { /* Badly damaged DWARF here. */ _dwarf_error(dbg, error, errcode); return (DW_DLV_ERROR); } res= _dwarf_check_string_valid(dbg,secbegin,strbegin, secend,error); if (res != DW_DLV_OK) { return res; } *return_str = (char *)strbegin; return DW_DLV_OK; } _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD); return (DW_DLV_ERROR); }
int dwarf_get_macro_details(Dwarf_Debug dbg, Dwarf_Off macro_offset, Dwarf_Unsigned maximum_count, Dwarf_Signed * entry_count, Dwarf_Macro_Details ** details, Dwarf_Error * error) { Dwarf_Small *macro_base = 0; Dwarf_Small *macro_end = 0; Dwarf_Small *pnext = 0; Dwarf_Unsigned endloc = 0; unsigned char uc = 0; unsigned long depth = 0; /* By section 6.3.2 Dwarf3 draft 8/9, the base file should appear as DW_MACINFO_start_file. See http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html on "[Bug debug/20253] New: [3.4/4.0 regression]: Macro debug info broken due to lexer change" for how gcc is broken in some versions. We no longer use depth as a stopping point, it's not needed as a stopping point anyway. */ int res = 0; /* count space used by strings */ unsigned long str_space = 0; int done = 0; unsigned long space_needed = 0; unsigned long string_offset = 0; Dwarf_Small *return_data = 0; Dwarf_Small *pdata = 0; unsigned long final_count = 0; Dwarf_Signed fileindex = -1; Dwarf_Small *latest_str_loc = 0; struct macro_stack_s msdata; unsigned long count = 0; unsigned long max_count = (unsigned long) maximum_count; _dwarf_reset_index_macro_stack(&msdata); if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); free_macro_stack(dbg,&msdata); return (DW_DLV_ERROR); } res = _dwarf_load_section(dbg, &dbg->de_debug_macinfo,error); if (res != DW_DLV_OK) { free_macro_stack(dbg,&msdata); return res; } if (!dbg->de_debug_abbrev.dss_size) { free_macro_stack(dbg,&msdata); return (DW_DLV_NO_ENTRY); } macro_base = dbg->de_debug_macinfo.dss_data; if (macro_base == NULL) { free_macro_stack(dbg,&msdata); return (DW_DLV_NO_ENTRY); } if (macro_offset >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); return (DW_DLV_NO_ENTRY); } macro_end = macro_base + dbg->de_debug_macinfo.dss_size; /* FIXME debugfission is NOT handled here. */ pnext = macro_base + macro_offset; if (maximum_count == 0) { max_count = ULONG_MAX; } /* how many entries and how much space will they take? */ endloc = (pnext - macro_base); if (endloc >= dbg->de_debug_macinfo.dss_size) { if (endloc == dbg->de_debug_macinfo.dss_size) { /* normal: found last entry */ free_macro_stack(dbg,&msdata); return DW_DLV_NO_ENTRY; } _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); free_macro_stack(dbg,&msdata); return (DW_DLV_ERROR); } for (count = 0; !done && count < max_count; ++count) { unsigned long slen = 0; /* Set but not used */ UNUSEDARG Dwarf_Unsigned utemp = 0; uc = *pnext; ++pnext; /* get past the type code */ switch (uc) { case DW_MACINFO_define: case DW_MACINFO_undef: /* line, string */ case DW_MACINFO_vendor_ext: /* number, string */ DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error, macro_end); if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } res = _dwarf_check_string_valid(dbg, macro_base,pnext,macro_end,error); if (res != DW_DLV_OK) { return res; } slen = strlen((char *) pnext) + 1; pnext += slen; if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } str_space += slen; break; case DW_MACINFO_start_file: /* line, file index */ DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error, macro_end); if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error, macro_end); if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } ++depth; break; case DW_MACINFO_end_file: if (--depth == 0) { /* done = 1; no, do not stop here, at least one gcc had the wrong depth settings in the gcc 3.4 timeframe. */ } /* no string or number here */ break; case 0: /* end of cu's entries */ done = 1; break; default: free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); /* bogus macinfo! */ } endloc = (pnext - macro_base); if (endloc == dbg->de_debug_macinfo.dss_size) { done = 1; } else if (endloc > dbg->de_debug_macinfo.dss_size) { _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); free_macro_stack(dbg,&msdata); return (DW_DLV_ERROR); } } if (count == 0) { free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR); return (DW_DLV_ERROR); } /* We have 'count' array entries to allocate and str_space bytes of string space to provide for. */ string_offset = count * sizeof(Dwarf_Macro_Details); /* extra 2 not really needed */ space_needed = string_offset + str_space + 2; return_data = pdata = (Dwarf_Small *)_dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed); latest_str_loc = pdata + string_offset; if (pdata == 0) { free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE); return (DW_DLV_ERROR); } pnext = macro_base + macro_offset; done = 0; /* A series ends with a type code of 0. */ for (final_count = 0; !done && final_count < count; ++final_count) { unsigned long slen = 0; Dwarf_Unsigned v1 = 0; Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata + (final_count * sizeof (Dwarf_Macro_Details))); endloc = (pnext - macro_base); if (endloc > dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); return (DW_DLV_ERROR); } uc = *pnext; pdmd->dmd_offset = (pnext - macro_base); pdmd->dmd_type = uc; pdmd->dmd_fileindex = fileindex; pdmd->dmd_lineno = 0; pdmd->dmd_macro = 0; ++pnext; /* get past the type code */ switch (uc) { case DW_MACINFO_define: case DW_MACINFO_undef: /* line, string */ case DW_MACINFO_vendor_ext: /* number, string */ DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error, macro_end); pdmd->dmd_lineno = v1; if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); dwarf_dealloc(dbg, return_data, DW_DLA_STRING); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } res = _dwarf_check_string_valid(dbg, macro_base,pnext,macro_end,error); if (res != DW_DLV_OK) { return res; } slen = strlen((char *) pnext) + 1; strcpy((char *) latest_str_loc, (char *) pnext); pdmd->dmd_macro = (char *) latest_str_loc; latest_str_loc += slen; pnext += slen; if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); dwarf_dealloc(dbg, return_data, DW_DLA_STRING); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } break; case DW_MACINFO_start_file: /* Line, file index */ DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error, macro_end); pdmd->dmd_lineno = v1; if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); dwarf_dealloc(dbg, return_data, DW_DLA_STRING); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error, macro_end); pdmd->dmd_fileindex = v1; (void) _dwarf_macro_stack_push_index(dbg, fileindex, &msdata); /* We ignore the error, we just let fileindex ** be -1 when we pop this one. */ fileindex = v1; if (((Dwarf_Unsigned)(pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) { free_macro_stack(dbg,&msdata); dwarf_dealloc(dbg, return_data, DW_DLA_STRING); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } break; case DW_MACINFO_end_file: fileindex = _dwarf_macro_stack_pop_index(&msdata); break; /* no string or number here */ case 0: /* Type code of 0 means the end of cu's entries. */ done = 1; break; default: /* Bogus macinfo! */ dwarf_dealloc(dbg, return_data, DW_DLA_STRING); free_macro_stack(dbg,&msdata); _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); return (DW_DLV_ERROR); } } *entry_count = count; *details = (Dwarf_Macro_Details *) return_data; free_macro_stack(dbg,&msdata); 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; }
/* Here a DW_DLV_NO_ENTRY return means the macro operator is not a def/undef operator. */ int dwarf_get_macro_defundef(Dwarf_Macro_Context macro_context, Dwarf_Unsigned op_number, Dwarf_Unsigned * line_number, Dwarf_Unsigned * index, Dwarf_Unsigned * offset, Dwarf_Half * forms_count, const char ** macro_string, Dwarf_Error *error) { Dwarf_Debug dbg = 0; Dwarf_Small *mdata = 0; int res = 0; Dwarf_Small *startptr = 0; Dwarf_Small *endptr = 0; Dwarf_Half lformscount = 0; struct Dwarf_Macro_Operator_s *curop = 0; unsigned macop = 0; if (!macro_context || macro_context->mc_sentinel != 0xada) { if(macro_context) { dbg = macro_context->mc_dbg; } _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER); return DW_DLV_ERROR; } dbg = macro_context->mc_dbg; if (op_number >= macro_context->mc_macro_ops_count) { _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_INDEX); return DW_DLV_ERROR; } curop = macro_context->mc_ops + op_number; macop = curop->mo_opcode; startptr = macro_context->mc_macro_header; endptr = startptr + macro_context->mc_total_length; mdata = curop->mo_data; lformscount = curop->mo_form->mf_formcount; if (lformscount != 2) { /*_dwarf_error(dbg, error,DW_DLE_MACRO_OPCODE_FORM_BAD);*/ return DW_DLV_NO_ENTRY; } switch(macop){ case DW_MACRO_define: case DW_MACRO_undef: { Dwarf_Unsigned linenum = 0; Dwarf_Word uleblen = 0; const char * content = 0; linenum = _dwarf_decode_u_leb128(mdata, &uleblen); mdata += uleblen; content = (const char *)mdata; res = _dwarf_check_string_valid(dbg, startptr,mdata, endptr, error); if(res != DW_DLV_OK) { return res; } *line_number = linenum; *index = 0; *offset = 0; *forms_count = lformscount; *macro_string = content; } return DW_DLV_OK; case DW_MACRO_define_strp: case DW_MACRO_undef_strp: { Dwarf_Unsigned linenum = 0; Dwarf_Word uleblen = 0; Dwarf_Unsigned stringoffset = 0; Dwarf_Small form1 = curop->mo_form->mf_formbytes[1]; char * localstr = 0; linenum = _dwarf_decode_u_leb128(mdata, &uleblen); mdata += uleblen; READ_UNALIGNED(dbg,stringoffset,Dwarf_Unsigned, mdata,macro_context->mc_offset_size); mdata += macro_context->mc_offset_size; res = _dwarf_extract_local_debug_str_string_given_offset(dbg, form1, stringoffset, &localstr, error); *index = 0; *line_number = linenum; *offset = stringoffset; *forms_count = lformscount; if (res == DW_DLV_ERROR) { return res; *macro_string = "<Error: getting local .debug_str>"; } else if (res == DW_DLV_NO_ENTRY) { *macro_string = "<Error: NO_ENTRY on .debug_string (strp)>"; } else { *macro_string = (const char *)localstr; } } return DW_DLV_OK; case DW_MACRO_define_strx: case DW_MACRO_undef_strx: { Dwarf_Unsigned linenum = 0; Dwarf_Word uleblen = 0; Dwarf_Unsigned stringindex = 0; Dwarf_Unsigned offsettostr= 0; int res = 0; Dwarf_Small form1 = curop->mo_form->mf_formbytes[1]; linenum = _dwarf_decode_u_leb128(mdata, &uleblen); mdata += uleblen; *line_number = linenum; stringindex = _dwarf_decode_u_leb128(mdata, &uleblen); /* leave mdata uchanged for call below */ *index = stringindex; *forms_count = lformscount; /* FIXME */ /* Redoes the index-getting. Gets offset. */ res = _dwarf_extract_string_offset_via_str_offsets(dbg, mdata, DW_AT_macros, /*arbitrary, unused by called routine. */ form1, macro_context->mc_cu_context, &offsettostr, error); if (res == DW_DLV_ERROR) { return res; } if (res == DW_DLV_OK) { *index = stringindex; *offset = offsettostr; char *localstr = 0; res = _dwarf_extract_local_debug_str_string_given_offset(dbg, form1, offsettostr, &localstr, error); if(res == DW_DLV_ERROR) { return res; } else if (res == DW_DLV_NO_ENTRY){ *macro_string = "<:No string available>"; } else { *macro_string = (const char *)localstr; /* All is ok. */ } } else { *index = stringindex; *offset = 0; *macro_string = "<.debug_str_offsets not available>"; } } return DW_DLV_OK; case DW_MACRO_define_sup: case DW_MACRO_undef_sup: { Dwarf_Unsigned linenum = 0; Dwarf_Word uleblen = 0; Dwarf_Unsigned supoffset = 0; char *localstring = 0; int res = 0; linenum = _dwarf_decode_u_leb128(mdata, &uleblen); mdata += uleblen; READ_UNALIGNED(dbg,supoffset,Dwarf_Unsigned, mdata,macro_context->mc_offset_size); mdata += macro_context->mc_offset_size; *line_number = linenum; *index = 0; *offset = supoffset; *forms_count = lformscount; res = _dwarf_get_string_from_tied(dbg, supoffset, &localstring, error); if (res != DW_DLV_OK) { if (res == DW_DLV_ERROR) { if(dwarf_errno(*error) == DW_DLE_NO_TIED_FILE_AVAILABLE) { *macro_string = (char *)"<DW_FORM_str_sup-no-tied_file>"; } else { *macro_string = (char *)"<Error: DW_FORM_str_sup-got-error>"; } dwarf_dealloc(dbg,*error,DW_DLA_ERROR); } else { *macro_string = "<DW_FORM_str_sup-no-entry>"; } } else { *macro_string = (const char *)localstring; } return DW_DLV_OK; } } return DW_DLV_NO_ENTRY; }
/* Sweeps the complete section. */ int _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg, Dwarf_Small * section_data_ptr, Dwarf_Unsigned section_length, Dwarf_Global ** globals, Dwarf_Signed * return_count, Dwarf_Error * error, int context_code, int global_code, int length_err_num, int version_err_num) { Dwarf_Small *pubnames_like_ptr = 0; Dwarf_Small *section_end_ptr = section_data_ptr +section_length; /* Points to the context for the current set of global names, and contains information to identify the compilation-unit that the set refers to. */ Dwarf_Global_Context pubnames_context = 0; Dwarf_Half version = 0; /* Offset from the start of compilation-unit for the current global. */ Dwarf_Off die_offset_in_cu = 0; Dwarf_Unsigned global_count = 0; /* Points to the current global read. */ Dwarf_Global global = 0; /* Used to chain the Dwarf_Global_s structs for creating contiguous list of pointers to the structs. */ Dwarf_Chain curr_chain = 0; Dwarf_Chain prev_chain = 0; Dwarf_Chain head_chain = 0; /* Points to contiguous block of Dwarf_Global's to be returned. */ Dwarf_Global *ret_globals = 0; /* Temporary counter. */ Dwarf_Unsigned i = 0; if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } /* We will eventually need the .debug_info data. Load it now. */ if (!dbg->de_debug_info.dss_data) { int res = _dwarf_load_debug_info(dbg, error); if (res != DW_DLV_OK) { return res; } } if (section_data_ptr == NULL) { return (DW_DLV_NO_ENTRY); } pubnames_like_ptr = section_data_ptr; do { Dwarf_Unsigned length = 0; int local_extension_size = 0; int local_length_size = 0; /* Some compilers emit padding at the end of each cu's area. pubnames_ptr_past_end_cu records the true area end for the pubnames(like) content of a cu. Essentially the length in the header and the 0 terminator of the data are redundant information. The dwarf2/3 spec does not mention what to do if the length is past the 0 terminator. So we take any bytes left after the 0 as padding and ignore them. */ Dwarf_Small *pubnames_ptr_past_end_cu = 0; pubnames_context = (Dwarf_Global_Context) _dwarf_get_alloc(dbg, context_code, 1); if (pubnames_context == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed bytes. */ READ_AREA_LENGTH_CK(dbg, length, Dwarf_Unsigned, pubnames_like_ptr, local_length_size, local_extension_size,error,section_length,section_end_ptr); pubnames_context->pu_length_size = local_length_size; pubnames_context->pu_extension_size = local_extension_size; pubnames_context->pu_dbg = dbg; pubnames_ptr_past_end_cu = pubnames_like_ptr + length; READ_UNALIGNED_CK(dbg, version, Dwarf_Half, pubnames_like_ptr, DWARF_HALF_SIZE, error,section_end_ptr); pubnames_like_ptr += DWARF_HALF_SIZE; /* ASSERT: DW_PUBNAMES_VERSION2 == DW_PUBTYPES_VERSION2 */ if (version != DW_PUBNAMES_VERSION2) { _dwarf_error(dbg, error, version_err_num); return (DW_DLV_ERROR); } /* Offset of CU header in debug section. */ READ_UNALIGNED_CK(dbg, pubnames_context->pu_offset_of_cu_header, Dwarf_Off, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; FIX_UP_OFFSET_IRIX_BUG(dbg, pubnames_context->pu_offset_of_cu_header, "pubnames cu header offset"); READ_UNALIGNED_CK(dbg, pubnames_context->pu_info_length, Dwarf_Unsigned, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; if (pubnames_like_ptr > (section_data_ptr + section_length)) { _dwarf_error(dbg, error, length_err_num); return (DW_DLV_ERROR); } /* Read initial offset (of DIE within CU) of a pubname, final entry is not a pair, just a zero offset. */ READ_UNALIGNED_CK(dbg, die_offset_in_cu, Dwarf_Off, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; FIX_UP_OFFSET_IRIX_BUG(dbg, die_offset_in_cu, "offset of die in cu"); /* Loop thru pairs. DIE off with CU followed by string. */ while (die_offset_in_cu != 0) { int res; /* Already read offset, pubnames_like_ptr now points to the string. */ global = (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1); if (global == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } global_count++; global->gl_context = pubnames_context; global->gl_named_die_offset_within_cu = die_offset_in_cu; global->gl_name = pubnames_like_ptr; res = _dwarf_check_string_valid(dbg,section_data_ptr, pubnames_like_ptr,section_end_ptr, DW_DLE_STRING_OFF_END_PUBNAMES_LIKE,error); if (res != DW_DLV_OK) { return res; } pubnames_like_ptr = pubnames_like_ptr + strlen((char *) pubnames_like_ptr) + 1; /* Finish off current entry chain */ curr_chain = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); if (curr_chain == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* Put current global on singly_linked list. */ curr_chain->ch_item = (Dwarf_Global) global; if (head_chain == NULL) head_chain = prev_chain = curr_chain; else { prev_chain->ch_next = curr_chain; prev_chain = curr_chain; } /* Fead offset for the *next* entry */ READ_UNALIGNED_CK(dbg, die_offset_in_cu, Dwarf_Off, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; FIX_UP_OFFSET_IRIX_BUG(dbg, die_offset_in_cu, "offset of next die in cu"); if (pubnames_like_ptr > (section_data_ptr + section_length)) { _dwarf_error(dbg, error, length_err_num); return (DW_DLV_ERROR); } } /* ASSERT: die_offset_in_cu == 0 */ if (pubnames_like_ptr > pubnames_ptr_past_end_cu) { /* This is some kind of error. This simply cannot happen. The encoding is wrong or the length in the header for this cu's contribution is wrong. */ _dwarf_error(dbg, error, length_err_num); return (DW_DLV_ERROR); } /* If there is some kind of padding at the end of the section, as emitted by some compilers, skip over that padding and simply ignore the bytes thus passed-over. With most compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at this point */ pubnames_like_ptr = pubnames_ptr_past_end_cu; } while (pubnames_like_ptr < (section_data_ptr + section_length)); /* Points to contiguous block of Dwarf_Global's. */ ret_globals = (Dwarf_Global *) _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count); if (ret_globals == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* Store pointers to Dwarf_Global_s structs in contiguous block, and deallocate the chain. */ curr_chain = head_chain; for (i = 0; i < global_count; i++) { *(ret_globals + i) = curr_chain->ch_item; prev_chain = curr_chain; curr_chain = curr_chain->ch_next; dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); } *globals = ret_globals; *return_count = (Dwarf_Signed) global_count; return DW_DLV_OK; }