Dean Michael Berris | f4f861b | 2018-05-02 00:43:17 +0000 | [diff] [blame] | 1 | //===- xray-extract.cpp: XRay Instrumentation Map Extraction --------------===// |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 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 | // Implementation of the xray-extract.h interface. |
| 11 | // |
| 12 | // FIXME: Support other XRay-instrumented binary formats other than ELF. |
| 13 | // |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 16 | |
Dean Michael Berris | 44292db | 2017-04-18 23:23:54 +0000 | [diff] [blame] | 17 | #include "func-id-helper.h" |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 18 | #include "xray-registry.h" |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 19 | #include "llvm/Object/ObjectFile.h" |
| 20 | #include "llvm/Support/CommandLine.h" |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 21 | #include "llvm/Support/Error.h" |
| 22 | #include "llvm/Support/FileSystem.h" |
| 23 | #include "llvm/Support/Format.h" |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 24 | #include "llvm/Support/raw_ostream.h" |
Dean Michael Berris | 93789c8 | 2017-02-01 00:05:29 +0000 | [diff] [blame] | 25 | #include "llvm/XRay/InstrumentationMap.h" |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 26 | |
| 27 | using namespace llvm; |
| 28 | using namespace llvm::xray; |
| 29 | using namespace llvm::yaml; |
| 30 | |
| 31 | // llvm-xray extract |
| 32 | // ---------------------------------------------------------------------------- |
| 33 | static cl::SubCommand Extract("extract", "Extract instrumentation maps"); |
| 34 | static cl::opt<std::string> ExtractInput(cl::Positional, |
| 35 | cl::desc("<input file>"), cl::Required, |
| 36 | cl::sub(Extract)); |
| 37 | static cl::opt<std::string> |
| 38 | ExtractOutput("output", cl::value_desc("output file"), cl::init("-"), |
| 39 | cl::desc("output file; use '-' for stdout"), |
| 40 | cl::sub(Extract)); |
| 41 | static cl::alias ExtractOutput2("o", cl::aliasopt(ExtractOutput), |
| 42 | cl::desc("Alias for -output"), |
| 43 | cl::sub(Extract)); |
Dean Michael Berris | 44292db | 2017-04-18 23:23:54 +0000 | [diff] [blame] | 44 | static cl::opt<bool> ExtractSymbolize("symbolize", cl::value_desc("symbolize"), |
| 45 | cl::init(false), |
| 46 | cl::desc("symbolize functions"), |
| 47 | cl::sub(Extract)); |
| 48 | static cl::alias ExtractSymbolize2("s", cl::aliasopt(ExtractSymbolize), |
| 49 | cl::desc("alias for -symbolize"), |
| 50 | cl::sub(Extract)); |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 51 | |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 52 | namespace { |
| 53 | |
Dean Michael Berris | 44292db | 2017-04-18 23:23:54 +0000 | [diff] [blame] | 54 | void exportAsYAML(const InstrumentationMap &Map, raw_ostream &OS, |
| 55 | FuncIdConversionHelper &FH) { |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 56 | // First we translate the sleds into the YAMLXRaySledEntry objects in a deque. |
| 57 | std::vector<YAMLXRaySledEntry> YAMLSleds; |
Dean Michael Berris | 93789c8 | 2017-02-01 00:05:29 +0000 | [diff] [blame] | 58 | auto Sleds = Map.sleds(); |
| 59 | YAMLSleds.reserve(std::distance(Sleds.begin(), Sleds.end())); |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 60 | for (const auto &Sled : Sleds) { |
Dean Michael Berris | 93789c8 | 2017-02-01 00:05:29 +0000 | [diff] [blame] | 61 | auto FuncId = Map.getFunctionId(Sled.Function); |
| 62 | if (!FuncId) |
| 63 | return; |
| 64 | YAMLSleds.push_back({*FuncId, Sled.Address, Sled.Function, Sled.Kind, |
Dean Michael Berris | 44292db | 2017-04-18 23:23:54 +0000 | [diff] [blame] | 65 | Sled.AlwaysInstrument, |
| 66 | ExtractSymbolize ? FH.SymbolOrNumber(*FuncId) : ""}); |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 67 | } |
Dimitry Andric | 193dc0b | 2017-02-14 22:49:49 +0000 | [diff] [blame] | 68 | Output Out(OS, nullptr, 0); |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 69 | Out << YAMLSleds; |
| 70 | } |
| 71 | |
Dean Michael Berris | 93789c8 | 2017-02-01 00:05:29 +0000 | [diff] [blame] | 72 | } // namespace |
| 73 | |
Mehdi Amini | df0b8bc | 2016-11-11 04:28:40 +0000 | [diff] [blame] | 74 | static CommandRegistration Unused(&Extract, []() -> Error { |
Dean Michael Berris | 93789c8 | 2017-02-01 00:05:29 +0000 | [diff] [blame] | 75 | auto InstrumentationMapOrError = loadInstrumentationMap(ExtractInput); |
| 76 | if (!InstrumentationMapOrError) |
| 77 | return joinErrors(make_error<StringError>( |
| 78 | Twine("Cannot extract instrumentation map from '") + |
| 79 | ExtractInput + "'.", |
| 80 | std::make_error_code(std::errc::invalid_argument)), |
| 81 | InstrumentationMapOrError.takeError()); |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 82 | |
| 83 | std::error_code EC; |
| 84 | raw_fd_ostream OS(ExtractOutput, EC, sys::fs::OpenFlags::F_Text); |
| 85 | if (EC) |
| 86 | return make_error<StringError>( |
| 87 | Twine("Cannot open file '") + ExtractOutput + "' for writing.", EC); |
Dean Michael Berris | 44292db | 2017-04-18 23:23:54 +0000 | [diff] [blame] | 88 | const auto &FunctionAddresses = |
| 89 | InstrumentationMapOrError->getFunctionAddresses(); |
| 90 | symbolize::LLVMSymbolizer::Options Opts( |
| 91 | symbolize::FunctionNameKind::LinkageName, true, true, false, ""); |
| 92 | symbolize::LLVMSymbolizer Symbolizer(Opts); |
| 93 | llvm::xray::FuncIdConversionHelper FuncIdHelper(ExtractInput, Symbolizer, |
| 94 | FunctionAddresses); |
| 95 | exportAsYAML(*InstrumentationMapOrError, OS, FuncIdHelper); |
Dean Michael Berris | 5a35548 | 2016-10-26 04:14:34 +0000 | [diff] [blame] | 96 | return Error::success(); |
| 97 | }); |