void DWARFDebugRanges::Dump(Stream &s, const DataExtractor& debug_ranges_data, uint32_t* offset_ptr, dw_addr_t cu_base_addr) { uint32_t addr_size = s.GetAddressByteSize(); bool verbose = s.GetVerbose(); dw_addr_t base_addr = cu_base_addr; while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits // of ones if (begin == 0xFFFFFFFFull && addr_size == 4) begin = DW_INVALID_ADDRESS; s.Indent(); if (verbose) { s.AddressRange(begin, end, sizeof (dw_addr_t), " offsets = "); } if (begin == 0 && end == 0) { s.PutCString(" End"); break; } else if (begin == DW_INVALID_ADDRESS) { // A base address selection entry base_addr = end; s.Address(base_addr, sizeof (dw_addr_t), " Base address = "); } else { // Convert from offset to an address dw_addr_t begin_addr = begin + base_addr; dw_addr_t end_addr = end + base_addr; s.AddressRange(begin_addr, end_addr, sizeof (dw_addr_t), verbose ? " ==> addrs = " : NULL); } } }
//---------------------------------------------------------------------- // DumpCallback // // A callback function for the static DWARFDebugInfo::Parse() function // that gets called each time a compile unit header or debug information // entry is successfully parsed. // // This function dump DWARF information and obey recurse depth and // whether a single DIE is to be dumped (or all of the data). //---------------------------------------------------------------------- static dw_offset_t DumpCallback ( SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu, DWARFDebugInfoEntry* die, const dw_offset_t next_offset, const uint32_t curr_depth, void* userData ) { DumpInfo* dumpInfo = (DumpInfo*)userData; Stream *s = dumpInfo->strm; bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); if (die) { // Are we dumping everything? if (dumpInfo->die_offset == DW_INVALID_OFFSET) { // Yes we are dumping everything. Obey our recurse level though if (curr_depth < dumpInfo->recurse_depth) die->Dump(dwarf2Data, cu, *s, 0); } else { // We are dumping a specific DIE entry by offset if (dumpInfo->die_offset == die->GetOffset()) { // We found the DIE we were looking for, dump it! if (show_parents) { s->SetIndentLevel(0); const uint32_t num_ancestors = dumpInfo->ancestors.size(); if (num_ancestors > 0) { for (uint32_t i=0; i<num_ancestors-1; ++i) { dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0); s->IndentMore(); } } } dumpInfo->found_depth = curr_depth; die->Dump(dwarf2Data, cu, *s, 0); // Note that we found the DIE we were looking for dumpInfo->found_die = true; // Since we are dumping a single DIE, if there are no children we are done! if (!die->HasChildren() || dumpInfo->recurse_depth == 0) return DW_INVALID_OFFSET; // Return an invalid address to end parsing } else if (dumpInfo->found_die) { // Are we done with all the children? if (curr_depth <= dumpInfo->found_depth) return DW_INVALID_OFFSET; // We have already found our DIE and are printing it's children. Obey // our recurse depth and return an invalid offset if we get done // dumping all of the children if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth) die->Dump(dwarf2Data, cu, *s, 0); } else if (dumpInfo->die_offset > die->GetOffset()) { if (show_parents) dumpInfo->ancestors.back() = *die; } } // Keep up with our indent level if (die->IsNULL()) { if (show_parents) dumpInfo->ancestors.pop_back(); if (curr_depth <= 1) return cu->GetNextCompileUnitOffset(); else s->IndentLess(); } else if (die->HasChildren()) { if (show_parents) { DWARFDebugInfoEntry null_die; dumpInfo->ancestors.push_back(null_die); } s->IndentMore(); } } else { if (cu == NULL) s->PutCString("NULL - cu"); // We have a compile unit, reset our indent level to zero just in case s->SetIndentLevel(0); // See if we are dumping everything? if (dumpInfo->die_offset == DW_INVALID_OFFSET) { // We are dumping everything if (cu) { cu->Dump(s); return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit } else { return DW_INVALID_OFFSET; } } else { if (show_parents) { dumpInfo->ancestors.clear(); dumpInfo->ancestors.resize(1); } // We are dumping only a single DIE possibly with it's children and // we must find it's compile unit before we can dump it properly if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) { // Not found, maybe the DIE offset provided wasn't correct? // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl; return DW_INVALID_OFFSET; } else { // See if the DIE is in this compile unit? if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) { // This DIE is in this compile unit! if (s->GetVerbose()) cu->Dump(s); // Dump the compile unit for the DIE in verbose mode return next_offset; // // We found our compile unit that contains our DIE, just skip to dumping the requested DIE... // return dumpInfo->die_offset; } else { // Skip to the next compile unit as the DIE isn't in the current one! if (cu) { return cu->GetNextCompileUnitOffset(); } else { return DW_INVALID_OFFSET; } } } } } // Just return the current offset to parse the next CU or DIE entry return next_offset; }
void DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const DWARFCompileUnit* cu) const { uint64_t uvalue = Unsigned(); bool cu_relative_offset = false; bool verbose = s.GetVerbose(); switch (m_form) { case DW_FORM_addr: s.Address(uvalue, sizeof (uint64_t)); break; case DW_FORM_flag: case DW_FORM_data1: s.PutHex8(uvalue); break; case DW_FORM_data2: s.PutHex16(uvalue); break; case DW_FORM_sec_offset: case DW_FORM_data4: s.PutHex32(uvalue); break; case DW_FORM_ref_sig8: case DW_FORM_data8: s.PutHex64(uvalue); break; case DW_FORM_string: s.QuotedCString(AsCString(NULL)); break; case DW_FORM_exprloc: case DW_FORM_block: case DW_FORM_block1: case DW_FORM_block2: case DW_FORM_block4: if (uvalue > 0) { switch (m_form) { case DW_FORM_exprloc: case DW_FORM_block: s.Printf("<0x%" PRIx64 "> ", uvalue); break; case DW_FORM_block1: s.Printf("<0x%2.2x> ", (uint8_t)uvalue); break; case DW_FORM_block2: s.Printf("<0x%4.4x> ", (uint16_t)uvalue); break; case DW_FORM_block4: s.Printf("<0x%8.8x> ", (uint32_t)uvalue); break; default: break; } const uint8_t* data_ptr = m_value.data; if (data_ptr) { const uint8_t* end_data_ptr = data_ptr + uvalue; // uvalue contains size of block while (data_ptr < end_data_ptr) { s.Printf("%2.2x ", *data_ptr); ++data_ptr; } } else s.PutCString("NULL"); } break; case DW_FORM_sdata: s.PutSLEB128(uvalue); break; case DW_FORM_udata: s.PutULEB128(uvalue); break; case DW_FORM_strp: if (debug_str_data) { if (verbose) s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); const char* dbg_str = AsCString(debug_str_data); if (dbg_str) s.QuotedCString(dbg_str); } else { s.PutHex32(uvalue); } break; case DW_FORM_ref_addr: { if (cu->GetVersion() <= 2) s.Address(uvalue, sizeof (uint64_t) * 2); else s.Address(uvalue, 4 * 2);// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet break; } case DW_FORM_ref1: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%2.2x", (uint8_t)uvalue); break; case DW_FORM_ref2: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%4.4x", (uint16_t)uvalue); break; case DW_FORM_ref4: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%4.4x", (uint32_t)uvalue); break; case DW_FORM_ref8: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%8.8" PRIx64, uvalue); break; case DW_FORM_ref_udata: cu_relative_offset = true; if (verbose) s.Printf("cu + 0x%" PRIx64, uvalue); break; // All DW_FORM_indirect attributes should be resolved prior to calling this function case DW_FORM_indirect: s.PutCString("DW_FORM_indirect"); break; case DW_FORM_flag_present: break; default: s.Printf("DW_FORM(0x%4.4x)", m_form); break; } if (cu_relative_offset) { if (verbose) s.PutCString(" => "); s.Printf("{0x%8.8" PRIx64 "}", (uvalue + (cu ? cu->GetOffset() : 0))); } }