blob: 835f7279e26b06379dac8313299ce420cc20df21 [file] [log] [blame]
Wolfgang Pieb439801b2018-07-23 22:37:17 +00001//===- 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"
Victor Leschukcba595d2018-08-20 09:59:08 +000012#include "llvm/Support/Errc.h"
Wolfgang Pieb439801b2018-07-23 22:37:17 +000013#include "llvm/Support/Error.h"
14#include "llvm/Support/Format.h"
15#include "llvm/Support/raw_ostream.h"
16
17using namespace llvm;
18
Wolfgang Pieb439801b2018-07-23 22:37:17 +000019Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
20 uint32_t *OffsetPtr) {
21 HeaderOffset = *OffsetPtr;
22 // Read and verify the length field.
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000023 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;
Victor Leschukcba595d2018-08-20 09:59:08 +000027 return createStringError(errc::invalid_argument,
28 "section is not large enough to contain a "
Wolfgang Pieb439801b2018-07-23 22:37:17 +000029 "%s table length at offset 0x%" PRIx32,
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000030 SectionName.data(), HeaderOffset);
31 }
Wolfgang Pieb439801b2018-07-23 22:37:17 +000032 // TODO: Add support for DWARF64.
33 HeaderData.Length = Data.getU32(OffsetPtr);
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000034 if (HeaderData.Length == 0xffffffffu) {
35 *OffsetPtr = 0;
Victor Leschukcba595d2018-08-20 09:59:08 +000036 return createStringError(errc::not_supported,
37 "DWARF64 is not supported in %s at offset 0x%" PRIx32,
Wolfgang Pieb439801b2018-07-23 22:37:17 +000038 SectionName.data(), HeaderOffset);
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000039 }
40
41 uint32_t TableLength = HeaderData.Length + sizeof(uint32_t);
42 uint32_t End = HeaderOffset + TableLength;
Wolfgang Pieb439801b2018-07-23 22:37:17 +000043 Format = dwarf::DwarfFormat::DWARF32;
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000044 if (TableLength < sizeof(Header)) {
45 *OffsetPtr = End;
46 return createStringError(
47 errc::invalid_argument,
48 "%s table at offset 0x%" PRIx32 " 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 }
Wolfgang Pieb439801b2018-07-23 22:37:17 +000060
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.
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000067 if (HeaderData.Version != 5) {
68 *OffsetPtr = End;
Victor Leschukcba595d2018-08-20 09:59:08 +000069 return createStringError(errc::invalid_argument,
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000070 "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;
Victor Leschukcba595d2018-08-20 09:59:08 +000077 return createStringError(errc::not_supported,
78 "%s table at offset 0x%" PRIx32
79 " has unsupported address size %" PRIu8,
Wolfgang Pieb439801b2018-07-23 22:37:17 +000080 SectionName.data(), HeaderOffset, HeaderData.AddrSize);
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000081 }
82 if (HeaderData.SegSize != 0) {
83 *OffsetPtr = End;
Victor Leschukcba595d2018-08-20 09:59:08 +000084 return createStringError(errc::not_supported,
85 "%s table at offset 0x%" PRIx32
Wolfgang Pieb439801b2018-07-23 22:37:17 +000086 " has unsupported segment selector size %" PRIu8,
87 SectionName.data(), HeaderOffset, HeaderData.SegSize);
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000088 }
Wolfgang Pieb439801b2018-07-23 22:37:17 +000089 if (End < HeaderOffset + sizeof(HeaderData) +
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000090 HeaderData.OffsetEntryCount * sizeof(uint32_t)) {
91 *OffsetPtr = End;
Victor Leschukcba595d2018-08-20 09:59:08 +000092 return createStringError(errc::invalid_argument,
Wolfgang Pieb439801b2018-07-23 22:37:17 +000093 "%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32
94 ") than there is space for",
95 SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount);
Wolfgang Pieb55dbac92018-09-14 09:14:10 +000096 }
Wolfgang Pieb439801b2018-07-23 22:37:17 +000097 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
103void 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
Wolfgang Pieb55dbac92018-09-14 09:14:10 +0000126uint32_t DWARFListTableHeader::getTableLength() const {
Wolfgang Pieb439801b2018-07-23 22:37:17 +0000127 if (HeaderData.Length == 0)
128 return 0;
Wolfgang Pieb55dbac92018-09-14 09:14:10 +0000129 assert(HeaderData.Version > 0 &&
130 "No DWARF version in header when using getTableLength()");
Wolfgang Pieb439801b2018-07-23 22:37:17 +0000131 // TODO: DWARF64 support.
Wolfgang Pieb55dbac92018-09-14 09:14:10 +0000132 return HeaderData.Length + (HeaderData.Version > 4) * sizeof(uint32_t);
Wolfgang Pieb439801b2018-07-23 22:37:17 +0000133}