1 //===- DWARFListTable.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 "llvm/DebugInfo/DWARF/DWARFListTable.h" 11 #include "llvm/BinaryFormat/Dwarf.h" 12 #include "llvm/Support/Errc.h" 13 #include "llvm/Support/Error.h" 14 #include "llvm/Support/Format.h" 15 #include "llvm/Support/raw_ostream.h" 16 17 using namespace llvm; 18 19 Error DWARFListTableHeader::extract(DWARFDataExtractor Data, 20 uint32_t *OffsetPtr) { 21 HeaderOffset = *OffsetPtr; 22 // Read and verify the length field. 23 if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) { 24 // By setting *OffsetPtr to 0, we indicate to the caller that 25 // we could not detemine the length of the table. 26 *OffsetPtr = 0; 27 return createStringError(errc::invalid_argument, 28 "section is not large enough to contain a " 29 "%s table length at offset 0x%" PRIx32, 30 SectionName.data(), HeaderOffset); 31 } 32 // TODO: Add support for DWARF64. 33 HeaderData.Length = Data.getU32(OffsetPtr); 34 if (HeaderData.Length == 0xffffffffu) { 35 *OffsetPtr = 0; 36 return createStringError(errc::not_supported, 37 "DWARF64 is not supported in %s at offset 0x%" PRIx32, 38 SectionName.data(), HeaderOffset); 39 } 40 41 uint32_t TableLength = HeaderData.Length + sizeof(uint32_t); 42 uint32_t End = HeaderOffset + TableLength; 43 Format = dwarf::DwarfFormat::DWARF32; 44 if (TableLength < sizeof(Header)) { 45 *OffsetPtr = End; 46 return createStringError(errc::invalid_argument, 47 "%s table at offset 0x%" PRIx32 48 " has too small length (0x%" PRIx32 49 ") to contain a complete header", 50 SectionName.data(), HeaderOffset, TableLength); 51 } 52 if (!Data.isValidOffsetForDataOfSize(HeaderOffset, TableLength)) { 53 *OffsetPtr = 0; // No recovery if the length exceeds the section size. 54 return createStringError( 55 errc::invalid_argument, 56 "section is not large enough to contain a %s table " 57 "of length 0x%" PRIx32 " at offset 0x%" PRIx32, 58 SectionName.data(), TableLength, HeaderOffset); 59 } 60 61 HeaderData.Version = Data.getU16(OffsetPtr); 62 HeaderData.AddrSize = Data.getU8(OffsetPtr); 63 HeaderData.SegSize = Data.getU8(OffsetPtr); 64 HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr); 65 66 // Perform basic validation of the remaining header fields. 67 if (HeaderData.Version != 5) { 68 *OffsetPtr = End; 69 return createStringError(errc::invalid_argument, 70 "unrecognised %s table version %" PRIu16 71 " in table at offset 0x%" PRIx32, 72 SectionName.data(), HeaderData.Version, 73 HeaderOffset); 74 } 75 if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) { 76 *OffsetPtr = End; 77 return createStringError(errc::not_supported, 78 "%s table at offset 0x%" PRIx32 79 " has unsupported address size %" PRIu8, 80 SectionName.data(), HeaderOffset, HeaderData.AddrSize); 81 } 82 if (HeaderData.SegSize != 0) { 83 *OffsetPtr = End; 84 return createStringError(errc::not_supported, 85 "%s table at offset 0x%" PRIx32 86 " has unsupported segment selector size %" PRIu8, 87 SectionName.data(), HeaderOffset, HeaderData.SegSize); 88 } 89 if (End < HeaderOffset + sizeof(HeaderData) + 90 HeaderData.OffsetEntryCount * sizeof(uint32_t)) { 91 *OffsetPtr = End; 92 return createStringError(errc::invalid_argument, 93 "%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32 94 ") than there is space for", 95 SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount); 96 } 97 Data.setAddressSize(HeaderData.AddrSize); 98 for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I) 99 Offsets.push_back(Data.getU32(OffsetPtr)); 100 return Error::success(); 101 } 102 103 void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { 104 if (DumpOpts.Verbose) 105 OS << format("0x%8.8" PRIx32 ": ", HeaderOffset); 106 OS << format( 107 "%s list header: length = 0x%8.8" PRIx32 ", version = 0x%4.4" PRIx16 ", " 108 "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 109 ", offset_entry_count = " 110 "0x%8.8" PRIx32 "\n", 111 ListTypeString.data(), HeaderData.Length, HeaderData.Version, 112 HeaderData.AddrSize, HeaderData.SegSize, HeaderData.OffsetEntryCount); 113 114 if (HeaderData.OffsetEntryCount > 0) { 115 OS << "offsets: ["; 116 for (const auto &Off : Offsets) { 117 OS << format("\n0x%8.8" PRIx32, Off); 118 if (DumpOpts.Verbose) 119 OS << format(" => 0x%8.8" PRIx32, 120 Off + HeaderOffset + sizeof(HeaderData)); 121 } 122 OS << "\n]\n"; 123 } 124 } 125 126 uint32_t DWARFListTableHeader::getTableLength() const { 127 if (HeaderData.Length == 0) 128 return 0; 129 assert(HeaderData.Version > 0 && 130 "No DWARF version in header when using getTableLength()"); 131 // TODO: DWARF64 support. 132 return HeaderData.Length + (HeaderData.Version > 4) * sizeof(uint32_t); 133 } 134