1 //===-- DWARFCompileUnit.cpp ----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "DWARFCompileUnit.h" 11 #include "DWARFContext.h" 12 #include "DWARFFormValue.h" 13 #include "llvm/Support/Dwarf.h" 14 #include "llvm/Support/Format.h" 15 #include "llvm/Support/raw_ostream.h" 16 using namespace llvm; 17 using namespace dwarf; 18 19 DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const { 20 return DataExtractor(Context.getInfoSection(), 21 Context.isLittleEndian(), getAddressByteSize()); 22 } 23 24 bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { 25 clear(); 26 27 Offset = *offset_ptr; 28 29 if (debug_info.isValidOffset(*offset_ptr)) { 30 uint64_t abbrOffset; 31 const DWARFDebugAbbrev *abbr = Context.getDebugAbbrev(); 32 Length = debug_info.getU32(offset_ptr); 33 Version = debug_info.getU16(offset_ptr); 34 abbrOffset = debug_info.getU32(offset_ptr); 35 AddrSize = debug_info.getU8(offset_ptr); 36 37 bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1); 38 bool versionOK = DWARFContext::isSupportedVersion(Version); 39 bool abbrOffsetOK = Context.getAbbrevSection().size() > abbrOffset; 40 bool addrSizeOK = AddrSize == 4 || AddrSize == 8; 41 42 if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && abbr != NULL) { 43 Abbrevs = abbr->getAbbreviationDeclarationSet(abbrOffset); 44 return true; 45 } 46 47 // reset the offset to where we tried to parse from if anything went wrong 48 *offset_ptr = Offset; 49 } 50 51 return false; 52 } 53 54 uint32_t 55 DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data, 56 const DWARFAbbreviationDeclarationSet *abbrevs) { 57 clear(); 58 59 Offset = offset; 60 61 if (debug_info_data.isValidOffset(offset)) { 62 Length = debug_info_data.getU32(&offset); 63 Version = debug_info_data.getU16(&offset); 64 bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset(); 65 Abbrevs = abbrevs; 66 AddrSize = debug_info_data.getU8 (&offset); 67 68 bool versionOK = DWARFContext::isSupportedVersion(Version); 69 bool addrSizeOK = AddrSize == 4 || AddrSize == 8; 70 71 if (versionOK && addrSizeOK && abbrevsOK && 72 debug_info_data.isValidOffset(offset)) 73 return offset; 74 } 75 return 0; 76 } 77 78 void DWARFCompileUnit::clear() { 79 Offset = 0; 80 Length = 0; 81 Version = 0; 82 Abbrevs = 0; 83 AddrSize = 0; 84 BaseAddr = 0; 85 DieArray.clear(); 86 } 87 88 void DWARFCompileUnit::dump(raw_ostream &OS) { 89 OS << format("0x%08x", Offset) << ": Compile Unit:" 90 << " length = " << format("0x%08x", Length) 91 << " version = " << format("0x%04x", Version) 92 << " abbr_offset = " << format("0x%04x", Abbrevs->getOffset()) 93 << " addr_size = " << format("0x%02x", AddrSize) 94 << " (next CU at " << format("0x%08x", getNextCompileUnitOffset()) 95 << ")\n"; 96 97 getCompileUnitDIE(false)->dump(OS, this, -1U); 98 } 99 100 void DWARFCompileUnit::setDIERelations() { 101 if (DieArray.empty()) 102 return; 103 DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front(); 104 DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back(); 105 DWARFDebugInfoEntryMinimal *curr_die; 106 // We purposely are skipping the last element in the array in the loop below 107 // so that we can always have a valid next item 108 for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) { 109 // Since our loop doesn't include the last element, we can always 110 // safely access the next die in the array. 111 DWARFDebugInfoEntryMinimal *next_die = curr_die + 1; 112 113 const DWARFAbbreviationDeclaration *curr_die_abbrev = 114 curr_die->getAbbreviationDeclarationPtr(); 115 116 if (curr_die_abbrev) { 117 // Normal DIE 118 if (curr_die_abbrev->hasChildren()) 119 next_die->setParent(curr_die); 120 else 121 curr_die->setSibling(next_die); 122 } else { 123 // NULL DIE that terminates a sibling chain 124 DWARFDebugInfoEntryMinimal *parent = curr_die->getParent(); 125 if (parent) 126 parent->setSibling(next_die); 127 } 128 } 129 130 // Since we skipped the last element, we need to fix it up! 131 if (die_array_begin < die_array_end) 132 curr_die->setParent(die_array_begin); 133 } 134 135 size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) { 136 const size_t initial_die_array_size = DieArray.size(); 137 if ((cu_die_only && initial_die_array_size > 0) || 138 initial_die_array_size > 1) 139 return 0; // Already parsed 140 141 // Set the offset to that of the first DIE and calculate the start of the 142 // next compilation unit header. 143 uint32_t offset = getFirstDIEOffset(); 144 uint32_t next_cu_offset = getNextCompileUnitOffset(); 145 146 DWARFDebugInfoEntryMinimal die; 147 // Keep a flat array of the DIE for binary lookup by DIE offset 148 uint32_t depth = 0; 149 // We are in our compile unit, parse starting at the offset 150 // we were told to parse 151 152 const uint8_t *fixed_form_sizes = 153 DWARFFormValue::getFixedFormSizesForAddressSize(getAddressByteSize()); 154 155 while (offset < next_cu_offset && 156 die.extractFast(this, fixed_form_sizes, &offset)) { 157 158 if (depth == 0) { 159 uint64_t base_addr = 160 die.getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U); 161 if (base_addr == -1U) 162 base_addr = die.getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0); 163 setBaseAddress(base_addr); 164 } 165 166 if (cu_die_only) { 167 addDIE(die); 168 return 1; 169 } 170 else if (depth == 0 && initial_die_array_size == 1) { 171 // Don't append the CU die as we already did that 172 } else { 173 addDIE (die); 174 } 175 176 const DWARFAbbreviationDeclaration *abbrDecl = 177 die.getAbbreviationDeclarationPtr(); 178 if (abbrDecl) { 179 // Normal DIE 180 if (abbrDecl->hasChildren()) 181 ++depth; 182 } else { 183 // NULL DIE. 184 if (depth > 0) 185 --depth; 186 if (depth == 0) 187 break; // We are done with this compile unit! 188 } 189 190 } 191 192 // Give a little bit of info if we encounter corrupt DWARF (our offset 193 // should always terminate at or before the start of the next compilation 194 // unit header). 195 if (offset > next_cu_offset) { 196 fprintf (stderr, "warning: DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset); 197 } 198 199 setDIERelations(); 200 return DieArray.size(); 201 } 202 203 void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) { 204 if (DieArray.size() > 1) { 205 // std::vectors never get any smaller when resized to a smaller size, 206 // or when clear() or erase() are called, the size will report that it 207 // is smaller, but the memory allocated remains intact (call capacity() 208 // to see this). So we need to create a temporary vector and swap the 209 // contents which will cause just the internal pointers to be swapped 210 // so that when "tmp_array" goes out of scope, it will destroy the 211 // contents. 212 213 // Save at least the compile unit DIE 214 std::vector<DWARFDebugInfoEntryMinimal> tmpArray; 215 DieArray.swap(tmpArray); 216 if (keep_compile_unit_die) 217 DieArray.push_back(tmpArray.front()); 218 } 219 } 220 221 void 222 DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, 223 bool clear_dies_if_already_not_parsed){ 224 // This function is usually called if there in no .debug_aranges section 225 // in order to produce a compile unit level set of address ranges that 226 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 227 // all compile units to stay loaded when they weren't needed. So we can end 228 // up parsing the DWARF and then throwing them all away to keep memory usage 229 // down. 230 const bool clear_dies = extractDIEsIfNeeded(false) > 1; 231 232 DieArray[0].buildAddressRangeTable(this, debug_aranges); 233 234 // Keep memory down by clearing DIEs if this generate function 235 // caused them to be parsed. 236 if (clear_dies) 237 clearDIEs(true); 238 } 239