1 | //===- xray-extract.cpp: XRay Instrumentation Map Extraction --------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Implementation of the xray-extract.h interface. |
10 | // |
11 | // FIXME: Support other XRay-instrumented binary formats other than ELF. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | |
16 | #include "func-id-helper.h" |
17 | #include "xray-registry.h" |
18 | #include "llvm/Object/ObjectFile.h" |
19 | #include "llvm/Support/CommandLine.h" |
20 | #include "llvm/Support/Error.h" |
21 | #include "llvm/Support/FileSystem.h" |
22 | #include "llvm/Support/Format.h" |
23 | #include "llvm/Support/raw_ostream.h" |
24 | #include "llvm/XRay/InstrumentationMap.h" |
25 | |
26 | using namespace llvm; |
27 | using namespace llvm::xray; |
28 | using namespace llvm::yaml; |
29 | |
30 | // llvm-xray extract |
31 | // ---------------------------------------------------------------------------- |
32 | static cl::SubCommand ("extract" , "Extract instrumentation maps" ); |
33 | static cl::opt<std::string> (cl::Positional, |
34 | cl::desc("<input file>" ), cl::Required, |
35 | cl::sub(Extract)); |
36 | static cl::opt<std::string> |
37 | ("output" , cl::value_desc("output file" ), cl::init(Val: "-" ), |
38 | cl::desc("output file; use '-' for stdout" ), |
39 | cl::sub(Extract)); |
40 | static cl::alias ("o" , cl::aliasopt(ExtractOutput), |
41 | cl::desc("Alias for -output" )); |
42 | static cl::opt<bool> ("symbolize" , cl::value_desc("symbolize" ), |
43 | cl::init(Val: false), |
44 | cl::desc("symbolize functions" ), |
45 | cl::sub(Extract)); |
46 | static cl::alias ("s" , cl::aliasopt(ExtractSymbolize), |
47 | cl::desc("alias for -symbolize" )); |
48 | static cl::opt<bool> Demangle("demangle" , |
49 | cl::desc("demangle symbols (default)" ), |
50 | cl::sub(Extract)); |
51 | static cl::opt<bool> NoDemangle("no-demangle" , |
52 | cl::desc("don't demangle symbols" ), |
53 | cl::sub(Extract)); |
54 | |
55 | namespace { |
56 | |
57 | void exportAsYAML(const InstrumentationMap &Map, raw_ostream &OS, |
58 | FuncIdConversionHelper &FH) { |
59 | // First we translate the sleds into the YAMLXRaySledEntry objects in a deque. |
60 | std::vector<YAMLXRaySledEntry> YAMLSleds; |
61 | auto Sleds = Map.sleds(); |
62 | YAMLSleds.reserve(n: std::distance(first: Sleds.begin(), last: Sleds.end())); |
63 | for (const auto &Sled : Sleds) { |
64 | auto FuncId = Map.getFunctionId(Addr: Sled.Function); |
65 | if (!FuncId) |
66 | return; |
67 | YAMLSleds.push_back( |
68 | x: {.FuncId: *FuncId, .Address: Sled.Address, .Function: Sled.Function, .Kind: Sled.Kind, .AlwaysInstrument: Sled.AlwaysInstrument, |
69 | .FunctionName: ExtractSymbolize ? FH.SymbolOrNumber(FuncId: *FuncId) : "" , .Version: Sled.Version}); |
70 | } |
71 | Output Out(OS, nullptr, 0); |
72 | Out << YAMLSleds; |
73 | } |
74 | |
75 | } // namespace |
76 | |
77 | static CommandRegistration Unused(&Extract, []() -> Error { |
78 | auto InstrumentationMapOrError = loadInstrumentationMap(Filename: ExtractInput); |
79 | if (!InstrumentationMapOrError) |
80 | return joinErrors(E1: make_error<StringError>( |
81 | Args: Twine("Cannot extract instrumentation map from '" ) + |
82 | ExtractInput + "'." , |
83 | Args: std::make_error_code(e: std::errc::invalid_argument)), |
84 | E2: InstrumentationMapOrError.takeError()); |
85 | |
86 | std::error_code EC; |
87 | raw_fd_ostream OS(ExtractOutput, EC, sys::fs::OpenFlags::OF_TextWithCRLF); |
88 | if (EC) |
89 | return make_error<StringError>( |
90 | Args: Twine("Cannot open file '" ) + ExtractOutput + "' for writing." , Args&: EC); |
91 | const auto &FunctionAddresses = |
92 | InstrumentationMapOrError->getFunctionAddresses(); |
93 | symbolize::LLVMSymbolizer::Options opts; |
94 | if (Demangle.getPosition() < NoDemangle.getPosition()) |
95 | opts.Demangle = false; |
96 | symbolize::LLVMSymbolizer Symbolizer(opts); |
97 | llvm::xray::FuncIdConversionHelper FuncIdHelper(ExtractInput, Symbolizer, |
98 | FunctionAddresses); |
99 | exportAsYAML(Map: *InstrumentationMapOrError, OS, FH&: FuncIdHelper); |
100 | return Error::success(); |
101 | }); |
102 | |