/* Helper routine to avoid code duplication. */ static int _dwarf_get_loclist_header_start(Dwarf_Debug dbg, Dwarf_Attribute attr, Dwarf_Unsigned * loclist_offset, Dwarf_Error * error) { int blkres = dwarf_global_formref(attr, loclist_offset, error); if (blkres != DW_DLV_OK) { return (blkres); } if (!dbg->de_debug_loc.dss_data) { int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); if (secload != DW_DLV_OK) { return secload; } if (!dbg->de_debug_loc.dss_size) { return (DW_DLV_NO_ENTRY); } } { int fisres = 0; Dwarf_Unsigned fissoff = 0; Dwarf_Unsigned size = 0; fisres = _dwarf_get_fission_addition_die(attr->ar_die, DW_SECT_LOC, &fissoff, &size,error); if(fisres != DW_DLV_OK) { return fisres; } *loclist_offset += fissoff; } return DW_DLV_OK; }
static int get_attributes(Dwarf_Debug dbg,Dwarf_Die die, int level, struct srcfilesdata *sf, struct attributes *attr) { int res; Dwarf_Error error = 0; Dwarf_Attribute *attrbuf = 0; Dwarf_Addr lowpc = 0; Dwarf_Addr highpc = 0; Dwarf_Signed attrcount = 0; Dwarf_Unsigned i; Dwarf_Unsigned filenum = 0; Dwarf_Unsigned linenum = 0; char *filename = 0; int ret = 1; res = dwarf_attrlist(die,&attrbuf,&attrcount,&error); if(res != DW_DLV_OK) { return ret; } for(i = 0; i < attrcount ; ++i) { Dwarf_Half aform; res = dwarf_whatattr(attrbuf[i],&aform,&error); if(res == DW_DLV_OK) { if(aform == DW_AT_decl_file) { get_number(attrbuf[i],&filenum); if((filenum > 0) && (sf->srcfilescount > (filenum-1))) { filename = sf->srcfiles[filenum-1]; attr->filename = filename; } } if(aform == DW_AT_declaration) { Dwarf_Unsigned size=0; get_number(attrbuf[i],&size); ret =0; } if(aform == DW_AT_byte_size) { attr->size=0; get_number(attrbuf[i],&attr->size); } if(aform == DW_AT_data_member_location) { attr->member_location=0; get_number(attrbuf[i],&attr->member_location); } if(aform == DW_AT_type) { attr->type_offset = 0; dwarf_global_formref(attrbuf[i],&(attr->type_offset),&error); } } dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR); } dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST); return ret; }
int type_off(Dwarf_Die *die, Dwarf_Off *ref_off, Dwarf_Error *err) { Dwarf_Attribute type; int status; if ((status = dwarf_attr(*die, DW_AT_type, &type, err)) != DW_DLV_OK) { if (status == DW_DLV_NO_ENTRY) { fprintf(stderr, "No type information associated with die\n"); } else { fprintf(stderr, "Error %d in getting type attribute: %s\n", status, dwarf_errmsg(*err)); } return status; } if ((status = dwarf_global_formref(type, ref_off, err)) != DW_DLV_OK) { fprintf(stderr, "Error %d in getting type offset: %s\n", status, dwarf_errmsg(*err)); return status; } return DW_DLV_OK; }
/* Helper routine to avoid code duplication. */ static int _dwarf_get_loclist_header_start(Dwarf_Debug dbg, Dwarf_Attribute attr, Dwarf_Unsigned * loclist_offset, Dwarf_Error * error) { int blkres = dwarf_global_formref(attr, loclist_offset, error); if (blkres != DW_DLV_OK) { return (blkres); } if (!dbg->de_debug_loc.dss_data) { int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error); if (secload != DW_DLV_OK) { return secload; } if (!dbg->de_debug_loc.dss_size) { return (DW_DLV_NO_ENTRY); } } return DW_DLV_OK; }
Dwarf_Off DieHolder::get_ref_from_attr(int attr) { Dwarf_Off offset = 0; Dwarf_Half form = 0; Dwarf_Error err = NULL; Dwarf_Attribute attrib = get_attr(attr); CHECK_DWERR2(attrib == NULL, NULL, "cannot find DIE attribute %d\n", attr); CHECK_DWERR(dwarf_whatform(attrib, &form, &err), err, "cannot get form of the DIE attribute %d", attr); switch(form) { case DW_FORM_ref_addr: CHECK_DWERR(dwarf_global_formref(attrib, &offset, &err), err, "cannot get global reference address"); break; case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: { Dwarf_Off cu_offset = 0; Dwarf_Off cu_length = 0; CHECK_DWERR(dwarf_formref(attrib, &offset, &err), err, "cannot get reference address"); cu_offset = get_CU_offset_range(&cu_length); offset += cu_offset; } break; default: THROW_DWERR("unknown reference form=%d\n", form); break; } return offset; }
/* return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR If err_count_out is non-NULL, this is a special 'check' call. */ int _dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error, int * err_count_out, int only_line_header) { /* This pointer is used to scan the portion of the .debug_line section for the current cu. */ Dwarf_Small *line_ptr = 0; Dwarf_Small *orig_line_ptr = 0; /* This points to the last byte of the .debug_line portion for the current cu. */ Dwarf_Small *line_ptr_end = 0; /* Pointer to a DW_AT_stmt_list attribute in case it exists in the die. */ Dwarf_Attribute stmt_list_attr = 0; /* Pointer to DW_AT_comp_dir attribute in die. */ Dwarf_Attribute comp_dir_attr = 0; /* Pointer to name of compilation directory. */ Dwarf_Small *comp_dir = NULL; /* Offset into .debug_line specified by a DW_AT_stmt_list attribute. */ Dwarf_Unsigned line_offset = 0; struct Line_Table_Prefix_s prefix; /* These are the state machine state variables. */ Dwarf_Addr address = 0; Dwarf_Word file = 1; Dwarf_Word line = 1; Dwarf_Word column = 0; Dwarf_Bool is_stmt = false; Dwarf_Bool basic_block = false; Dwarf_Bool end_sequence = false; Dwarf_Bool prologue_end = false; Dwarf_Bool epilogue_begin = false; Dwarf_Small isa = 0; Dwarf_Sword i=0; /* This is the current opcode read from the statement program. */ Dwarf_Small opcode=0; /* These variables are used to decode leb128 numbers. Leb128_num holds the decoded number, and leb128_length is its length in bytes. */ Dwarf_Word leb128_num=0; Dwarf_Word leb128_length=0; Dwarf_Sword advance_line=0; Dwarf_Half attrform = 0; /* This is the operand of the latest fixed_advance_pc extended opcode. */ Dwarf_Half fixed_advance_pc=0; /* In case there are wierd bytes 'after' the line table * prologue this lets us print something. This is a gcc * compiler bug and we expect the bytes count to be 12. */ Dwarf_Small* bogus_bytes_ptr = 0; Dwarf_Unsigned bogus_bytes_count = 0; /* The Dwarf_Debug this die belongs to. */ Dwarf_Debug dbg=0; int resattr = DW_DLV_ERROR; int lres = DW_DLV_ERROR; int res = DW_DLV_ERROR; /* ***** BEGIN CODE ***** */ if (error != NULL) { *error = NULL; } CHECK_DIE(die, DW_DLV_ERROR); dbg = die->di_cu_context->cc_dbg; res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); if (res != DW_DLV_OK) { return res; } resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); if (resattr != DW_DLV_OK) { return resattr; } /* The list of relevant FORMs is small. DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset */ lres = dwarf_whatform(stmt_list_attr,&attrform,error); if (lres != DW_DLV_OK) { return lres; } if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && attrform != DW_FORM_sec_offset ) { _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); return (DW_DLV_ERROR); } lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); if (lres != DW_DLV_OK) { return lres; } if (line_offset >= dbg->de_debug_line.dss_size) { _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); return (DW_DLV_ERROR); } orig_line_ptr = dbg->de_debug_line.dss_data; line_ptr = dbg->de_debug_line.dss_data + line_offset; dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); /* If die has DW_AT_comp_dir attribute, get the string that names the compilation directory. */ resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); if (resattr == DW_DLV_ERROR) { return resattr; } if (resattr == DW_DLV_OK) { int cres = DW_DLV_ERROR; char *cdir = 0; cres = dwarf_formstring(comp_dir_attr, &cdir, error); if (cres == DW_DLV_ERROR) { return cres; } else if (cres == DW_DLV_OK) { comp_dir = (Dwarf_Small *) cdir; } } if (resattr == DW_DLV_OK) { dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); } dwarf_init_line_table_prefix(&prefix); { Dwarf_Small *line_ptr_out = 0; int dres = dwarf_read_line_table_prefix(dbg, line_ptr,dbg->de_debug_line.dss_size - line_offset, &line_ptr_out, &prefix, &bogus_bytes_ptr, &bogus_bytes_count, error, err_count_out); if (dres == DW_DLV_ERROR) { dwarf_free_line_table_prefix(&prefix); return dres; } if (dres == DW_DLV_NO_ENTRY) { dwarf_free_line_table_prefix(&prefix); return dres; } line_ptr_end = prefix.pf_line_ptr_end; line_ptr = line_ptr_out; } if(only_line_header) { /* Just checking for header errors, nothing more here.*/ dwarf_free_line_table_prefix(&prefix); return DW_DLV_OK; } printf("total line info length %ld bytes, " "line offset 0x%" DW_PR_DUx " %" DW_PR_DSd "\n", (long) prefix.pf_total_length, (Dwarf_Unsigned) line_offset, (Dwarf_Signed) line_offset); printf("line table version %d\n",(int) prefix.pf_version); printf("line table length field length %d prologue length %d\n", (int)prefix.pf_length_field_length, (int)prefix.pf_prologue_length); printf("compilation_directory %s\n", comp_dir ? ((char *) comp_dir) : ""); printf(" min instruction length %d\n", (int) prefix.pf_minimum_instruction_length); printf(" default is stmt %d\n", (int) prefix.pf_default_is_stmt); printf(" line base %d\n", (int) prefix.pf_line_base); printf(" line_range %d\n", (int) prefix.pf_line_range); printf(" opcode base %d\n", (int) prefix.pf_opcode_base); printf(" standard opcode count %d\n", (int) prefix.pf_std_op_count); for (i = 1; i < prefix.pf_opcode_base; i++) { printf(" opcode[%2d] length %d\n", (int) i, (int) prefix.pf_opcode_length_table[i - 1]); } printf(" include directories count %d\n", (int) prefix.pf_include_directories_count); for (i = 0; i < prefix.pf_include_directories_count; ++i) { printf(" include dir[%d] %s\n", (int) i, prefix.pf_include_directories[i]); } printf(" files count %d\n", (int) prefix.pf_files_count); for (i = 0; i < prefix.pf_files_count; ++i) { struct Line_Table_File_Entry_s *lfile = prefix.pf_line_table_file_entries + i; Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time; Dwarf_Unsigned di = lfile->lte_directory_index; Dwarf_Unsigned fl = lfile->lte_length_of_file; printf(" file[%d] %s (file-number: %d) \n", (int) i, (char *) lfile->lte_filename, (int)(i+1)); printf(" dir index %d\n", (int) di); { time_t tt = (time_t) tlm2; printf(" last time 0x%x %s", /* ctime supplies newline */ (unsigned) tlm2, ctime(&tt)); } printf(" file length %ld 0x%lx\n", (long) fl, (unsigned long) fl); } { Dwarf_Unsigned offset = 0; if(bogus_bytes_count > 0) { Dwarf_Unsigned wcount = bogus_bytes_count; Dwarf_Unsigned boffset = bogus_bytes_ptr - orig_line_ptr; printf("*** DWARF CHECK: the line table prologue header_length " " is %" DW_PR_DUu " too high, we pretend it is smaller." "Section offset: %" DW_PR_DUu " (0x%" DW_PR_DUx ") ***\n", wcount, boffset,boffset); *err_count_out += 1; } offset = line_ptr - orig_line_ptr; printf(" statement prog offset in section: %" DW_PR_DUu " 0x%" DW_PR_DUx "\n", offset, offset); } /* Initialize the part of the state machine dependent on the prefix. */ is_stmt = prefix.pf_default_is_stmt; print_line_header(); /* Start of statement program. */ while (line_ptr < line_ptr_end) { int type = 0; printf(" [0x%06" DW_PR_DSx "] ", (Dwarf_Signed) (line_ptr - orig_line_ptr)); opcode = *(Dwarf_Small *) line_ptr; line_ptr++; /* 'type' is the output */ WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, prefix.pf_opcode_length_table, line_ptr, prefix.pf_std_op_count); if (type == LOP_DISCARD) { int oc; int opcnt = prefix.pf_opcode_length_table[opcode]; printf("*** DWARF CHECK: DISCARD standard opcode %d " "with %d operands: " "not understood.", opcode, opcnt); *err_count_out += 1; for (oc = 0; oc < opcnt; oc++) { /* * Read and discard operands we don't * understand. * Arbitrary choice of unsigned read. * Signed read would work as well. */ Dwarf_Unsigned utmp2; DECODE_LEB128_UWORD(line_ptr, utmp2); printf(" %" DW_PR_DUu " (0x%" DW_PR_DUx ")", (Dwarf_Unsigned) utmp2, (Dwarf_Unsigned) utmp2); } printf("***\n"); /* do nothing, necessary ops done */ } else if (type == LOP_SPECIAL) { /* This op code is a special op in the object, no matter that it might fall into the standard op range in this compile Thatis, these are special opcodes between special_opcode_base and MAX_LINE_OP_CODE. (including special_opcode_base and MAX_LINE_OP_CODE) */ char special[50]; unsigned origop = opcode; opcode = opcode - prefix.pf_opcode_base; address = address + prefix.pf_minimum_instruction_length * (opcode / prefix.pf_line_range); line = line + prefix.pf_line_base + opcode % prefix.pf_line_range; sprintf(special, "Specialop %3u", origop); print_line_detail(special, opcode, address, (int) file, line, column, is_stmt, basic_block, end_sequence, prologue_end, epilogue_begin, isa); basic_block = false; } else if (type == LOP_STANDARD) { switch (opcode) { case DW_LNS_copy:{ print_line_detail("DW_LNS_copy", opcode, address, file, line, column, is_stmt, basic_block, end_sequence, prologue_end, epilogue_begin, isa); basic_block = false; break; } case DW_LNS_advance_pc:{ Dwarf_Unsigned utmp2; DECODE_LEB128_UWORD(line_ptr, utmp2); printf("DW_LNS_advance_pc val %" DW_PR_DSd " 0x%" DW_PR_DUx "\n", (Dwarf_Signed) (Dwarf_Word) utmp2, (Dwarf_Unsigned) (Dwarf_Word) utmp2); leb128_num = (Dwarf_Word) utmp2; address = address + prefix.pf_minimum_instruction_length * leb128_num; break; } case DW_LNS_advance_line:{ Dwarf_Signed stmp; DECODE_LEB128_SWORD(line_ptr, stmp); advance_line = (Dwarf_Sword) stmp; printf("DW_LNS_advance_line val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", (Dwarf_Signed) advance_line, (Dwarf_Signed) advance_line); line = line + advance_line; break; } case DW_LNS_set_file:{ Dwarf_Unsigned utmp2; DECODE_LEB128_UWORD(line_ptr, utmp2); file = (Dwarf_Word) utmp2; printf("DW_LNS_set_file %ld\n", (long) file); break; } case DW_LNS_set_column:{ Dwarf_Unsigned utmp2; DECODE_LEB128_UWORD(line_ptr, utmp2); column = (Dwarf_Word) utmp2; printf("DW_LNS_set_column val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", (Dwarf_Signed) column, (Dwarf_Signed) column); break; } case DW_LNS_negate_stmt:{ is_stmt = !is_stmt; printf("DW_LNS_negate_stmt\n"); break; } case DW_LNS_set_basic_block:{ printf("DW_LNS_set_basic_block\n"); basic_block = true; break; } case DW_LNS_const_add_pc:{ opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; address = address + prefix.pf_minimum_instruction_length * (opcode / prefix. pf_line_range); printf("DW_LNS_const_add_pc new address 0x%" DW_PR_DSx "\n", (Dwarf_Signed) address); break; } case DW_LNS_fixed_advance_pc:{ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, line_ptr, sizeof(Dwarf_Half)); line_ptr += sizeof(Dwarf_Half); address = address + fixed_advance_pc; printf("DW_LNS_fixed_advance_pc val %" DW_PR_DSd " 0x%" DW_PR_DSx " new address 0x%" DW_PR_DSx "\n", (Dwarf_Signed) fixed_advance_pc, (Dwarf_Signed) fixed_advance_pc, (Dwarf_Signed) address); break; } case DW_LNS_set_prologue_end:{ prologue_end = true; printf("DW_LNS_set_prologue_end set true.\n"); break; } /* New in DWARF3 */ case DW_LNS_set_epilogue_begin:{ epilogue_begin = true; printf("DW_LNS_set_epilogue_begin set true.\n"); break; } /* New in DWARF3 */ case DW_LNS_set_isa:{ Dwarf_Unsigned utmp2; DECODE_LEB128_UWORD(line_ptr, utmp2); isa = utmp2; printf("DW_LNS_set_isa new value 0x%" DW_PR_DUx ".\n", (Dwarf_Unsigned) utmp2); if (isa != utmp2) { /* The value of the isa did not fit in our local so we record it wrong. declare an error. */ dwarf_free_line_table_prefix(&prefix); _dwarf_error(dbg, error, DW_DLE_LINE_NUM_OPERANDS_BAD); return (DW_DLV_ERROR); } break; } } } else if (type == LOP_EXTENDED) { Dwarf_Unsigned utmp3 = 0; Dwarf_Word instr_length = 0; Dwarf_Small ext_opcode = 0; DECODE_LEB128_UWORD(line_ptr, utmp3); instr_length = (Dwarf_Word) utmp3; ext_opcode = *(Dwarf_Small *) line_ptr; line_ptr++; switch (ext_opcode) { case DW_LNE_end_sequence:{ end_sequence = true; print_line_detail("DW_LNE_end_sequence extended", opcode, address, file, line, column, is_stmt, basic_block, end_sequence, prologue_end, epilogue_begin, isa); address = 0; file = 1; line = 1; column = 0; is_stmt = prefix.pf_default_is_stmt; basic_block = false; end_sequence = false; prologue_end = false; epilogue_begin = false; break; } case DW_LNE_set_address:{ { READ_UNALIGNED(dbg, address, Dwarf_Addr, line_ptr, die->di_cu_context->cc_address_size); line_ptr += die->di_cu_context->cc_address_size; printf("DW_LNE_set_address address 0x%" DW_PR_DUx "\n", (Dwarf_Unsigned) address); } break; } case DW_LNE_define_file:{ Dwarf_Unsigned di = 0; Dwarf_Unsigned tlm = 0; Dwarf_Unsigned fl = 0; Dwarf_Small *fn = (Dwarf_Small *) line_ptr; line_ptr = line_ptr + strlen((char *) line_ptr) + 1; di = _dwarf_decode_u_leb128(line_ptr, &leb128_length); line_ptr = line_ptr + leb128_length; tlm = _dwarf_decode_u_leb128(line_ptr, &leb128_length); line_ptr = line_ptr + leb128_length; fl = _dwarf_decode_u_leb128(line_ptr, &leb128_length); line_ptr = line_ptr + leb128_length; printf("DW_LNE_define_file %s \n", fn); printf(" dir index %d\n", (int) di); { time_t tt3 = (time_t) tlm; /* ctime supplies newline */ printf(" last time 0x%x %s", (unsigned) tlm, ctime(&tt3)); } printf(" file length %ld 0x%lx\n", (long) fl, (unsigned long) fl); break; } default:{ /* This is an extended op code we do not know about, other than we know now many bytes it is (and the op code and the bytes of operand). */ Dwarf_Unsigned remaining_bytes = instr_length -1; if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) { dwarf_free_line_table_prefix(&prefix); _dwarf_error(dbg, error, DW_DLE_LINE_EXT_OPCODE_BAD); return (DW_DLV_ERROR); } printf("DW_LNE extended op 0x%x ",ext_opcode); printf("Bytecount: " DW_PR_DUu , instr_length); if(remaining_bytes > 0) { printf(" linedata: 0x"); while (remaining_bytes > 0) { printf("%02x",(unsigned char)(*(line_ptr))); line_ptr++; remaining_bytes--; } } printf("\n"); } break; } } } dwarf_free_line_table_prefix(&prefix); return (DW_DLV_OK); }
/* return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR If err_count_out is non-NULL, this is a special 'check' call. */ static int _dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error, int * err_count_out, int only_line_header) { /* This pointer is used to scan the portion of the .debug_line section for the current cu. */ Dwarf_Small *line_ptr = 0; Dwarf_Small *orig_line_ptr = 0; /* Pointer to a DW_AT_stmt_list attribute in case it exists in the die. */ Dwarf_Attribute stmt_list_attr = 0; /* Pointer to DW_AT_comp_dir attribute in die. */ Dwarf_Attribute comp_dir_attr = 0; /* Pointer to name of compilation directory. */ Dwarf_Small *comp_dir = NULL; /* Offset into .debug_line specified by a DW_AT_stmt_list attribute. */ Dwarf_Unsigned line_offset = 0; Dwarf_Sword i=0; Dwarf_Word u=0; /* These variables are used to decode leb128 numbers. Leb128_num holds the decoded number, and leb128_length is its length in bytes. */ Dwarf_Half attrform = 0; /* In case there are wierd bytes 'after' the line table prologue this lets us print something. This is a gcc compiler bug and we expect the bytes count to be 12. */ Dwarf_Small* bogus_bytes_ptr = 0; Dwarf_Unsigned bogus_bytes_count = 0; Dwarf_Half address_size = 0; Dwarf_Unsigned fission_offset = 0; /* The Dwarf_Debug this die belongs to. */ Dwarf_Debug dbg=0; Dwarf_CU_Context cu_context = 0; Dwarf_Line_Context line_context = 0; int resattr = DW_DLV_ERROR; int lres = DW_DLV_ERROR; int res = DW_DLV_ERROR; Dwarf_Small *line_ptr_actuals = 0; Dwarf_Small *line_ptr_end = 0; Dwarf_Small *section_start = 0; /* ***** BEGIN CODE ***** */ if (error != NULL) { *error = NULL; } CHECK_DIE(die, DW_DLV_ERROR); cu_context = die->di_cu_context; dbg = cu_context->cc_dbg; res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); if (res != DW_DLV_OK) { return res; } if (!dbg->de_debug_line.dss_size) { return (DW_DLV_NO_ENTRY); } address_size = _dwarf_get_address_size(dbg, die); resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); if (resattr != DW_DLV_OK) { return resattr; } /* The list of relevant FORMs is small. DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset */ lres = dwarf_whatform(stmt_list_attr,&attrform,error); if (lres != DW_DLV_OK) { return lres; } if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && attrform != DW_FORM_sec_offset ) { _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); return (DW_DLV_ERROR); } lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); if (lres != DW_DLV_OK) { return lres; } if (line_offset >= dbg->de_debug_line.dss_size) { _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); return (DW_DLV_ERROR); } section_start = dbg->de_debug_line.dss_data; { Dwarf_Unsigned fission_size = 0; int resfis = _dwarf_get_fission_addition_die(die, DW_SECT_LINE, &fission_offset,&fission_size,error); if(resfis != DW_DLV_OK) { return resfis; } } orig_line_ptr = section_start + line_offset + fission_offset; line_ptr = orig_line_ptr; dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); /* If die has DW_AT_comp_dir attribute, get the string that names the compilation directory. */ resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); if (resattr == DW_DLV_ERROR) { return resattr; } if (resattr == DW_DLV_OK) { int cres = DW_DLV_ERROR; char *cdir = 0; cres = dwarf_formstring(comp_dir_attr, &cdir, error); if (cres == DW_DLV_ERROR) { return cres; } else if (cres == DW_DLV_OK) { comp_dir = (Dwarf_Small *) cdir; } } if (resattr == DW_DLV_OK) { dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); } line_context = (Dwarf_Line_Context) _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1); if (line_context == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } { Dwarf_Small *newlinep = 0; int dres = _dwarf_read_line_table_header(dbg, cu_context, section_start, line_ptr, dbg->de_debug_line.dss_size, &newlinep, line_context, &bogus_bytes_ptr, &bogus_bytes_count, error, err_count_out); if (dres == DW_DLV_ERROR) { dwarf_srclines_dealloc_b(line_context); return dres; } if (dres == DW_DLV_NO_ENTRY) { dwarf_srclines_dealloc_b(line_context); return dres; } line_ptr_end = line_context->lc_line_ptr_end; line_ptr = newlinep; if (line_context->lc_actuals_table_offset > 0) { line_ptr_actuals = line_context->lc_line_prologue_start + line_context->lc_actuals_table_offset; } } line_context->lc_compilation_directory = comp_dir; if (only_line_header) { /* Just checking for header errors, nothing more here.*/ dwarf_srclines_dealloc_b(line_context); return DW_DLV_OK; } dwarf_printf(dbg, "total line info length %ld bytes," " line offset 0x%" DW_PR_XZEROS DW_PR_DUx " %" DW_PR_DUu "\n", (long) line_context->lc_total_length, line_context->lc_section_offset, line_context->lc_section_offset); if (line_context->lc_version_number <= DW_LINE_VERSION5) { dwarf_printf(dbg, "line table version %d\n",(int) line_context->lc_version_number); } else { dwarf_printf(dbg, "line table version 0x%x\n",(int) line_context->lc_version_number); } dwarf_printf(dbg, "line table length field length %d prologue length %d\n", (int)line_context->lc_length_field_length, (int)line_context->lc_prologue_length); dwarf_printf(dbg, "compilation_directory %s\n", comp_dir ? ((char *) comp_dir) : ""); dwarf_printf(dbg, " min instruction length %d\n", (int) line_context->lc_minimum_instruction_length); if (line_context->lc_version_number == EXPERIMENTAL_LINE_TABLES_VERSION) { dwarf_printf(dbg, " actuals table offset " "0x%" DW_PR_XZEROS DW_PR_DUx " logicals table offset " "0x%" DW_PR_XZEROS DW_PR_DUx "\n", line_context->lc_actuals_table_offset, line_context->lc_logicals_table_offset); } if (line_context->lc_version_number == DW_LINE_VERSION5) { dwarf_printf(dbg, " segment selector size %d\n", (int) line_context->lc_segment_selector_size); dwarf_printf(dbg, " address size %d\n", (int) line_context->lc_address_size); } dwarf_printf(dbg, " default is stmt %d\n",(int)line_context->lc_default_is_stmt); dwarf_printf(dbg, " line base %d\n",(int)line_context->lc_line_base); dwarf_printf(dbg, " line_range %d\n",(int)line_context->lc_line_range); dwarf_printf(dbg, " opcode base %d\n",(int)line_context->lc_opcode_base); dwarf_printf(dbg, " standard opcode count %d\n",(int)line_context->lc_std_op_count); for (i = 1; i < line_context->lc_opcode_base; i++) { dwarf_printf(dbg, " opcode[%2d] length %d\n", (int) i, (int) line_context->lc_opcode_length_table[i - 1]); } dwarf_printf(dbg, " include directories count %d\n", (int) line_context->lc_include_directories_count); for (u = 0; u < line_context->lc_include_directories_count; ++u) { dwarf_printf(dbg, " include dir[%u] %s\n", (int) u, line_context->lc_include_directories[u]); } dwarf_printf(dbg, " files count %d\n", (int) line_context->lc_file_entry_count); if (line_context->lc_file_entry_count) { Dwarf_File_Entry fe = line_context->lc_file_entries; Dwarf_File_Entry fe2 = fe; unsigned fiu = 0; for (fiu = 0 ; fe2 ; fe2 = fe->fi_next,++fiu ) { Dwarf_Unsigned tlm2 = 0; Dwarf_Unsigned di = 0; Dwarf_Unsigned fl = 0; fe = fe2; tlm2 = fe->fi_time_last_mod; di = fe->fi_dir_index; fl = fe->fi_file_length; dwarf_printf(dbg, " file[%u] %s (file-number: %u) \n", (unsigned) fiu, (char *) fe->fi_file_name, (unsigned)(fiu+1)); dwarf_printf(dbg, " dir index %d\n", (int) di); { time_t tt = (time_t) tlm2; /* ctime supplies newline */ dwarf_printf(dbg, " last time 0x%x %s", (unsigned) tlm2, ctime(&tt)); } dwarf_printf(dbg, " file length %ld 0x%lx\n", (long) fl, (unsigned long) fl); } } if (line_context->lc_version_number == EXPERIMENTAL_LINE_TABLES_VERSION) { /* Print the subprograms list. */ Dwarf_Unsigned count = line_context->lc_subprogs_count; Dwarf_Unsigned exu = 0; Dwarf_Subprog_Entry sub = line_context->lc_subprogs; dwarf_printf(dbg," subprograms count" " %" DW_PR_DUu "\n",count); if (count > 0) { dwarf_printf(dbg," indx file line name\n"); } for (exu = 0 ; exu < count ; exu++,sub++) { dwarf_printf(dbg," [%2" DW_PR_DUu "] %4" DW_PR_DUu " %4" DW_PR_DUu " %s\n", exu+1, sub->ds_decl_file, sub->ds_decl_line, sub->ds_subprog_name); } } { Dwarf_Unsigned offset = 0; if (bogus_bytes_count > 0) { Dwarf_Unsigned wcount = bogus_bytes_count; Dwarf_Unsigned boffset = bogus_bytes_ptr - section_start; dwarf_printf(dbg, "*** DWARF CHECK: the line table prologue header_length " " is %" DW_PR_DUu " too high, we pretend it is smaller." "Section offset: 0x%" DW_PR_XZEROS DW_PR_DUx " (%" DW_PR_DUu ") ***\n", wcount, boffset,boffset); *err_count_out += 1; } offset = line_ptr - section_start; dwarf_printf(dbg, " statement prog offset in section: 0x%" DW_PR_XZEROS DW_PR_DUx " (%" DW_PR_DUu ")\n", offset, offset); } { Dwarf_Bool doaddrs = false; Dwarf_Bool dolines = true; _dwarf_print_line_context_record(dbg,line_context); if (!line_ptr_actuals) { /* Normal single level line table. */ Dwarf_Bool is_single_table = true; Dwarf_Bool is_actuals_table = false; print_line_header(dbg, is_single_table, is_actuals_table); res = read_line_table_program(dbg, line_ptr, line_ptr_end, orig_line_ptr, section_start, line_context, address_size, doaddrs, dolines, is_single_table, is_actuals_table, error, err_count_out); if (res != DW_DLV_OK) { dwarf_srclines_dealloc_b(line_context); return res; } } else { Dwarf_Bool is_single_table = false; Dwarf_Bool is_actuals_table = false; if (line_context->lc_version_number != EXPERIMENTAL_LINE_TABLES_VERSION) { dwarf_srclines_dealloc_b(line_context); _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); return (DW_DLV_ERROR); } /* Read Logicals */ print_line_header(dbg, is_single_table, is_actuals_table); res = read_line_table_program(dbg, line_ptr, line_ptr_actuals, orig_line_ptr, section_start, line_context, address_size, doaddrs, dolines, is_single_table, is_actuals_table, error,err_count_out); if (res != DW_DLV_OK) { dwarf_srclines_dealloc_b(line_context); return res; } if (line_context->lc_actuals_table_offset > 0) { is_actuals_table = true; /* Read Actuals */ print_line_header(dbg, is_single_table, is_actuals_table); res = read_line_table_program(dbg, line_ptr_actuals, line_ptr_end, orig_line_ptr, section_start, line_context, address_size, doaddrs, dolines, is_single_table, is_actuals_table, error, err_count_out); if (res != DW_DLV_OK) { dwarf_srclines_dealloc_b(line_context); return res; } } } } dwarf_srclines_dealloc_b(line_context); return DW_DLV_OK; }
/** * Finds a function name in DWARF DIE (Debug Information Entry). * For more info on DWARF format, see http://www.dwarfstd.org/Download.php , http://www.ibm.com/developerworks/library/os-debugging/ * * @return true if we need to stop search (i.e. either found it or some error happened) */ bool FindFunctionNameInDIE(Dwarf_Debug DebugInfo, Dwarf_Die Die, Dwarf_Addr Addr, const char **OutFuncName) { Dwarf_Error ErrorInfo; Dwarf_Half Tag; Dwarf_Unsigned LowerPC, HigherPC; char *TempFuncName; int ReturnCode; if (dwarf_tag(Die, &Tag, &ErrorInfo) != DW_DLV_OK || Tag != DW_TAG_subprogram || dwarf_attrval_unsigned(Die, DW_AT_low_pc, &LowerPC, &ErrorInfo) != DW_DLV_OK || dwarf_attrval_unsigned(Die, DW_AT_high_pc, &HigherPC, &ErrorInfo) != DW_DLV_OK || Addr < LowerPC || HigherPC <= Addr ) { return false; } // found it *OutFuncName = NULL; Dwarf_Attribute SubAt; ReturnCode = dwarf_attr(Die, DW_AT_name, &SubAt, &ErrorInfo); if (ReturnCode == DW_DLV_ERROR) { return true; // error, but stop the search } else if (ReturnCode == DW_DLV_OK) { if (dwarf_formstring(SubAt, &TempFuncName, &ErrorInfo)) { *OutFuncName = NULL; } else { *OutFuncName = TempFuncName; } return true; } // DW_AT_Name is not present, look in DW_AT_specification Dwarf_Attribute SpecAt; if (dwarf_attr(Die, DW_AT_specification, &SpecAt, &ErrorInfo)) { // not found, tough luck return false; } Dwarf_Off Offset; if (dwarf_global_formref(SpecAt, &Offset, &ErrorInfo)) { return false; } Dwarf_Die SpecDie; if (dwarf_offdie(DebugInfo, Offset, &SpecDie, &ErrorInfo)) { return false; } if (dwarf_attrval_string(SpecDie, DW_AT_name, OutFuncName, &ErrorInfo)) { *OutFuncName = NULL; } return true; }
/* 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; }
static int get_type(Dwarf_Debug dbg, Dwarf_Die die) { Dwarf_Attribute attr; Dwarf_Off off; Dwarf_Die type_die; Dwarf_Half tag; int ret; ret = dwarf_attr(die, DW_AT_type, &attr, NULL); if (ret == DW_DLV_ERROR) { fprintf(stderr, "SET dwarf: Error in dwarf_attr()\n"); return 1; } if (ret == DW_DLV_NO_ENTRY) return 0; /* "DW_AT_type" is of the form "DW_FORM_ref4" */ ret = dwarf_global_formref(attr, &off, NULL); dwarf_dealloc(dbg, attr, DW_DLA_ATTR); if (ret != DW_DLV_OK) { fprintf(stderr, "SET dwarf: Error in dwarf_global_formref()\n"); return 1; } /* Get the referenced DIE which is the type of "die" */ ret = dwarf_offdie(dbg, off, &type_die, NULL); if (ret != DW_DLV_OK) { fprintf(stderr, "SET dwarf: Error in dwarf_offdie()\n"); return 1; } /* Get the type */ ret = dwarf_tag(type_die, &tag, NULL); if (ret != DW_DLV_OK) { fprintf(stderr, "SET dwarf: Error in dwarf_tag()\n"); dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 1; } switch (tag) { case DW_TAG_base_type: ret = get_size(dbg, type_die); if (ret != 0) { dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 1; } break; case DW_TAG_pointer_type: /* Recursive call */ /* FIXME */ // get_type(dbg, type_die); ret = get_size(dbg, type_die); if (ret != 0) { dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 1; } break; case DW_TAG_structure_type: ret = get_size(dbg, type_die); if (ret != 0) { dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 1; } break; case DW_TAG_union_type: ret = get_size(dbg, type_die); if (ret != 0) { dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 1; } break; case DW_TAG_enumeration_type: ret = get_size(dbg, type_die); if (ret != 0) { dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 1; } break; /* The types above have "DW_AT_byte_size" */ case DW_TAG_subroutine_type: /* function pointer */ /* FIXME: Can be transformed to the real function by runtime address */ break; case DW_TAG_typedef: case DW_TAG_const_type: case DW_TAG_volatile_type: ret = get_type(dbg, type_die); if (ret != 0) { dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 1; } break; default: dwarf_dealloc(dbg, type_die, DW_DLA_DIE); fprintf(stderr, "SET dwarf: Unspecified type\n"); return 1; } dwarf_dealloc(dbg, type_die, DW_DLA_DIE); return 0; }
QVariant DwarfDie::attributeLocal(Dwarf_Half attributeType) const { Dwarf_Attribute attr; auto res = dwarf_attr(m_die, attributeType, &attr, nullptr); if (res != DW_DLV_OK) return {}; Dwarf_Half formType; res = dwarf_whatform(attr, &formType, nullptr); if (res != DW_DLV_OK) return {}; QVariant value; switch (formType) { case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_udata: { Dwarf_Unsigned n; res = dwarf_formudata(attr, &n, nullptr); value = n; break; } case DW_FORM_sdata: { Dwarf_Signed n; res = dwarf_formsdata(attr, &n, nullptr); value = n; break; } case DW_FORM_string: case DW_FORM_strp: { char *str; res = dwarf_formstring(attr, &str, nullptr); value = QByteArray(str); break; } case DW_FORM_flag: case DW_FORM_flag_present: { Dwarf_Bool b; res = dwarf_formflag(attr, &b, nullptr); value = b ? true : false; break; } case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: { Dwarf_Off offset; res = dwarf_global_formref(attr, &offset, nullptr); value = QVariant::fromValue(dwarfInfo()->dieAtOffset(offset)); break; } case DW_FORM_sec_offset: { Dwarf_Off offset; res = dwarf_global_formref(attr, &offset, nullptr); value = offset; break; } case DW_FORM_addr: { Dwarf_Addr addr; res = dwarf_formaddr(attr, &addr, nullptr); value = addr; break; } case DW_FORM_exprloc: { Dwarf_Unsigned len; Dwarf_Ptr block; res = dwarf_formexprloc(attr, &len, &block, nullptr); value = QVariant::fromValue(DwarfExpression(block, len, dwarfInfo()->elfFile()->addressSize())); break; } default: { const char* formName; res = dwarf_get_FORM_name(formType, &formName); if (res != DW_DLV_OK) return {}; value = QStringLiteral("TODO: ") + QString::fromLocal8Bit(formName); break; } } // post-process some well-known types switch (attributeType) { case DW_AT_decl_file: case DW_AT_call_file: { const auto fileIndex = value.value<Dwarf_Unsigned>(); // index 0 means not present, TODO handle that value = compilationUnit()->sourceFileForIndex(fileIndex -1); break; } case DW_AT_ranges: value = QVariant::fromValue(DwarfRanges(this, value.toLongLong())); break; case DW_AT_accessibility: stringifyEnum(value, &dwarf_get_ACCESS_name); break; case DW_AT_language: stringifyEnum(value, &dwarf_get_LANG_name); break; case DW_AT_virtuality: value = QVariant::fromValue(static_cast<DwarfVirtuality>(value.toInt())); break; case DW_AT_visibility: stringifyEnum(value, &dwarf_get_VIS_name); break; case DW_AT_identifier_case: stringifyEnum(value, &dwarf_get_ID_name); break; case DW_AT_inline: stringifyEnum(value, &dwarf_get_INL_name); break; case DW_AT_encoding: stringifyEnum(value, &dwarf_get_ATE_name); break; case DW_AT_ordering: stringifyEnum(value, &dwarf_get_ORD_name); break; case DW_AT_calling_convention: stringifyEnum(value, &dwarf_get_CC_name); break; case DW_AT_discr_list: stringifyEnum(value, &dwarf_get_DSC_name); break; default: break; } return value; }
static void show_all_attrs(Dwarf_Die die, unsigned long level, void *ndata){ Dwarf_Error error; Dwarf_Half tag; dwarf_tag(die,&tag,&error); const char *stag; dwarf_get_TAG_name(tag,&stag); Dwarf_Off off = 0x0; dwarf_die_CU_offset(die,&off,&error); fprintf(stderr,"[%u]<%x>%s\n",level,off,stag); char **sourceFiles; Dwarf_Signed num; int res; if( (res = dwarf_srcfiles(die,&sourceFiles,&num,&error)) == DW_DLV_OK){ fprintf(stderr,"Source Files Referenced:\n"); int i; for(i = 0; i < num; i++){ fprintf(stderr,"%s\n",sourceFiles[i]); dwarf_dealloc(d, sourceFiles[i],DW_DLA_STRING); } dwarf_dealloc(d, sourceFiles,DW_DLA_LIST); } Dwarf_Unsigned atcnt; Dwarf_Attribute *atlist; int errv; if((errv = dwarf_attrlist(die, &atlist, &atcnt, &error)) == DW_DLV_OK){ int i; for(i = 0; i < atcnt; i++){ Dwarf_Half attr; if(dwarf_whatattr(atlist[i],&attr,&error) == DW_DLV_OK){ const char *sattr; dwarf_get_AT_name(attr,&sattr); fprintf(stderr,"\t%s => ",sattr); }else{ fprintf(stderr,"\tCouldn't Get Attr Type!\n"); continue; } Dwarf_Half form; if(dwarf_whatform(atlist[i],&form,&error) == DW_DLV_OK){ //const char *formname; //dwarf_get_FORM_name(form,&formname); //fprintf(stderr,"[%s] ",formname); switch(form){ case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: {Dwarf_Off offset; dwarf_formref(atlist[i],&offset,&error); fprintf(stderr,"%x\n",offset);} break; case DW_FORM_ref_addr: {Dwarf_Off offset; dwarf_global_formref(atlist[i],&offset,&error); fprintf(stderr,"%x\n",offset);} break; case DW_FORM_addr: {Dwarf_Addr addr; dwarf_formaddr(atlist[i],&addr,&error); fprintf(stderr,"%x\n",addr);} break; case DW_FORM_flag: {Dwarf_Bool flag; dwarf_formflag(atlist[i],&flag,&error); fprintf(stderr,"%s\n",flag ? "True" : "False");} break; case DW_FORM_udata: case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: {Dwarf_Unsigned val; dwarf_formudata(atlist[i],&val,&error); fprintf(stderr,"%u\n",val);} break; case DW_FORM_sdata: {Dwarf_Signed val; dwarf_formsdata(atlist[i],&val,&error); fprintf(stderr,"%d\n",val);} break; case DW_FORM_block: case DW_FORM_block1: if(attr == DW_AT_location || attr == DW_AT_data_member_location || attr == DW_AT_vtable_elem_location || attr == DW_AT_string_length || attr == DW_AT_use_location || attr == DW_AT_return_addr){ /* Dwarf_Locdesc *locationList; Dwarf_Signed listLength; int ret = dwarf_loclist( atlist[i], &locationList, &listLength, &error ); int frameRel = 0; long offset = 0; decode_location(locationList,listLength,&offset,NULL,&frameRel); int i; for( i = 0; i < listLength; ++i){ dwarf_dealloc(d,locationList[i].ld_s,DW_DLA_LOC_BLOCK); } dwarf_dealloc(d,locationList,DW_DLA_LOCDESC); */ DC_location dcl; DC_get_location_attr_value(atlist[i],&dcl); fprintf(stderr," %s:",dcl.isFrameOffset ? "FP Offset" : "Address"); fprintf(stderr," %ld\n",dcl.offset); }else{ fprintf(stderr,"UNSUPPORTED ATTRIBUTE TYPE\n"); } break; case DW_FORM_string: {char *val; dwarf_formstring(atlist[i],&val,&error); fprintf(stderr,"%s\n",val);} break; case DW_FORM_strp: {char *str; if( (dwarf_formstring(atlist[i],&str,&error) == DW_DLV_OK) ){ fprintf(stderr,"%s\n",str); } } break; default: fprintf(stderr,"Unhandled Attribute Form!\n"); break; }; } dwarf_dealloc(d, atlist[i], DW_DLA_ATTR); } dwarf_dealloc(d, atlist, DW_DLA_LIST); } }
static void search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, char **rlt_func) { Dwarf_Die ret_die, spec_die; Dwarf_Error de; Dwarf_Half tag; Dwarf_Unsigned lopc, hipc; Dwarf_Off ref; Dwarf_Attribute sub_at, spec_at; char *func0; const char *func1; int ret; if (*rlt_func != NULL) goto done; if (dwarf_tag(die, &tag, &de)) { warnx("dwarf_tag: %s", dwarf_errmsg(de)); goto cont_search; } if (tag == DW_TAG_subprogram) { if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) || dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) goto cont_search; if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) goto cont_search; if (addr < lopc || addr >= hipc) goto cont_search; /* Found it! */ if ((*rlt_func = strdup(unknown)) == NULL) err(EXIT_FAILURE, "strdup"); ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); if (ret == DW_DLV_ERROR) goto done; if (ret == DW_DLV_OK) { if (dwarf_formstring(sub_at, &func0, &de) == DW_DLV_OK) { free(*rlt_func); if ((*rlt_func = strdup(func0)) == NULL) err(EXIT_FAILURE, "strdup"); } goto done; } /* * If DW_AT_name is not present, but DW_AT_specification is * present, then probably the actual name is in the DIE * referenced by DW_AT_specification. */ if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) goto done; if (dwarf_global_formref(spec_at, &ref, &de)) goto done; if (dwarf_offdie(dbg, ref, &spec_die, &de)) goto done; if (dwarf_attrval_string(spec_die, DW_AT_name, &func1, &de) == DW_DLV_OK) { free(*rlt_func); if ((*rlt_func = strdup(func1)) == NULL) err(EXIT_FAILURE, "strdup"); } goto done; } cont_search: /* Search children. */ ret = dwarf_child(die, &ret_die, &de); if (ret == DW_DLV_ERROR) errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_func(dbg, ret_die, addr, rlt_func); /* Search sibling. */ ret = dwarf_siblingof(dbg, die, &ret_die, &de); if (ret == DW_DLV_ERROR) errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_func(dbg, ret_die, addr, rlt_func); done: dwarf_dealloc(dbg, die, DW_DLA_DIE); }
static VALUE rd_attr_raw_value(VALUE self) { rd_attr_t *attr = GetAttr(self); Dwarf_Half form; Dwarf_Error err; union { Dwarf_Addr addr; Dwarf_Off off; Dwarf_Unsigned udata; Dwarf_Signed sdata; Dwarf_Bool bool; char *str; } val; VALUE top; chkerr1(dwarf_whatform(attr->attr, &form, &err), &err, self); switch (form) { case DW_FORM_addr: chkerr1(dwarf_formaddr(attr->attr, &val.addr, &err), &err, self); return ULL2NUM(val.addr); case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: chkerr1(dwarf_global_formref(attr->attr, &val.off, &err), &err, self); top = rb_ivar_get(self, id_at_top); return rdwarf_die_at(top, LL2NUM(val.off)); case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_udata: chkerr1(dwarf_formudata(attr->attr, &val.udata, &err), &err, self); return ULL2NUM(val.udata); case DW_FORM_sdata: chkerr1(dwarf_formsdata(attr->attr, &val.sdata, &err), &err, self); return LL2NUM(val.sdata); case DW_FORM_flag: chkerr1(dwarf_formflag(attr->attr, &val.bool, &err), &err, self); return val.bool ? Qtrue : Qfalse; case DW_FORM_strp: case DW_FORM_string: chkerr1(dwarf_formstring(attr->attr, &val.str, &err), &err, self); return rb_str_new_cstr(val.str); } return sym_unsupported_type; }