llvm.org GIT mirror llvm / e0ef46e
[FaultMaps] Add a parser for the __llvm__faultmaps section. Summary: The parser is exercised by llvm-objdump using -print-fault-maps. As is probably obvious, the code itself was "heavily inspired" by http://reviews.llvm.org/D10434. Reviewers: reames, atrick, JosephTremoulet Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D10491 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240304 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 5 years ago
5 changed file(s) with 286 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
1111
1212 #include "llvm/ADT/DenseMap.h"
1313 #include "llvm/MC/MCSymbol.h"
14 #include "llvm/Support/Endian.h"
15 #include "llvm/Support/Format.h"
1416
1517 #include
1618 #include
6769
6870 void emitFunctionInfo(const MCSymbol *FnLabel, const FunctionFaultInfos &FFI);
6971 };
72
73 /// A parser for the __llvm_faultmaps section generated by the FaultMaps class
74 /// above. This parser is version locked with with the __llvm_faultmaps section
75 /// generated by the version of LLVM that includes it. No guarantees are made
76 /// with respect to forward or backward compatibility.
77 class FaultMapParser {
78 typedef uint8_t FaultMapVersionType;
79 static const size_t FaultMapVersionOffset = 0;
80
81 typedef uint8_t Reserved0Type;
82 static const size_t Reserved0Offset =
83 FaultMapVersionOffset + sizeof(FaultMapVersionType);
84
85 typedef uint16_t Reserved1Type;
86 static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type);
87
88 typedef uint32_t NumFunctionsType;
89 static const size_t NumFunctionsOffset =
90 Reserved1Offset + sizeof(Reserved1Type);
91
92 static const size_t FunctionInfosOffset =
93 NumFunctionsOffset + sizeof(NumFunctionsType);
94
95 const uint8_t *P;
96 const uint8_t *E;
97
98 template static T read(const uint8_t *P, const uint8_t *E) {
99 assert(P + sizeof(T) <= E && "out of bounds read!");
100 return support::endian::read(P);
101 }
102
103 public:
104 class FunctionFaultInfoAccessor {
105 typedef uint32_t FaultKindType;
106 static const size_t FaultKindOffset = 0;
107
108 typedef uint32_t FaultingPCOffsetType;
109 static const size_t FaultingPCOffsetOffset =
110 FaultKindOffset + sizeof(FaultKindType);
111
112 typedef uint32_t HandlerPCOffsetType;
113 static const size_t HandlerPCOffsetOffset =
114 FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType);
115
116 const uint8_t *P;
117 const uint8_t *E;
118
119 public:
120 static const size_t Size =
121 HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType);
122
123 explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E)
124 : P(P), E(E) {}
125
126 FaultKindType getFaultKind() const {
127 return read(P + FaultKindOffset, E);
128 }
129
130 FaultingPCOffsetType getFaultingPCOffset() const {
131 return read(P + FaultingPCOffsetOffset, E);
132 }
133
134 HandlerPCOffsetType getHandlerPCOffset() const {
135 return read(P + HandlerPCOffsetOffset, E);
136 }
137 };
138
139 class FunctionInfoAccessor {
140 typedef uint64_t FunctionAddrType;
141 static const size_t FunctionAddrOffset = 0;
142
143 typedef uint32_t NumFaultingPCsType;
144 static const size_t NumFaultingPCsOffset =
145 FunctionAddrOffset + sizeof(FunctionAddrType);
146
147 typedef uint32_t ReservedType;
148 static const size_t ReservedOffset =
149 NumFaultingPCsOffset + sizeof(NumFaultingPCsType);
150
151 static const size_t FunctionFaultInfosOffset =
152 ReservedOffset + sizeof(ReservedType);
153
154 static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
155
156 const uint8_t *P;
157 const uint8_t *E;
158
159 public:
160 FunctionInfoAccessor() : P(nullptr), E(nullptr) {}
161
162 explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
163 : P(P), E(E) {}
164
165 FunctionAddrType getFunctionAddr() const {
166 return read(P + FunctionAddrOffset, E);
167 }
168
169 NumFaultingPCsType getNumFaultingPCs() const {
170 return read(P + NumFaultingPCsOffset, E);
171 }
172
173 FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const {
174 assert(Index < getNumFaultingPCs() && "index out of bounds!");
175 const uint8_t *Begin = P + FunctionFaultInfosOffset +
176 FunctionFaultInfoAccessor::Size * Index;
177 return FunctionFaultInfoAccessor(Begin, E);
178 }
179
180 FunctionInfoAccessor getNextFunctionInfo() const {
181 size_t MySize = FunctionInfoHeaderSize +
182 getNumFaultingPCs() * FunctionFaultInfoAccessor::Size;
183
184 const uint8_t *Begin = P + MySize;
185 assert(Begin < E && "out of bounds!");
186 return FunctionInfoAccessor(Begin, E);
187 }
188 };
189
190 explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End)
191 : P(Begin), E(End) {}
192
193 FaultMapVersionType getFaultMapVersion() const {
194 auto Version = read(P + FaultMapVersionOffset, E);
195 assert(Version == 1 && "only version 1 supported!");
196 return Version;
197 }
198
199 NumFunctionsType getNumFunctions() const {
200 return read(P + NumFunctionsOffset, E);
201 }
202
203 FunctionInfoAccessor getFirstFunctionInfo() const {
204 const uint8_t *Begin = P + FunctionInfosOffset;
205 return FunctionInfoAccessor(Begin, E);
206 }
207 };
208
209 raw_ostream &
210 operator<<(raw_ostream &OS,
211 const typename FaultMapParser::FunctionFaultInfoAccessor &);
212
213 raw_ostream &operator<<(raw_ostream &OS,
214 const typename FaultMapParser::FunctionInfoAccessor &);
215
216 raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
217
70218 } // namespace llvm
71219
72220 #endif
111111 return "FaultingLoad";
112112 }
113113 }
114
115 raw_ostream &llvm::
116 operator<<(raw_ostream &OS,
117 const typename FaultMapParser::FunctionFaultInfoAccessor &FFI) {
118 OS << "Fault kind: "
119 << FaultMaps::faultTypeToString((FaultMaps::FaultKind)FFI.getFaultKind())
120 << ", faulting PC offset: " << FFI.getFaultingPCOffset()
121 << ", handling PC offset: " << FFI.getHandlerPCOffset();
122 return OS;
123 }
124
125 raw_ostream &llvm::
126 operator<<(raw_ostream &OS,
127 const typename FaultMapParser::FunctionInfoAccessor &FI) {
128 OS << "FunctionAddress: " << format_hex(FI.getFunctionAddr(), 8)
129 << ", NumFaultingPCs: " << FI.getNumFaultingPCs() << "\n";
130 for (unsigned i = 0, e = FI.getNumFaultingPCs(); i != e; ++i)
131 OS << FI.getFunctionFaultInfoAt(i) << "\n";
132 return OS;
133 }
134
135 raw_ostream &llvm::operator<<(raw_ostream &OS, const FaultMapParser &FMP) {
136 OS << "Version: " << format_hex(FMP.getFaultMapVersion(), 2) << "\n";
137 OS << "NumFunctions: " << FMP.getNumFunctions() << "\n";
138
139 if (FMP.getNumFunctions() == 0)
140 return OS;
141
142 typename FaultMapParser::FunctionInfoAccessor FI;
143
144 for (unsigned i = 0, e = FMP.getNumFunctions(); i != e; ++i) {
145 FI = (i == 0) ? FMP.getFirstFunctionInfo() : FI.getNextFunctionInfo();
146 OS << FI;
147 }
148
149 return OS;
150 }
0 ; RUN: llc -O3 -mtriple=x86_64-apple-macosx -enable-implicit-null-checks < %s | FileCheck %s
1
2 ; RUN: llc < %s -mtriple=x86_64-apple-macosx -enable-implicit-null-checks \
3 ; RUN: | llvm-mc -triple x86_64-apple-macosx -filetype=obj -o - \
4 ; RUN: | llvm-objdump -triple x86_64-apple-macosx -fault-map-section - \
5 ; RUN: | FileCheck %s -check-prefix OBJDUMP
6
7 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -enable-implicit-null-checks \
8 ; RUN: | llvm-mc -triple x86_64-unknown-linux-gnu -filetype=obj -o - \
9 ; RUN: | llvm-objdump -triple x86_64-unknown-linux-gnu -fault-map-section - \
10 ; RUN: | FileCheck %s -check-prefix OBJDUMP
111
212 define i32 @imp_null_check_load(i32* %x) {
313 ; CHECK-LABEL: _imp_null_check_load:
115125 ; CHECK-NEXT: .long Ltmp1-_imp_null_check_load
116126 ; Fault[0].HandlerOffset:
117127 ; CHECK-NEXT: .long Ltmp0-_imp_null_check_load
128
129 ; OBJDUMP: FaultMap table:
130 ; OBJDUMP-NEXT: Version: 0x1
131 ; OBJDUMP-NEXT: NumFunctions: 3
132 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
133 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 5
134 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
135 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 7
136 ; OBJDUMP-NEXT: FunctionAddress: 0x000000, NumFaultingPCs: 1
137 ; OBJDUMP-NEXT: Fault kind: FaultingLoad, faulting PC offset: 0, handling PC offset: 3
0 // RUN: llvm-mc < %s -triple=x86_64-apple-macosx -filetype=obj -o - | llvm-objdump -fault-map-section - | FileCheck %s
1
2 .section __LLVM_FAULTMAPS,__llvm_faultmaps
3 __LLVM_FaultMaps:
4 .byte 1
5 .byte 0
6 .short 0
7 .long 2
8 .quad 0xFFDEAD
9 .long 1
10 .long 0
11 .long 1
12 .long 100
13 .long 200
14
15 .quad 0xFFDAED
16 .long 1
17 .long 0
18 .long 1
19 .long 400
20 .long 500
21
22 // CHECK: FaultMap table:
23 // CHECK-NEXT: Version: 0x1
24 // CHECK-NEXT: NumFunctions: 2
25 // CHECK-NEXT: FunctionAddress: 0xffdead, NumFaultingPCs: 1
26 // CHECK-NEXT: Fault kind: FaultingLoad, faulting PC offset: 100, handling PC offset: 200
27 // CHECK-NEXT: FunctionAddress: 0xffdaed, NumFaultingPCs: 1
28 // CHECK-NEXT: Fault kind: FaultingLoad, faulting PC offset: 400, handling PC offset: 500
1616 //===----------------------------------------------------------------------===//
1717
1818 #include "llvm-objdump.h"
19 #include "llvm/ADT/Optional.h"
1920 #include "llvm/ADT/STLExtras.h"
2021 #include "llvm/ADT/StringExtras.h"
2122 #include "llvm/ADT/Triple.h"
23 #include "llvm/CodeGen/FaultMaps.h"
2224 #include "llvm/MC/MCAsmInfo.h"
2325 #include "llvm/MC/MCContext.h"
2426 #include "llvm/MC/MCDisassembler.h"
152154 llvm::PrintImmHex("print-imm-hex",
153155 cl::desc("Use hex format for immediate values"));
154156
157 cl::opt PrintFaultMaps("fault-map-section",
158 cl::desc("Display contents of faultmap section"));
159
155160 static StringRef ToolName;
156161 static int ReturnValue = EXIT_SUCCESS;
157162
12251230 }
12261231 }
12271232
1233 static void printFaultMaps(const ObjectFile *Obj) {
1234 const char *FaultMapSectionName = nullptr;
1235
1236 if (isa(Obj)) {
1237 FaultMapSectionName = ".llvm_faultmaps";
1238 } else if (isa(Obj)) {
1239 FaultMapSectionName = "__llvm_faultmaps";
1240 } else {
1241 errs() << "This operation is only currently supported "
1242 "for ELF and Mach-O executable files.\n";
1243 return;
1244 }
1245
1246 Optional FaultMapSection;
1247
1248 for (auto Sec : Obj->sections()) {
1249 StringRef Name;
1250 Sec.getName(Name);
1251 if (Name == FaultMapSectionName) {
1252 FaultMapSection = Sec;
1253 break;
1254 }
1255 }
1256
1257 outs() << "FaultMap table:\n";
1258
1259 if (!FaultMapSection.hasValue()) {
1260 outs() << "\n";
1261 return;
1262 }
1263
1264 StringRef FaultMapContents;
1265 if (error(FaultMapSection.getValue().getContents(FaultMapContents))) {
1266 errs() << "Could not read the " << FaultMapContents << " section!\n";
1267 return;
1268 }
1269
1270 FaultMapParser FMP(FaultMapContents.bytes_begin(),
1271 FaultMapContents.bytes_end());
1272
1273 outs() << FMP;
1274 }
1275
12281276 static void printPrivateFileHeader(const ObjectFile *o) {
12291277 if (o->isELF()) {
12301278 printELFFileHeader(o);
12641312 printLazyBindTable(o);
12651313 if (WeakBind)
12661314 printWeakBindTable(o);
1315 if (PrintFaultMaps)
1316 printFaultMaps(o);
12671317 }
12681318
12691319 /// @brief Dump each object file in \a a;
13611411 && !(DylibsUsed && MachOOpt)
13621412 && !(DylibId && MachOOpt)
13631413 && !(ObjcMetaData && MachOOpt)
1364 && !(DumpSections.size() != 0 && MachOOpt)) {
1414 && !(DumpSections.size() != 0 && MachOOpt)
1415 && !PrintFaultMaps) {
13651416 cl::PrintHelpMessage();
13661417 return 2;
13671418 }