llvm.org GIT mirror llvm / 93789c8
[XRay] Define the InstrumentationMap type Summary: This change implements the instrumentation map loading library which can understand both YAML-defined instrumentation maps, and ELF 64-bit object files that have the XRay instrumentation map section. We break it out into a library on its own to allow for other applications to deal with the XRay instrumentation map defined in XRay-instrumented binaries. This type provides both raw access to the logical representation of the instrumentation map entries as well as higher level functions for converting a function ID into a function address. At this point we only support ELF64 binaries and YAML-defined XRay instrumentation maps. Future changes should extend this to support 32-bit ELF binaries, as well as other binary formats (like MachO). As part of this change we also migrate all uses of the extraction logic that used to be defined in tools/llvm-xray/ to use this new type and interface for loading from files. We also remove the flag from the `llvm-xray` tool that required users to specify the type of the instrumentation map file being provided to instead make the library auto-detect the file type. Reviewers: dblaikie Subscribers: mgorny, varno, llvm-commits Differential Revision: https://reviews.llvm.org/D29319 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293721 91177308-0d34-0410-b5e6-96231b3b80d8 Dean Michael Berris 2 years ago
17 changed file(s) with 475 addition(s) and 481 deletion(s). Raw diff Collapse all Expand all
0 //===- InstrumentationMap.h - XRay Instrumentation Map --------------------===//
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 // Defines the interface for extracting the instrumentation map from an
10 // XRay-instrumented binary.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_XRAY_INSTRUMENTATION_MAP_H
15 #define LLVM_XRAY_INSTRUMENTATION_MAP_H
16
17 #include
18 #include
19 #include
20
21 #include "llvm/ADT/Optional.h"
22 #include "llvm/ADT/iterator_range.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/YAMLTraits.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 namespace llvm {
28 namespace xray {
29
30 // Forward declare to make a friend.
31 class InstrumentationMap;
32
33 /// Loads the instrumentation map from |Filename|. This auto-deduces the type of
34 /// the instrumentation map.
35 Expected loadInstrumentationMap(StringRef Filename);
36
37 /// Represents an XRay instrumentation sled entry from an object file.
38 struct SledEntry {
39
40 /// Each entry here represents the kinds of supported instrumentation map
41 /// entries.
42 enum class FunctionKinds { ENTRY, EXIT, TAIL };
43
44 /// The address of the sled.
45 uint64_t Address;
46
47 /// The address of the function.
48 uint64_t Function;
49
50 /// The kind of sled.
51 FunctionKinds Kind;
52
53 /// Whether the sled was annotated to always be instrumented.
54 bool AlwaysInstrument;
55 };
56
57 struct YAMLXRaySledEntry {
58 int32_t FuncId;
59 yaml::Hex64 Address;
60 yaml::Hex64 Function;
61 SledEntry::FunctionKinds Kind;
62 bool AlwaysInstrument;
63 };
64
65 /// The InstrumentationMap represents the computed function id's and indicated
66 /// function addresses from an object file (or a YAML file). This provides an
67 /// interface to just the mapping between the function id, and the function
68 /// address.
69 ///
70 /// We also provide raw access to the actual instrumentation map entries we find
71 /// associated with a particular object file.
72 ///
73 class InstrumentationMap {
74 public:
75 using FunctionAddressMap = std::unordered_map;
76 using FunctionAddressReverseMap = std::unordered_map;
77 using SledContainer = std::vector;
78
79 private:
80 SledContainer Sleds;
81 FunctionAddressMap FunctionAddresses;
82 FunctionAddressReverseMap FunctionIds;
83
84 friend Expected loadInstrumentationMap(StringRef);
85
86 public:
87 /// Provides a raw accessor to the unordered map of function addresses.
88 const FunctionAddressMap &getFunctionAddresses() { return FunctionAddresses; }
89
90 /// Returns an XRay computed function id, provided a function address.
91 Optional getFunctionId(uint64_t Addr) const;
92
93 /// Returns the function address for a function id.
94 Optional getFunctionAddr(int32_t FuncId) const;
95
96 /// Provide read-only access to the entries of the instrumentation map.
97 const SledContainer &sleds() const { return Sleds; };
98 };
99
100 } // namespace xray
101 } // namespace llvm
102
103 namespace llvm {
104 namespace yaml {
105
106 template <> struct ScalarEnumerationTraits {
107 static void enumeration(IO &IO, xray::SledEntry::FunctionKinds &Kind) {
108 IO.enumCase(Kind, "function-enter", xray::SledEntry::FunctionKinds::ENTRY);
109 IO.enumCase(Kind, "function-exit", xray::SledEntry::FunctionKinds::EXIT);
110 IO.enumCase(Kind, "tail-exit", xray::SledEntry::FunctionKinds::TAIL);
111 }
112 };
113
114 template <> struct MappingTraits {
115 static void mapping(IO &IO, xray::YAMLXRaySledEntry &Entry) {
116 IO.mapRequired("id", Entry.FuncId);
117 IO.mapRequired("address", Entry.Address);
118 IO.mapRequired("function", Entry.Function);
119 IO.mapRequired("kind", Entry.Kind);
120 IO.mapRequired("always-instrument", Entry.AlwaysInstrument);
121 }
122
123 static constexpr bool flow = true;
124 };
125 } // namespace yaml
126 } // namespace llvm
127
128 LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRaySledEntry)
129
130 #endif // LLVM_XRAY_INSTRUMENTATION_MAP_H
0 add_llvm_library(LLVMXRay
1 InstrumentationMap.cpp
12 Trace.cpp
23
34 ADDITIONAL_HEADER_DIRS
67
78 DEPENDS
89 LLVMSupport
10 LLVMObject
911
1012 LINK_LIBS
1113 LLVMSupport
14 LLVMObject
1215 )
0 //===- InstrumentationMap.cpp - XRay Instrumentation Map ------------------===//
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 // Implementation of the InstrumentationMap type for XRay sleds.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef XRAY_INSTRUMENTATIONMAP_H
14 #define XRAY_INSTRUMENTATIONMAP_H
15
16 #include "llvm/XRay/InstrumentationMap.h"
17
18 #include "llvm/Object/ObjectFile.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/FileSystem.h"
21 #include "llvm/XRay/XRayRecord.h"
22 #include
23
24 namespace llvm {
25 namespace xray {
26
27 Optional InstrumentationMap::getFunctionId(uint64_t Addr) const {
28 auto I = FunctionIds.find(Addr);
29 if (I != FunctionIds.end())
30 return I->second;
31 return None;
32 }
33
34 Optional InstrumentationMap::getFunctionAddr(int32_t FuncId) const {
35 auto I = FunctionAddresses.find(FuncId);
36 if (I != FunctionAddresses.end())
37 return I->second;
38 return None;
39 }
40
41 namespace {
42 Error loadELF64(StringRef Filename,
43 object::OwningBinary &ObjFile,
44 InstrumentationMap::SledContainer &Sleds,
45 InstrumentationMap::FunctionAddressMap &FunctionAddresses,
46 InstrumentationMap::FunctionAddressReverseMap &FunctionIds) {
47 InstrumentationMap Map;
48
49 // Find the section named "xray_instr_map".
50 if (!ObjFile.getBinary()->isELF() ||
51 ObjFile.getBinary()->getArch() != Triple::x86_64)
52 return make_error(
53 "File format not supported (only does ELF little endian 64-bit).",
54 std::make_error_code(std::errc::not_supported));
55
56 StringRef Contents = "";
57 const auto &Sections = ObjFile.getBinary()->sections();
58 auto I = find_if(Sections, [&](object::SectionRef Section) {
59 StringRef Name = "";
60 if (Section.getName(Name))
61 return false;
62 return Name == "xray_instr_map";
63 });
64
65 if (I == Sections.end())
66 return make_error(
67 "Failed to find XRay instrumentation map.",
68 std::make_error_code(std::errc::executable_format_error));
69
70 if (I->getContents(Contents))
71 return errorCodeToError(
72 std::make_error_code(std::errc::executable_format_error));
73
74 // Copy the instrumentation map data into the Sleds data structure.
75 auto C = Contents.bytes_begin();
76 static constexpr size_t ELF64SledEntrySize = 32;
77
78 if ((C - Contents.bytes_end()) % ELF64SledEntrySize != 0)
79 return make_error(
80 Twine("Instrumentation map entries not evenly divisible by size of "
81 "an XRay sled entry in ELF64."),
82 std::make_error_code(std::errc::executable_format_error));
83
84 int32_t FuncId = 1;
85 uint64_t CurFn = 0;
86 for (; C != Contents.bytes_end(); C += ELF64SledEntrySize) {
87 DataExtractor Extractor(
88 StringRef(reinterpret_cast(C), ELF64SledEntrySize), true,
89 8);
90 Sleds.push_back({});
91 auto &Entry = Sleds.back();
92 uint32_t OffsetPtr = 0;
93 Entry.Address = Extractor.getU64(&OffsetPtr);
94 Entry.Function = Extractor.getU64(&OffsetPtr);
95 auto Kind = Extractor.getU8(&OffsetPtr);
96 static constexpr SledEntry::FunctionKinds Kinds[] = {
97 SledEntry::FunctionKinds::ENTRY, SledEntry::FunctionKinds::EXIT,
98 SledEntry::FunctionKinds::TAIL,
99 };
100 if (Kind >= sizeof(Kinds))
101 return errorCodeToError(
102 std::make_error_code(std::errc::executable_format_error));
103 Entry.Kind = Kinds[Kind];
104 Entry.AlwaysInstrument = Extractor.getU8(&OffsetPtr) != 0;
105
106 // We do replicate the function id generation scheme implemented in the
107 // XRay runtime.
108 // FIXME: Figure out how to keep this consistent with the XRay runtime.
109 if (CurFn == 0) {
110 CurFn = Entry.Function;
111 FunctionAddresses[FuncId] = Entry.Function;
112 FunctionIds[Entry.Function] = FuncId;
113 }
114 if (Entry.Function != CurFn) {
115 ++FuncId;
116 CurFn = Entry.Function;
117 FunctionAddresses[FuncId] = Entry.Function;
118 FunctionIds[Entry.Function] = FuncId;
119 }
120 }
121 return Error::success();
122 }
123
124 Error loadYAML(int Fd, size_t FileSize, StringRef Filename,
125 InstrumentationMap::SledContainer &Sleds,
126 InstrumentationMap::FunctionAddressMap &FunctionAddresses,
127 InstrumentationMap::FunctionAddressReverseMap &FunctionIds) {
128 std::error_code EC;
129 sys::fs::mapped_file_region MappedFile(
130 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
131 if (EC)
132 return make_error(
133 Twine("Failed memory-mapping file '") + Filename + "'.", EC);
134
135 std::vector YAMLSleds;
136 yaml::Input In(StringRef(MappedFile.data(), MappedFile.size()));
137 In >> YAMLSleds;
138 if (In.error())
139 return make_error(
140 Twine("Failed loading YAML document from '") + Filename + "'.",
141 In.error());
142
143 Sleds.reserve(YAMLSleds.size());
144 for (const auto &Y : YAMLSleds) {
145 FunctionAddresses[Y.FuncId] = Y.Function;
146 FunctionIds[Y.Function] = Y.FuncId;
147 Sleds.push_back(
148 SledEntry{Y.Address, Y.Function, Y.Kind, Y.AlwaysInstrument});
149 }
150 return Error::success();
151 }
152 } // namespace
153
154 // FIXME: Create error types that encapsulate a bit more information than what
155 // StringError instances contain.
156 Expected loadInstrumentationMap(StringRef Filename) {
157 // At this point we assume the file is an object file -- and if that doesn't
158 // work, we treat it as YAML.
159 // FIXME: Extend to support non-ELF and non-x86_64 binaries.
160
161 InstrumentationMap Map;
162 auto ObjectFileOrError = object::ObjectFile::createObjectFile(Filename);
163 if (!ObjectFileOrError) {
164 auto E = ObjectFileOrError.takeError();
165 // We try to load it as YAML if the ELF load didn't work.
166 int Fd;
167 if (sys::fs::openFileForRead(Filename, Fd))
168 return std::move(E);
169
170 uint64_t FileSize;
171 if (sys::fs::file_size(Filename, FileSize))
172 return std::move(E);
173
174 // If the file is empty, we return the original error.
175 if (FileSize == 0)
176 return std::move(E);
177
178 // From this point on the errors will be only for the YAML parts, so we
179 // consume the errors at this point.
180 consumeError(std::move(E));
181 if (auto E = loadYAML(Fd, FileSize, Filename, Map.Sleds,
182 Map.FunctionAddresses, Map.FunctionIds))
183 return std::move(E);
184 } else if (auto E = loadELF64(Filename, *ObjectFileOrError, Map.Sleds,
185 Map.FunctionAddresses, Map.FunctionIds)) {
186 return std::move(E);
187 }
188 return Map;
189 }
190 }
191 }
192
193 #endif // XRAY_INSTRUMENTATIONMAP_H
None #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d | FileCheck %s
0 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -d | FileCheck %s
11 ---
22 header:
33 version: 1
None #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -k | FileCheck %s
0 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -k | FileCheck %s
11 ---
22 header:
33 version: 1
None #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml | FileCheck %s
0 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml | FileCheck %s
11 ---
22 header:
33 version: 1
None #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml | FileCheck --check-prefix DEFAULT %s
1 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s count | FileCheck --check-prefix COUNT-ASC %s
2 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s min | FileCheck --check-prefix MIN-ASC %s
3 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s max | FileCheck --check-prefix MAX-ASC %s
4 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s sum | FileCheck --check-prefix SUM-ASC %s
0 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml | FileCheck --check-prefix DEFAULT %s
1 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s count | FileCheck --check-prefix COUNT-ASC %s
2 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s min | FileCheck --check-prefix MIN-ASC %s
3 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s max | FileCheck --check-prefix MAX-ASC %s
4 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s sum | FileCheck --check-prefix SUM-ASC %s
55
6 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s count -r dsc | FileCheck --check-prefix COUNT-DSC %s
7 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s min -r dsc | FileCheck --check-prefix MIN-DSC %s
8 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s max -r dsc | FileCheck --check-prefix MAX-DSC %s
9 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -s sum -r dsc | FileCheck --check-prefix SUM-DSC %s
6 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s count -r dsc | FileCheck --check-prefix COUNT-DSC %s
7 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s min -r dsc | FileCheck --check-prefix MIN-DSC %s
8 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s max -r dsc | FileCheck --check-prefix MAX-DSC %s
9 #RUN: llvm-xray account %s -o - -m %S/Inputs/simple-instrmap.yaml -s sum -r dsc | FileCheck --check-prefix SUM-DSC %s
1010 ---
1111 header:
1212 version: 1
None ; RUN: llvm-xray convert -m %S/Inputs/simple-xray-instrmap.yaml -t yaml %S/Inputs/naive-log-simple.xray -f=yaml -o - | FileCheck %s
0 ; RUN: llvm-xray convert -m %S/Inputs/simple-xray-instrmap.yaml %S/Inputs/naive-log-simple.xray -f=yaml -o - | FileCheck %s
11
22 ; CHECK: ---
33 ; CHECK-NEXT: header:
None #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e sum -c sum \
0 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e sum -c sum \
11 #RUN: | FileCheck %s -check-prefix=EDGE
2 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -v sum -b sum \
2 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -v sum -b sum \
33 #RUN: | FileCheck %s -check-prefix=VERTEX
44 ---
55 header:
None #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d \
0 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d \
11 #RUN: | FileCheck %s -check-prefix=EMPTY
2 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d -e count \
2 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d -e count \
33 #RUN: | FileCheck %s -check-prefix=COUNT
44 #
5 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d -e min \
5 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d -e min \
66 #RUN: | FileCheck %s -check-prefix=TIME
7 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d -e med \
7 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d -e med \
88 #RUN: | FileCheck %s -check-prefix=TIME
9 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d -e 90p \
9 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d -e 90p \
1010 #RUN: | FileCheck %s -check-prefix=TIME
11 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d -e 99p \
11 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d -e 99p \
1212 #RUN: | FileCheck %s -check-prefix=TIME
13 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d -e max \
13 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d -e max \
1414 #RUN: | FileCheck %s -check-prefix=TIME
15 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -d -e sum \
15 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -d -e sum \
1616 #RUN: | FileCheck %s -check-prefix=TIME
1717 #
1818 ---
None #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml \
0 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml \
11 #RUN: | FileCheck %s -check-prefix=EMPTY
2 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e count \
2 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e count \
33 #RUN: | FileCheck %s -check-prefix=COUNT
44 #
5 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e min \
5 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e min \
66 #RUN: | FileCheck %s -check-prefix=TIME
7 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e med \
7 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e med \
88 #RUN: | FileCheck %s -check-prefix=TIME
9 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e 90p \
9 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e 90p \
1010 #RUN: | FileCheck %s -check-prefix=TIME
11 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e 99p \
11 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e 99p \
1212 #RUN: | FileCheck %s -check-prefix=TIME
13 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e max \
13 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e max \
1414 #RUN: | FileCheck %s -check-prefix=TIME
15 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -t yaml -e sum \
15 #RUN: llvm-xray graph %s -o - -m %S/Inputs/simple-instrmap.yaml -e sum \
1616 #RUN: | FileCheck %s -check-prefix=TIME
1717 ---
1818 header:
1717 #include
1818
1919 #include "xray-account.h"
20 #include "xray-extract.h"
2120 #include "xray-registry.h"
2221 #include "llvm/Support/ErrorHandling.h"
2322 #include "llvm/Support/FormatVariadic.h"
23 #include "llvm/XRay/InstrumentationMap.h"
2424 #include "llvm/XRay/Trace.h"
2525
2626 using namespace llvm;
119119 static cl::alias AccountInstrMap2("m", cl::aliasopt(AccountInstrMap),
120120 cl::desc("Alias for -instr_map"),
121121 cl::sub(Account));
122 static cl::opt InstrMapFormat(
123 "instr-map-format", cl::desc("format of instrumentation map"),
124 cl::values(clEnumValN(InstrumentationMapExtractor::InputFormats::ELF, "elf",
125 "instrumentation map in an ELF header"),
126 clEnumValN(InstrumentationMapExtractor::InputFormats::YAML,
127 "yaml", "instrumentation map in YAML")),
128 cl::sub(Account), cl::init(InstrumentationMapExtractor::InputFormats::ELF));
129 static cl::alias InstrMapFormat2("t", cl::aliasopt(InstrMapFormat),
130 cl::desc("Alias for -instr-map-format"),
131 cl::sub(Account));
132122
133123 namespace {
134124
417407 using namespace llvm::xray;
418408
419409 static CommandRegistration Unused(&Account, []() -> Error {
420 int Fd;
421 auto EC = sys::fs::openFileForRead(AccountInput, Fd);
422 if (EC)
423 return make_error(
424 Twine("Cannot open file '") + AccountInput + "'", EC);
425
426 Error Err = Error::success();
427 xray::InstrumentationMapExtractor Extractor(AccountInstrMap, InstrMapFormat,
428 Err);
429 if (auto E = handleErrors(
430 std::move(Err), [&](std::unique_ptr SE) -> Error {
431 if (SE->convertToErrorCode() == std::errc::no_such_file_or_directory)
432 return Error::success();
433 return Error(std::move(SE));
434 }))
435 return E;
436
410 InstrumentationMap Map;
411 if (!AccountInstrMap.empty()) {
412 auto InstrumentationMapOrError = loadInstrumentationMap(AccountInstrMap);
413 if (!InstrumentationMapOrError)
414 return joinErrors(make_error(
415 Twine("Cannot open instrumentation map '") +
416 AccountInstrMap + "'",
417 std::make_error_code(std::errc::invalid_argument)),
418 InstrumentationMapOrError.takeError());
419 Map = std::move(*InstrumentationMapOrError);
420 }
421
422 std::error_code EC;
437423 raw_fd_ostream OS(AccountOutput, EC, sys::fs::OpenFlags::F_Text);
438424 if (EC)
439425 return make_error(
440426 Twine("Cannot open file '") + AccountOutput + "' for writing.", EC);
441427
442 const auto &FunctionAddresses = Extractor.getFunctionAddresses();
428 const auto &FunctionAddresses = Map.getFunctionAddresses();
443429 symbolize::LLVMSymbolizer::Options Opts(
444430 symbolize::FunctionNameKind::LinkageName, true, true, false, "");
445431 symbolize::LLVMSymbolizer Symbolizer(Opts);
446432 llvm::xray::FuncIdConversionHelper FuncIdHelper(AccountInstrMap, Symbolizer,
447433 FunctionAddresses);
448434 xray::LatencyAccountant FCA(FuncIdHelper, AccountDeduceSiblingCalls);
449 if (auto TraceOrErr = loadTraceFile(AccountInput)) {
450 auto &T = *TraceOrErr;
451 for (const auto &Record : T) {
452 if (FCA.accountRecord(Record))
453 continue;
454 for (const auto &ThreadStack : FCA.getPerThreadFunctionStack()) {
455 errs() << "Thread ID: " << ThreadStack.first << "\n";
456 auto Level = ThreadStack.second.size();
457 for (const auto &Entry : llvm::reverse(ThreadStack.second))
458 errs() << "#" << Level-- << "\t"
459 << FuncIdHelper.SymbolOrNumber(Entry.first) << '\n';
460 }
461 if (!AccountKeepGoing)
462 return make_error(
463 Twine("Failed accounting function calls in file '") + AccountInput +
464 "'.",
465 std::make_error_code(std::errc::executable_format_error));
466 }
467 switch (AccountOutputFormat) {
468 case AccountOutputFormats::TEXT:
469 FCA.exportStatsAsText(OS, T.getFileHeader());
470 break;
471 case AccountOutputFormats::CSV:
472 FCA.exportStatsAsCSV(OS, T.getFileHeader());
473 break;
474 }
475 } else {
435 auto TraceOrErr = loadTraceFile(AccountInput);
436 if (!TraceOrErr)
476437 return joinErrors(
477438 make_error(
478439 Twine("Failed loading input file '") + AccountInput + "'",
479440 std::make_error_code(std::errc::executable_format_error)),
480441 TraceOrErr.takeError());
442
443 auto &T = *TraceOrErr;
444 for (const auto &Record : T) {
445 if (FCA.accountRecord(Record))
446 continue;
447 for (const auto &ThreadStack : FCA.getPerThreadFunctionStack()) {
448 errs() << "Thread ID: " << ThreadStack.first << "\n";
449 auto Level = ThreadStack.second.size();
450 for (const auto &Entry : llvm::reverse(ThreadStack.second))
451 errs() << "#" << Level-- << "\t"
452 << FuncIdHelper.SymbolOrNumber(Entry.first) << '\n';
453 }
454 if (!AccountKeepGoing)
455 return make_error(
456 Twine("Failed accounting function calls in file '") + AccountInput +
457 "'.",
458 std::make_error_code(std::errc::executable_format_error));
459 }
460 switch (AccountOutputFormat) {
461 case AccountOutputFormats::TEXT:
462 FCA.exportStatsAsText(OS, T.getFileHeader());
463 break;
464 case AccountOutputFormats::CSV:
465 FCA.exportStatsAsCSV(OS, T.getFileHeader());
466 break;
481467 }
482468
483469 return Error::success();
1111 //===----------------------------------------------------------------------===//
1212 #include "xray-converter.h"
1313
14 #include "xray-extract.h"
1514 #include "xray-registry.h"
1615 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
1716 #include "llvm/Support/EndianStream.h"
1918 #include "llvm/Support/ScopedPrinter.h"
2019 #include "llvm/Support/YAMLTraits.h"
2120 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/XRay/InstrumentationMap.h"
2222 #include "llvm/XRay/Trace.h"
2323 #include "llvm/XRay/YAMLXRayRecord.h"
2424
7272 static cl::alias ConvertSortInput2("s", cl::aliasopt(ConvertSortInput),
7373 cl::desc("Alias for -sort"),
7474 cl::sub(Convert));
75 static cl::opt InstrMapFormat(
76 "instr-map-format", cl::desc("format of instrumentation map"),
77 cl::values(clEnumValN(InstrumentationMapExtractor::InputFormats::ELF, "elf",
78 "instrumentation map in an ELF header"),
79 clEnumValN(InstrumentationMapExtractor::InputFormats::YAML,
80 "yaml", "instrumentation map in YAML")),
81 cl::sub(Convert), cl::init(InstrumentationMapExtractor::InputFormats::ELF));
82 static cl::alias InstrMapFormat2("t", cl::aliasopt(InstrMapFormat),
83 cl::desc("Alias for -instr-map-format"),
84 cl::sub(Convert));
8575
8676 using llvm::yaml::Output;
8777
150140
151141 static CommandRegistration Unused(&Convert, []() -> Error {
152142 // FIXME: Support conversion to BINARY when upgrading XRay trace versions.
153 int Fd;
154 auto EC = sys::fs::openFileForRead(ConvertInput, Fd);
155 if (EC)
156 return make_error(
157 Twine("Cannot open file '") + ConvertInput + "'", EC);
143 InstrumentationMap Map;
144 if (!ConvertInstrMap.empty()) {
145 auto InstrumentationMapOrError = loadInstrumentationMap(ConvertInstrMap);
146 if (!InstrumentationMapOrError)
147 return joinErrors(make_error(
148 Twine("Cannot open instrumentation map '") +
149 ConvertInstrMap + "'",
150 std::make_error_code(std::errc::invalid_argument)),
151 InstrumentationMapOrError.takeError());
152 Map = std::move(*InstrumentationMapOrError);
153 }
158154
159 Error Err = Error::success();
160 xray::InstrumentationMapExtractor Extractor(ConvertInstrMap, InstrMapFormat,
161 Err);
162 handleAllErrors(std::move(Err),
163 [&](const ErrorInfoBase &E) { E.log(errs()); });
164
165 const auto &FunctionAddresses = Extractor.getFunctionAddresses();
155 const auto &FunctionAddresses = Map.getFunctionAddresses();
166156 symbolize::LLVMSymbolizer::Options Opts(
167157 symbolize::FunctionNameKind::LinkageName, true, true, false, "");
168158 symbolize::LLVMSymbolizer Symbolizer(Opts);
169159 llvm::xray::FuncIdConversionHelper FuncIdHelper(ConvertInstrMap, Symbolizer,
170160 FunctionAddresses);
171161 llvm::xray::TraceConverter TC(FuncIdHelper, ConvertSymbolize);
162 std::error_code EC;
172163 raw_fd_ostream OS(ConvertOutput, EC,
173164 ConvertOutputFormat == ConvertFormats::BINARY
174165 ? sys::fs::OpenFlags::F_None
177168 return make_error(
178169 Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
179170
180 if (auto TraceOrErr = loadTraceFile(ConvertInput, ConvertSortInput)) {
181 auto &T = *TraceOrErr;
182 switch (ConvertOutputFormat) {
183 case ConvertFormats::YAML:
184 TC.exportAsYAML(T, OS);
185 break;
186 case ConvertFormats::BINARY:
187 TC.exportAsRAWv1(T, OS);
188 break;
189 }
190 } else {
171 auto TraceOrErr = loadTraceFile(ConvertInput, ConvertSortInput);
172 if (!TraceOrErr)
191173 return joinErrors(
192174 make_error(
193175 Twine("Failed loading input file '") + ConvertInput + "'.",
194176 std::make_error_code(std::errc::executable_format_error)),
195177 TraceOrErr.takeError());
178
179 auto &T = *TraceOrErr;
180 switch (ConvertOutputFormat) {
181 case ConvertFormats::YAML:
182 TC.exportAsYAML(T, OS);
183 break;
184 case ConvertFormats::BINARY:
185 TC.exportAsRAWv1(T, OS);
186 break;
196187 }
197188 return Error::success();
198189 });
1515 #include
1616 #include
1717
18 #include "xray-extract.h"
19
2018 #include "xray-registry.h"
21 #include "xray-sleds.h"
2219 #include "llvm/Object/ELF.h"
2320 #include "llvm/Object/ObjectFile.h"
2421 #include "llvm/Support/CommandLine.h"
2724 #include "llvm/Support/Error.h"
2825 #include "llvm/Support/FileSystem.h"
2926 #include "llvm/Support/Format.h"
30 #include "llvm/Support/YAMLTraits.h"
3127 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/XRay/InstrumentationMap.h"
3229
3330 using namespace llvm;
3431 using namespace llvm::xray;
4845 cl::desc("Alias for -output"),
4946 cl::sub(Extract));
5047
51 struct YAMLXRaySledEntry {
52 int32_t FuncId;
53 Hex64 Address;
54 Hex64 Function;
55 SledEntry::FunctionKinds Kind;
56 bool AlwaysInstrument;
57 };
58
59 namespace llvm {
60 namespace yaml {
61
62 template <> struct ScalarEnumerationTraits {
63 static void enumeration(IO &IO, SledEntry::FunctionKinds &Kind) {
64 IO.enumCase(Kind, "function-enter", SledEntry::FunctionKinds::ENTRY);
65 IO.enumCase(Kind, "function-exit", SledEntry::FunctionKinds::EXIT);
66 IO.enumCase(Kind, "tail-exit", SledEntry::FunctionKinds::TAIL);
67 }
68 };
69
70 template <> struct MappingTraits {
71 static void mapping(IO &IO, YAMLXRaySledEntry &Entry) {
72 IO.mapRequired("id", Entry.FuncId);
73 IO.mapRequired("address", Entry.Address);
74 IO.mapRequired("function", Entry.Function);
75 IO.mapRequired("kind", Entry.Kind);
76 IO.mapRequired("always-instrument", Entry.AlwaysInstrument);
77 }
78
79 static constexpr bool flow = true;
80 };
81 }
82 }
83
84 LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLXRaySledEntry)
85
8648 namespace {
8749
88 llvm::Error LoadBinaryInstrELF(
89 StringRef Filename, std::deque &OutputSleds,
90 InstrumentationMapExtractor::FunctionAddressMap &InstrMap,
91 InstrumentationMapExtractor::FunctionAddressReverseMap &FunctionIds) {
92 auto ObjectFile = object::ObjectFile::createObjectFile(Filename);
93
94 if (!ObjectFile)
95 return ObjectFile.takeError();
96
97 // FIXME: Maybe support other ELF formats. For now, 64-bit Little Endian only.
98 if (!ObjectFile->getBinary()->isELF())
99 return make_error(
100 "File format not supported (only does ELF).",
101 std::make_error_code(std::errc::not_supported));
102 if (ObjectFile->getBinary()->getArch() != Triple::x86_64)
103 return make_error(
104 "File format not supported (only does ELF little endian 64-bit).",
105 std::make_error_code(std::errc::not_supported));
106
107 // Find the section named "xray_instr_map".
108 StringRef Contents = "";
109 const auto &Sections = ObjectFile->getBinary()->sections();
110 auto I = find_if(Sections, [&](object::SectionRef Section) {
111 StringRef Name = "";
112 if (Section.getName(Name))
113 return false;
114 return Name == "xray_instr_map";
115 });
116 if (I == Sections.end())
117 return make_error(
118 "Failed to find XRay instrumentation map.",
119 std::make_error_code(std::errc::not_supported));
120 if (I->getContents(Contents))
121 return make_error(
122 "Failed to get contents of 'xray_instr_map' section.",
123 std::make_error_code(std::errc::executable_format_error));
124
125 // Copy the instrumentation map data into the Sleds data structure.
126 auto C = Contents.bytes_begin();
127 static constexpr size_t ELF64SledEntrySize = 32;
128
129 if ((C - Contents.bytes_end()) % ELF64SledEntrySize != 0)
130 return make_error(
131 "Instrumentation map entries not evenly divisible by size of an XRay "
132 "sled entry in ELF64.",
133 std::make_error_code(std::errc::executable_format_error));
134
135 int32_t FuncId = 1;
136 uint64_t CurFn = 0;
137 std::deque Sleds;
138 for (; C != Contents.bytes_end(); C += ELF64SledEntrySize) {
139 DataExtractor Extractor(
140 StringRef(reinterpret_cast(C), ELF64SledEntrySize), true,
141 8);
142 Sleds.push_back({});
143 auto &Entry = Sleds.back();
144 uint32_t OffsetPtr = 0;
145 Entry.Address = Extractor.getU64(&OffsetPtr);
146 Entry.Function = Extractor.getU64(&OffsetPtr);
147 auto Kind = Extractor.getU8(&OffsetPtr);
148 switch (Kind) {
149 case 0: // ENTRY
150 Entry.Kind = SledEntry::FunctionKinds::ENTRY;
151 break;
152 case 1: // EXIT
153 Entry.Kind = SledEntry::FunctionKinds::EXIT;
154 break;
155 case 2: // TAIL
156 Entry.Kind = SledEntry::FunctionKinds::TAIL;
157 break;
158 default:
159 return make_error(
160 Twine("Encountered unknown sled type ") + "'" + Twine(int32_t{Kind}) +
161 "'.",
162 std::make_error_code(std::errc::executable_format_error));
163 }
164 Entry.AlwaysInstrument = Extractor.getU8(&OffsetPtr) != 0;
165
166 // We replicate the function id generation scheme implemented in the runtime
167 // here. Ideally we should be able to break it out, or output this map from
168 // the runtime, but that's a design point we can discuss later on. For now,
169 // we replicate the logic and move on.
170 if (CurFn == 0) {
171 CurFn = Entry.Function;
172 InstrMap[FuncId] = Entry.Function;
173 FunctionIds[Entry.Function] = FuncId;
174 }
175 if (Entry.Function != CurFn) {
176 ++FuncId;
177 CurFn = Entry.Function;
178 InstrMap[FuncId] = Entry.Function;
179 FunctionIds[Entry.Function] = FuncId;
180 }
181 }
182 OutputSleds = std::move(Sleds);
183 return llvm::Error::success();
184 }
185
186 Error LoadYAMLInstrMap(
187 StringRef Filename, std::deque &Sleds,
188 InstrumentationMapExtractor::FunctionAddressMap &InstrMap,
189 InstrumentationMapExtractor::FunctionAddressReverseMap &FunctionIds) {
190 int Fd;
191 if (auto EC = sys::fs::openFileForRead(Filename, Fd))
192 return make_error(
193 Twine("Failed opening file '") + Filename + "' for reading.", EC);
194
195 uint64_t FileSize;
196 if (auto EC = sys::fs::file_size(Filename, FileSize))
197 return make_error(
198 Twine("Failed getting size of file '") + Filename + "'.", EC);
199
200 std::error_code EC;
201 sys::fs::mapped_file_region MappedFile(
202 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
203 if (EC)
204 return make_error(
205 Twine("Failed memory-mapping file '") + Filename + "'.", EC);
206
207 std::vector YAMLSleds;
208 Input In(StringRef(MappedFile.data(), MappedFile.size()));
209 In >> YAMLSleds;
210 if (In.error())
211 return make_error(
212 Twine("Failed loading YAML document from '") + Filename + "'.",
213 In.error());
214
215 for (const auto &Y : YAMLSleds) {
216 InstrMap[Y.FuncId] = Y.Function;
217 FunctionIds[Y.Function] = Y.FuncId;
218 Sleds.push_back(
219 SledEntry{Y.Address, Y.Function, Y.Kind, Y.AlwaysInstrument});
220 }
221 return Error::success();
222 }
223
224 } // namespace
225
226 InstrumentationMapExtractor::InstrumentationMapExtractor(std::string Filename,
227 InputFormats Format,
228 Error &EC) {
229 ErrorAsOutParameter ErrAsOutputParam(&EC);
230 if (Filename.empty()) {
231 EC = Error::success();
232 return;
233 }
234 switch (Format) {
235 case InputFormats::ELF: {
236 EC = handleErrors(
237 LoadBinaryInstrELF(Filename, Sleds, FunctionAddresses, FunctionIds),
238 [&](std::unique_ptr E) {
239 return joinErrors(
240 make_error(
241 Twine("Cannot extract instrumentation map from '") +
242 Filename + "'.",
243 std::make_error_code(std::errc::executable_format_error)),
244 std::move(E));
245 });
246 break;
247 }
248 case InputFormats::YAML: {
249 EC = handleErrors(
250 LoadYAMLInstrMap(Filename, Sleds, FunctionAddresses, FunctionIds),
251 [&](std::unique_ptr E) {
252 return joinErrors(
253 make_error(
254 Twine("Cannot load YAML instrumentation map from '") +
255 Filename + "'.",
256 std::make_error_code(std::errc::executable_format_error)),
257 std::move(E));
258 });
259 break;
260 }
261 }
262 }
263
264 void InstrumentationMapExtractor::exportAsYAML(raw_ostream &OS) {
50 void exportAsYAML(const InstrumentationMap &Map, raw_ostream &OS) {
26551 // First we translate the sleds into the YAMLXRaySledEntry objects in a deque.
26652 std::vector YAMLSleds;
267 YAMLSleds.reserve(Sleds.size());
53 auto Sleds = Map.sleds();
54 YAMLSleds.reserve(std::distance(Sleds.begin(), Sleds.end()));
26855 for (const auto &Sled : Sleds) {
269 YAMLSleds.push_back({FunctionIds[Sled.Function], Sled.Address,
270 Sled.Function, Sled.Kind, Sled.AlwaysInstrument});
56 auto FuncId = Map.getFunctionId(Sled.Function);
57 if (!FuncId)
58 return;
59 YAMLSleds.push_back({*FuncId, Sled.Address, Sled.Function, Sled.Kind,
60 Sled.AlwaysInstrument});
27161 }
27262 Output Out(OS);
27363 Out << YAMLSleds;
27464 }
27565
66 } // namespace
67
27668 static CommandRegistration Unused(&Extract, []() -> Error {
277 Error Err = Error::success();
278 xray::InstrumentationMapExtractor Extractor(
279 ExtractInput, InstrumentationMapExtractor::InputFormats::ELF, Err);
280 if (Err)
281 return Err;
69 auto InstrumentationMapOrError = loadInstrumentationMap(ExtractInput);
70 if (!InstrumentationMapOrError)
71 return joinErrors(make_error(
72 Twine("Cannot extract instrumentation map from '") +
73 ExtractInput + "'.",
74 std::make_error_code(std::errc::invalid_argument)),
75 InstrumentationMapOrError.takeError());
28276
28377 std::error_code EC;
28478 raw_fd_ostream OS(ExtractOutput, EC, sys::fs::OpenFlags::F_Text);
28579 if (EC)
28680 return make_error(
28781 Twine("Cannot open file '") + ExtractOutput + "' for writing.", EC);
288 Extractor.exportAsYAML(OS);
82 exportAsYAML(*InstrumentationMapOrError, OS);
28983 return Error::success();
29084 });
+0
-58
tools/llvm-xray/xray-extract.h less more
None //===- xray-extract.h - XRay Instrumentation Map Extraction ---------------===//
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 // Defines the interface for extracting the instrumentation map from an
10 // XRay-instrumented binary.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_TOOLS_XRAY_EXTRACT_H
15 #define LLVM_TOOLS_XRAY_EXTRACT_H
16
17 #include
18 #include
19 #include
20 #include
21
22 #include "xray-sleds.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 namespace llvm {
27 namespace xray {
28
29 class InstrumentationMapExtractor {
30 public:
31 typedef std::unordered_map FunctionAddressMap;
32 typedef std::unordered_map FunctionAddressReverseMap;
33
34 enum class InputFormats { ELF, YAML };
35
36 private:
37 std::deque Sleds;
38 FunctionAddressMap FunctionAddresses;
39 FunctionAddressReverseMap FunctionIds;
40
41 public:
42 /// Loads the instrumentation map from |Filename|. Updates |EC| in case there
43 /// were errors encountered opening the file. |Format| defines what the input
44 /// instrumentation map is in.
45 InstrumentationMapExtractor(std::string Filename, InputFormats Format,
46 Error &EC);
47
48 const FunctionAddressMap &getFunctionAddresses() { return FunctionAddresses; }
49
50 /// Exports the loaded function address map as YAML through |OS|.
51 void exportAsYAML(raw_ostream &OS);
52 };
53
54 } // namespace xray
55 } // namespace llvm
56
57 #endif // LLVM_TOOLS_XRAY_EXTRACT_H
1616 #include
1717 #include
1818
19 #include "xray-extract.h"
2019 #include "xray-graph.h"
2120 #include "xray-registry.h"
2221 #include "llvm/ADT/ArrayRef.h"
2322 #include "llvm/Support/ErrorHandling.h"
2423 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/XRay/InstrumentationMap.h"
2525 #include "llvm/XRay/Trace.h"
2626 #include "llvm/XRay/YAMLXRayRecord.h"
2727
2828 using namespace llvm;
29 using namespace xray;
29 using namespace llvm::xray;
3030
3131 // Setup llvm-xray graph subcommand and its options.
3232 static cl::SubCommand Graph("graph", "Generate function-call graph");
4747 static cl::alias GraphOutput2("o", cl::aliasopt(GraphOutput),
4848 cl::desc("Alias for -output"), cl::sub(Graph));
4949
50 static cl::opt
51 GraphInstrMap("instr_map",
52 cl::desc("binary with the instrumrntation map, or "
53 "a separate instrumentation map"),
54 cl::value_desc("binary with xray_instr_map"), cl::sub(Graph),
55 cl::init(""));
50 static cl::opt GraphInstrMap(
51 "instr_map", cl::desc("binary with the instrumrntation map, or "
52 "a separate instrumentation map"),
53 cl::value_desc("binary with xray_instr_map"), cl::sub(Graph), cl::init(""));
5654 static cl::alias GraphInstrMap2("m", cl::aliasopt(GraphInstrMap),
5755 cl::desc("alias for -instr_map"),
5856 cl::sub(Graph));
59
60 static cl::opt InstrMapFormat(
61 "instr-map-format", cl::desc("format of instrumentation map"),
62 cl::values(clEnumValN(InstrumentationMapExtractor::InputFormats::ELF, "elf",
63 "instrumentation map in an ELF header"),
64 clEnumValN(InstrumentationMapExtractor::InputFormats::YAML,
65 "yaml", "instrumentation map in YAML")),
66 cl::sub(Graph), cl::init(InstrumentationMapExtractor::InputFormats::ELF));
67 static cl::alias InstrMapFormat2("t", cl::aliasopt(InstrMapFormat),
68 cl::desc("Alias for -instr-map-format"),
69 cl::sub(Graph));
7057
7158 static cl::opt GraphDeduceSiblingCalls(
7259 "deduce-sibling-calls",
534521 // FIXME: include additional filtering and annalysis passes to provide more
535522 // specific useful information.
536523 static CommandRegistration Unused(&Graph, []() -> Error {
537 int Fd;
538 auto EC = sys::fs::openFileForRead(GraphInput, Fd);
539 if (EC)
540 return make_error(
541 Twine("Cannot open file '") + GraphInput + "'", EC);
542
543 Error Err = Error::success();
544 xray::InstrumentationMapExtractor Extractor(GraphInstrMap, InstrMapFormat,
545 Err);
546 handleAllErrors(std::move(Err),
547 [&](const ErrorInfoBase &E) { E.log(errs()); });
548
549 const auto &FunctionAddresses = Extractor.getFunctionAddresses();
550
524 InstrumentationMap Map;
525 if (!GraphInstrMap.empty()) {
526 auto InstrumentationMapOrError = loadInstrumentationMap(GraphInstrMap);
527 if (!InstrumentationMapOrError)
528 return joinErrors(
529 make_error(
530 Twine("Cannot open instrumentation map '") + GraphInstrMap + "'",
531 std::make_error_code(std::errc::invalid_argument)),
532 InstrumentationMapOrError.takeError());
533 Map = std::move(*InstrumentationMapOrError);
534 }
535
536 const auto &FunctionAddresses = Map.getFunctionAddresses();
551537 symbolize::LLVMSymbolizer::Options Opts(
552538 symbolize::FunctionNameKind::LinkageName, true, true, false, "");
553
554539 symbolize::LLVMSymbolizer Symbolizer(Opts);
555
556540 llvm::xray::FuncIdConversionHelper FuncIdHelper(GraphInstrMap, Symbolizer,
557541 FunctionAddresses);
558
559542 xray::GraphRenderer GR(FuncIdHelper, GraphDeduceSiblingCalls);
560
543 std::error_code EC;
561544 raw_fd_ostream OS(GraphOutput, EC, sys::fs::OpenFlags::F_Text);
562
563545 if (EC)
564546 return make_error(
565547 Twine("Cannot open file '") + GraphOutput + "' for writing.", EC);
566548
567549 auto TraceOrErr = loadTraceFile(GraphInput, true);
568
569 if (!TraceOrErr) {
550 if (!TraceOrErr)
570551 return joinErrors(
571552 make_error(Twine("Failed loading input file '") +
572553 GraphInput + "'",
573554 make_error_code(llvm::errc::invalid_argument)),
574 std::move(Err));
575 }
555 TraceOrErr.takeError());
576556
577557 auto &Trace = *TraceOrErr;
578558 const auto &Header = Trace.getFileHeader();
559
560 // Here we generate the call graph from entries we find in the trace.
579561 for (const auto &Record : Trace) {
580 // Generate graph.
581562 auto E = GR.accountRecord(Record);
582563 if (!E)
583564 continue;
591572 }
592573
593574 if (!GraphKeepGoing)
594 return joinErrors(std::move(E), std::move(Err));
575 return joinErrors(make_error(
576 "Error encountered generating the call graph.",
577 std::make_error_code(std::errc::bad_message)),
578 std::move(E));
579
595580 handleAllErrors(std::move(E),
596581 [&](const ErrorInfoBase &E) { E.log(errs()); });
597582 }
598583
599584 GR.exportGraphAsDOT(OS, Header, GraphEdgeLabel, GraphEdgeColorType,
600585 GraphVertexLabel, GraphVertexColorType);
601 return Err;
586 return Error::success();
602587 });
+0
-32
tools/llvm-xray/xray-sleds.h less more
None //===- xray-sleds.h - XRay Sleds Data Structure ---------------------------===//
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 // Defines the structure used to represent XRay instrumentation map entries.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_SLEDS_H
14 #define LLVM_TOOLS_LLVM_XRAY_XRAY_SLEDS_H
15
16 namespace llvm {
17 namespace xray {
18
19 struct SledEntry {
20 enum class FunctionKinds { ENTRY, EXIT, TAIL };
21
22 uint64_t Address;
23 uint64_t Function;
24 FunctionKinds Kind;
25 bool AlwaysInstrument;
26 };
27
28 } // namespace xray
29 } // namespace llvm
30
31 #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_SLEDS_H