llvm.org GIT mirror llvm / 63f4054
[StackMaps] Add a lightweight parser for stackmap version 1 sections. The parser provides a convenient interface for reading llvm stackmap v1 sections in object files. This patch also includes a new option for llvm-readobj, '-stackmap', which uses the parser to pretty-print stackmap sections for debugging/testing purposes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240860 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 4 years ago
9 changed file(s) with 687 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
0 //===-------- StackMapParser.h - StackMap Parsing Support -------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_CODEGEN_STACKMAPPARSER_H
10 #define LLVM_CODEGEN_STACKMAPPARSER_H
11
12 #include "llvm/Support/Debug.h"
13 #include "llvm/Support/Endian.h"
14 #include
15 #include
16
17 namespace llvm {
18
19 template
20 class StackMapV1Parser {
21 public:
22
23 template
24 class AccessorIterator {
25 public:
26
27 AccessorIterator(AccessorT A) : A(A) {}
28 AccessorIterator& operator++() { A = A.next(); return *this; }
29 AccessorIterator operator++(int) {
30 auto tmp = *this;
31 ++*this;
32 return tmp;
33 }
34
35 bool operator==(const AccessorIterator &Other) {
36 return A.P == Other.A.P;
37 }
38
39 bool operator!=(const AccessorIterator &Other) { return !(*this == Other); }
40
41 AccessorT& operator*() { return A; }
42 AccessorT* operator->() { return &A; }
43
44 private:
45 AccessorT A;
46 };
47
48 /// Accessor for function records.
49 class FunctionAccessor {
50 friend class StackMapV1Parser;
51 public:
52
53 /// Get the function address.
54 uint64_t getFunctionAddress() const {
55 return read(P);
56 }
57
58 /// Get the function's stack size.
59 uint32_t getStackSize() const {
60 return read(P + sizeof(uint64_t));
61 }
62
63 private:
64 FunctionAccessor(const uint8_t *P) : P(P) {}
65
66 const static int FunctionAccessorSize = 2 * sizeof(uint64_t);
67
68 FunctionAccessor next() const {
69 return FunctionAccessor(P + FunctionAccessorSize);
70 }
71
72 const uint8_t *P;
73 };
74
75 /// Accessor for constants.
76 class ConstantAccessor {
77 friend class StackMapV1Parser;
78 public:
79
80 /// Return the value of this constant.
81 uint64_t getValue() const { return read(P); }
82
83 private:
84
85 ConstantAccessor(const uint8_t *P) : P(P) {}
86
87 const static int ConstantAccessorSize = sizeof(uint64_t);
88
89 ConstantAccessor next() const {
90 return ConstantAccessor(P + ConstantAccessorSize);
91 }
92
93 const uint8_t *P;
94 };
95
96 // Forward-declare RecordAccessor so we can friend it below.
97 class RecordAccessor;
98
99 enum class LocationKind : uint8_t {
100 Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5
101 };
102
103
104 /// Accessor for location records.
105 class LocationAccessor {
106 friend class StackMapV1Parser;
107 friend class RecordAccessor;
108 public:
109
110 /// Get the Kind for this location.
111 LocationKind getKind() const {
112 return LocationKind(P[KindOffset]);
113 }
114
115 /// Get the Dwarf register number for this location.
116 uint16_t getDwarfRegNum() const {
117 return read(P + DwarfRegNumOffset);
118 }
119
120 /// Get the small-constant for this location. (Kind must be Constant).
121 uint32_t getSmallConstant() const {
122 assert(getKind() == LocationKind::Constant && "Not a small constant.");
123 return read(P + SmallConstantOffset);
124 }
125
126 /// Get the constant-index for this location. (Kind must be ConstantIndex).
127 uint32_t getConstantIndex() const {
128 assert(getKind() == LocationKind::ConstantIndex &&
129 "Not a constant-index.");
130 return read(P + SmallConstantOffset);
131 }
132
133 /// Get the offset for this location. (Kind must be Direct or Indirect).
134 int32_t getOffset() const {
135 assert((getKind() == LocationKind::Direct ||
136 getKind() == LocationKind::Indirect) &&
137 "Not direct or indirect.");
138 return read(P + SmallConstantOffset);
139 }
140
141 private:
142
143 LocationAccessor(const uint8_t *P) : P(P) {}
144
145 LocationAccessor next() const {
146 return LocationAccessor(P + LocationAccessorSize);
147 }
148
149 static const int KindOffset = 0;
150 static const int DwarfRegNumOffset = KindOffset + sizeof(uint16_t);
151 static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint16_t);
152 static const int LocationAccessorSize = sizeof(uint64_t);
153
154 const uint8_t *P;
155 };
156
157 /// Accessor for stackmap live-out fields.
158 class LiveOutAccessor {
159 friend class StackMapV1Parser;
160 friend class RecordAccessor;
161 public:
162
163 /// Get the Dwarf register number for this live-out.
164 uint16_t getDwarfRegNum() const {
165 return read(P + DwarfRegNumOffset);
166 }
167
168 /// Get the size in bytes of live [sub]register.
169 unsigned getSizeInBytes() const {
170 return read(P + SizeOffset);
171 }
172
173 private:
174
175 LiveOutAccessor(const uint8_t *P) : P(P) {}
176
177 LiveOutAccessor next() const {
178 return LiveOutAccessor(P + LiveOutAccessorSize);
179 }
180
181 static const int DwarfRegNumOffset = 0;
182 static const int SizeOffset =
183 DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t);
184 static const int LiveOutAccessorSize = sizeof(uint32_t);
185
186 const uint8_t *P;
187 };
188
189 /// Accessor for stackmap records.
190 class RecordAccessor {
191 friend class StackMapV1Parser;
192 public:
193
194 typedef AccessorIterator location_iterator;
195 typedef AccessorIterator liveout_iterator;
196
197 /// Get the patchpoint/stackmap ID for this record.
198 uint64_t getID() const {
199 return read(P + PatchpointIDOffset);
200 }
201
202 /// Get the instruction offset (from the start of the containing function)
203 /// for this record.
204 uint32_t getInstructionOffset() const {
205 return read(P + InstructionOffsetOffset);
206 }
207
208 /// Get the number of locations contained in this record.
209 uint16_t getNumLocations() const {
210 return read(P + NumLocationsOffset);
211 }
212
213 /// Get the location with the given index.
214 LocationAccessor getLocation(unsigned LocationIndex) const {
215 unsigned LocationOffset =
216 LocationListOffset + LocationIndex * LocationSize;
217 return LocationAccessor(P + LocationOffset);
218 }
219
220 /// Begin iterator for locations.
221 location_iterator location_begin() const {
222 return location_iterator(getLocation(0));
223 }
224
225 /// End iterator for locations.
226 location_iterator location_end() const {
227 return location_iterator(getLocation(getNumLocations()));
228 }
229
230 /// Iterator range for locations.
231 iterator_range locations() const {
232 return make_range(location_begin(), location_end());
233 }
234
235 /// Get the number of liveouts contained in this record.
236 uint16_t getNumLiveOuts() const {
237 return read(P + getNumLiveOutsOffset());
238 }
239
240 /// Get the live-out with the given index.
241 LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const {
242 unsigned LiveOutOffset =
243 getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize;
244 return LiveOutAccessor(P + LiveOutOffset);
245 }
246
247 /// Begin iterator for live-outs.
248 liveout_iterator liveouts_begin() const {
249 return liveout_iterator(getLiveOut(0));
250 }
251
252
253 /// End iterator for live-outs.
254 liveout_iterator liveouts_end() const {
255 return liveout_iterator(getLiveOut(getNumLiveOuts()));
256 }
257
258 /// Iterator range for live-outs.
259 iterator_range liveouts() const {
260 return make_range(liveouts_begin(), liveouts_end());
261 }
262
263 private:
264
265 RecordAccessor(const uint8_t *P) : P(P) {}
266
267 unsigned getNumLiveOutsOffset() const {
268 return LocationListOffset + LocationSize * getNumLocations() +
269 sizeof(uint16_t);
270 }
271
272 unsigned getSizeInBytes() const {
273 unsigned RecordSize =
274 getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize;
275 return (RecordSize + 7) & ~0x7;
276 }
277
278 RecordAccessor next() const {
279 return RecordAccessor(P + getSizeInBytes());
280 }
281
282 static const unsigned PatchpointIDOffset = 0;
283 static const unsigned InstructionOffsetOffset =
284 PatchpointIDOffset + sizeof(uint64_t);
285 static const unsigned NumLocationsOffset =
286 InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t);
287 static const unsigned LocationListOffset =
288 NumLocationsOffset + sizeof(uint16_t);
289 static const unsigned LocationSize = sizeof(uint64_t);
290 static const unsigned LiveOutSize = sizeof(uint32_t);
291
292 const uint8_t *P;
293 };
294
295 /// Construct a parser for a version-1 stackmap. StackMap data will be read
296 /// from the given array.
297 StackMapV1Parser(ArrayRef StackMapSection)
298 : StackMapSection(StackMapSection) {
299 ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
300
301 assert(StackMapSection[0] == 1 &&
302 "StackMapV1Parser can only parse version 1 stackmaps");
303
304 unsigned CurrentRecordOffset =
305 ConstantsListOffset + getNumConstants() * ConstantSize;
306
307 for (unsigned I = 0, E = getNumRecords(); I != E; ++I) {
308 StackMapRecordOffsets.push_back(CurrentRecordOffset);
309 CurrentRecordOffset +=
310 RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes();
311 }
312 }
313
314 typedef AccessorIterator function_iterator;
315 typedef AccessorIterator constant_iterator;
316 typedef AccessorIterator record_iterator;
317
318 /// Get the version number of this stackmap. (Always returns 1).
319 unsigned getVersion() const { return 1; }
320
321 /// Get the number of functions in the stack map.
322 uint32_t getNumFunctions() const {
323 return read(&StackMapSection[NumFunctionsOffset]);
324 }
325
326 /// Get the number of large constants in the stack map.
327 uint32_t getNumConstants() const {
328 return read(&StackMapSection[NumConstantsOffset]);
329 }
330
331 /// Get the number of stackmap records in the stackmap.
332 uint32_t getNumRecords() const {
333 return read(&StackMapSection[NumRecordsOffset]);
334 }
335
336 /// Return an FunctionAccessor for the given function index.
337 FunctionAccessor getFunction(unsigned FunctionIndex) const {
338 return FunctionAccessor(StackMapSection.data() +
339 getFunctionOffset(FunctionIndex));
340 }
341
342 /// Begin iterator for functions.
343 function_iterator functions_begin() const {
344 return function_iterator(getFunction(0));
345 }
346
347 /// End iterator for functions.
348 function_iterator functions_end() const {
349 return function_iterator(
350 FunctionAccessor(StackMapSection.data() +
351 getFunctionOffset(getNumFunctions())));
352 }
353
354 /// Iterator range for functions.
355 iterator_range functions() const {
356 return make_range(functions_begin(), functions_end());
357 }
358
359 /// Return the large constant at the given index.
360 ConstantAccessor getConstant(unsigned ConstantIndex) const {
361 return ConstantAccessor(StackMapSection.data() +
362 getConstantOffset(ConstantIndex));
363 }
364
365 /// Begin iterator for constants.
366 constant_iterator constants_begin() const {
367 return constant_iterator(getConstant(0));
368 }
369
370 /// End iterator for constants.
371 constant_iterator constants_end() const {
372 return constant_iterator(
373 ConstantAccessor(StackMapSection.data() +
374 getConstantOffset(getNumConstants())));
375 }
376
377 /// Iterator range for constants.
378 iterator_range constants() const {
379 return make_range(constants_begin(), constants_end());
380 }
381
382 /// Return a RecordAccessor for the given record index.
383 RecordAccessor getRecord(unsigned RecordIndex) const {
384 std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex];
385 return RecordAccessor(StackMapSection.data() + RecordOffset);
386 }
387
388 /// Begin iterator for records.
389 record_iterator records_begin() const {
390 if (getNumRecords() == 0)
391 return record_iterator(RecordAccessor(nullptr));
392 return record_iterator(getRecord(0));
393 }
394
395 /// End iterator for records.
396 record_iterator records_end() const {
397 // Records need to be handled specially, since we cache the start addresses
398 // for them: We can't just compute the 1-past-the-end address, we have to
399 // look at the last record and use the 'next' method.
400 if (getNumRecords() == 0)
401 return record_iterator(RecordAccessor(nullptr));
402 return record_iterator(getRecord(getNumRecords() - 1).next());
403 }
404
405 /// Iterator range for records.
406 iterator_range records() const {
407 return make_range(records_begin(), records_end());
408 }
409
410 private:
411
412 template
413 static T read(const uint8_t *P) {
414 return support::endian::read(P);
415 }
416
417 static const unsigned HeaderOffset = 0;
418 static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t);
419 static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t);
420 static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t);
421 static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t);
422
423 static const unsigned FunctionSize = 2 * sizeof(uint64_t);
424 static const unsigned ConstantSize = sizeof(uint64_t);
425
426 std::size_t getFunctionOffset(unsigned FunctionIndex) const {
427 return FunctionListOffset + FunctionIndex * FunctionSize;
428 }
429
430 std::size_t getConstantOffset(unsigned ConstantIndex) const {
431 return ConstantsListOffset + ConstantIndex * ConstantSize;
432 }
433
434 ArrayRef StackMapSection;
435 unsigned ConstantsListOffset;
436 std::vector StackMapRecordOffsets;
437 };
438
439 }
440
441 #endif
0 .section __TEXT,__text,regular,pure_instructions
1 .globl _trivial_patchpoint_codegen
2 .align 4, 0x90
3 _trivial_patchpoint_codegen: ## @trivial_patchpoint_codegen
4 .fill 1
5 Ltmp3:
6
7 .section __LLVM_STACKMAPS,__llvm_stackmaps
8 __LLVM_StackMaps:
9 .byte 1
10 .byte 0
11 .short 0
12 .long 1
13 .long 1
14 .long 1
15 .quad _trivial_patchpoint_codegen
16 .quad 16
17 .quad 10000000000
18 .quad 2
19 .long Ltmp3-_trivial_patchpoint_codegen
20 .short 0
21 .short 5
22 .byte 1
23 .byte 8
24 .short 5
25 .long 0
26 .byte 4
27 .byte 8
28 .short 0
29 .long 10
30 .byte 5
31 .byte 8
32 .short 0
33 .long 0
34 .byte 2
35 .byte 8
36 .short 4
37 .long -8
38 .byte 3
39 .byte 8
40 .short 6
41 .long -16
42 .short 0
43 .short 1
44 .short 7
45 .byte 0
46 .byte 8
47 .align 3
48
49 .subsections_via_symbols
0 RUN: llvm-mc -triple x86_64-apple-darwin -filetype=obj -o %t %p/Inputs/stackmap.s && \
1 RUN: llvm-readobj -stackmap %t | FileCheck %s
2
3 CHECK: LLVM StackMap Version: 1
4 CHECK-NEXT: Num Functions: 1
5 CHECK-NEXT: Function address: 0, stack size: 16
6 CHECK-NEXT: Num Constants: 1
7 CHECK-NEXT: #1: 10000000000
8 CHECK-NEXT: Num Records: 1
9 CHECK-NEXT: Record ID: 2, instruction offset: 1
10 CHECK-NEXT: 5 locations:
11 CHECK-NEXT: #1: Register R#5
12 CHECK-NEXT: #2: Constant 10
13 CHECK-NEXT: #3: ConstantIndex #0 (10000000000)
14 CHECK-NEXT: #4: Direct R#4 + -8
15 CHECK-NEXT: #5: Indirect [R#6 + -16]
16 CHECK-NEXT: 1 live-outs: [ R#7 (8-bytes) ]
1515 #include "ARMWinEHPrinter.h"
1616 #include "Error.h"
1717 #include "ObjDumper.h"
18 #include "StackMapPrinter.h"
1819 #include "StreamWriter.h"
1920 #include "Win64EHDumper.h"
2021 #include "llvm/ADT/DenseMap.h"
5960 void printCOFFExports() override;
6061 void printCOFFDirectives() override;
6162 void printCOFFBaseReloc() override;
62
63 void printStackMap() const override;
6364 private:
6465 void printSymbol(const SymbolRef &Sym);
6566 void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
11391140 W.printHex("Address", RVA);
11401141 }
11411142 }
1143
1144 void COFFDumper::printStackMap() const {
1145 object::SectionRef StackMapSection;
1146 for (auto Sec : Obj->sections()) {
1147 StringRef Name;
1148 Sec.getName(Name);
1149 if (Name == ".llvm_stackmaps") {
1150 StackMapSection = Sec;
1151 break;
1152 }
1153 }
1154
1155 if (StackMapSection == object::SectionRef())
1156 return;
1157
1158 StringRef StackMapContents;
1159 StackMapSection.getContents(StackMapContents);
1160 ArrayRef StackMapContentsArray(
1161 reinterpret_cast(StackMapContents.data()),
1162 StackMapContents.size());
1163
1164 if (Obj->isLittleEndian())
1165 prettyPrintStackMap(
1166 llvm::outs(),
1167 StackMapV1Parser(StackMapContentsArray));
1168 else
1169 prettyPrintStackMap(llvm::outs(),
1170 StackMapV1Parser(StackMapContentsArray));
1171 }
1616 #include "ARMEHABIPrinter.h"
1717 #include "Error.h"
1818 #include "ObjDumper.h"
19 #include "StackMapPrinter.h"
1920 #include "StreamWriter.h"
2021 #include "llvm/ADT/Optional.h"
2122 #include "llvm/ADT/SmallString.h"
5960 void printMipsPLTGOT() override;
6061 void printMipsABIFlags() override;
6162 void printMipsReginfo() override;
63
64 void printStackMap() const override;
6265
6366 private:
6467 typedef ELFFile ELFO;
14931496 W.printHex("Co-Proc Mask2", Reginfo->ri_cprmask[2]);
14941497 W.printHex("Co-Proc Mask3", Reginfo->ri_cprmask[3]);
14951498 }
1499
1500 template void ELFDumper::printStackMap() const {
1501 const typename ELFFile::Elf_Shdr *StackMapSection = nullptr;
1502 for (const auto &Sec : Obj->sections()) {
1503 ErrorOr Name = Obj->getSectionName(&Sec);
1504 if (*Name == ".llvm_stackmaps") {
1505 StackMapSection = &Sec;
1506 break;
1507 }
1508 }
1509
1510 if (!StackMapSection)
1511 return;
1512
1513 StringRef StackMapContents;
1514 ErrorOr> StackMapContentsArray =
1515 Obj->getSectionContents(StackMapSection);
1516
1517 prettyPrintStackMap(
1518 llvm::outs(),
1519 StackMapV1Parser(*StackMapContentsArray));
1520 }
1313 #include "llvm-readobj.h"
1414 #include "Error.h"
1515 #include "ObjDumper.h"
16 #include "StackMapPrinter.h"
1617 #include "StreamWriter.h"
1718 #include "llvm/ADT/SmallString.h"
1819 #include "llvm/ADT/StringExtras.h"
3637 void printSymbols() override;
3738 void printDynamicSymbols() override;
3839 void printUnwindInfo() override;
40 void printStackMap() const override;
3941
4042 private:
4143 template
572574 void MachODumper::printUnwindInfo() {
573575 W.startLine() << "UnwindInfo not implemented.\n";
574576 }
577
578 void MachODumper::printStackMap() const {
579 object::SectionRef StackMapSection;
580 for (auto Sec : Obj->sections()) {
581 StringRef Name;
582 Sec.getName(Name);
583 if (Name == "__llvm_stackmaps") {
584 StackMapSection = Sec;
585 break;
586 }
587 }
588
589 if (StackMapSection == object::SectionRef())
590 return;
591
592 StringRef StackMapContents;
593 StackMapSection.getContents(StackMapContents);
594 ArrayRef StackMapContentsArray(
595 reinterpret_cast(StackMapContents.data()),
596 StackMapContents.size());
597
598 if (Obj->isLittleEndian())
599 prettyPrintStackMap(
600 llvm::outs(),
601 StackMapV1Parser(StackMapContentsArray));
602 else
603 prettyPrintStackMap(llvm::outs(),
604 StackMapV1Parser(StackMapContentsArray));
605 }
5151 virtual void printCOFFDirectives() { }
5252 virtual void printCOFFBaseReloc() { }
5353
54 virtual void printStackMap() const = 0;
55
5456 protected:
5557 StreamWriter& W;
5658 };
0 //===-------- StackMapPrinter.h - Pretty-print stackmaps --------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVM_READOBJ_STACKMAPPRINTER_H
10 #define LLVM_TOOLS_LLVM_READOBJ_STACKMAPPRINTER_H
11
12 #include "llvm/Object/StackMapParser.h"
13
14 namespace llvm {
15
16 // Pretty print a stackmap to the given ostream.
17 template
18 void prettyPrintStackMap(OStreamT &OS, const StackMapParserT &SMP) {
19
20 OS << "LLVM StackMap Version: " << SMP.getVersion()
21 << "\nNum Functions: " << SMP.getNumFunctions();
22
23 // Functions:
24 for (const auto &F : SMP.functions())
25 OS << "\n Function address: " << F.getFunctionAddress()
26 << ", stack size: " << F.getStackSize();
27
28 // Constants:
29 OS << "\nNum Constants: " << SMP.getNumConstants();
30 unsigned ConstantIndex = 0;
31 for (const auto &C : SMP.constants())
32 OS << "\n #" << ++ConstantIndex << ": " << C.getValue();
33
34 // Records:
35 OS << "\nNum Records: " << SMP.getNumRecords();
36 for (const auto &R : SMP.records()) {
37 OS << "\n Record ID: " << R.getID()
38 << ", instruction offset: " << R.getInstructionOffset()
39 << "\n " << R.getNumLocations() << " locations:";
40
41 unsigned LocationIndex = 0;
42 for (const auto &Loc : R.locations()) {
43 OS << "\n #" << ++LocationIndex << ": ";
44 switch (Loc.getKind()) {
45 case StackMapParserT::LocationKind::Register:
46 OS << "Register R#" << Loc.getDwarfRegNum();
47 break;
48 case StackMapParserT::LocationKind::Direct:
49 OS << "Direct R#" << Loc.getDwarfRegNum() << " + "
50 << Loc.getOffset();
51 break;
52 case StackMapParserT::LocationKind::Indirect:
53 OS << "Indirect [R#" << Loc.getDwarfRegNum() << " + "
54 << Loc.getOffset() << "]";
55 break;
56 case StackMapParserT::LocationKind::Constant:
57 OS << "Constant " << Loc.getSmallConstant();
58 break;
59 case StackMapParserT::LocationKind::ConstantIndex:
60 OS << "ConstantIndex #" << Loc.getConstantIndex() << " ("
61 << SMP.getConstant(Loc.getConstantIndex()).getValue() << ")";
62 break;
63 }
64 }
65
66 OS << "\n " << R.getNumLiveOuts() << " live-outs: [ ";
67 for (const auto &LO : R.liveouts())
68 OS << "R#" << LO.getDwarfRegNum() << " ("
69 << LO.getSizeInBytes() << "-bytes) ";
70 OS << "]\n";
71 }
72
73 OS << "\n";
74
75 }
76
77 }
78
79 #endif
175175 cl::opt
176176 COFFBaseRelocs("coff-basereloc",
177177 cl::desc("Display the PE/COFF .reloc section"));
178
179 // -stackmap
180 cl::opt
181 PrintStackMap("stackmap",
182 cl::desc("Display contents of stackmap section"));
183
178184 } // namespace opts
179185
180186 static int ReturnValue = EXIT_SUCCESS;
315321 Dumper->printCOFFDirectives();
316322 if (opts::COFFBaseRelocs)
317323 Dumper->printCOFFBaseReloc();
324
325 if (opts::PrintStackMap)
326 Dumper->printStackMap();
318327 }
319328
320329 /// @brief Dumps each object file in \a Arc;