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