1 //===- InstrumentationMap.h - XRay Instrumentation Map ----------*- C++ -*-===//
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 // Defines the interface for extracting the instrumentation map from an
10 // XRay-instrumented binary.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_XRAY_INSTRUMENTATIONMAP_H
15 #define LLVM_XRAY_INSTRUMENTATIONMAP_H
16 
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/YAMLTraits.h"
20 #include <cstdint>
21 #include <optional>
22 #include <unordered_map>
23 #include <vector>
24 
25 namespace llvm {
26 
27 namespace xray {
28 
29 // Forward declare to make a friend.
30 class InstrumentationMap;
31 
32 /// Loads the instrumentation map from |Filename|. This auto-deduces the type of
33 /// the instrumentation map.
34 Expected<InstrumentationMap> loadInstrumentationMap(StringRef Filename);
35 
36 /// Represents an XRay instrumentation sled entry from an object file.
37 struct SledEntry {
38   /// Each entry here represents the kinds of supported instrumentation map
39   /// entries.
40   enum class FunctionKinds { ENTRY, EXIT, TAIL, LOG_ARGS_ENTER, CUSTOM_EVENT };
41 
42   /// The address of the sled.
43   uint64_t Address;
44 
45   /// The address of the function.
46   uint64_t Function;
47 
48   /// The kind of sled.
49   FunctionKinds Kind;
50 
51   /// Whether the sled was annotated to always be instrumented.
52   bool AlwaysInstrument;
53 
54   unsigned char Version;
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   std::string FunctionName;
64   unsigned char Version;
65 };
66 
67 /// The InstrumentationMap represents the computed function id's and indicated
68 /// function addresses from an object file (or a YAML file). This provides an
69 /// interface to just the mapping between the function id, and the function
70 /// address.
71 ///
72 /// We also provide raw access to the actual instrumentation map entries we find
73 /// associated with a particular object file.
74 ///
75 class InstrumentationMap {
76 public:
77   using FunctionAddressMap = std::unordered_map<int32_t, uint64_t>;
78   using FunctionAddressReverseMap = std::unordered_map<uint64_t, int32_t>;
79   using SledContainer = std::vector<SledEntry>;
80 
81 private:
82   SledContainer Sleds;
83   FunctionAddressMap FunctionAddresses;
84   FunctionAddressReverseMap FunctionIds;
85 
86   friend Expected<InstrumentationMap> loadInstrumentationMap(StringRef);
87 
88 public:
89   /// Provides a raw accessor to the unordered map of function addresses.
90   const FunctionAddressMap &getFunctionAddresses() { return FunctionAddresses; }
91 
92   /// Returns an XRay computed function id, provided a function address.
93   std::optional<int32_t> getFunctionId(uint64_t Addr) const;
94 
95   /// Returns the function address for a function id.
96   std::optional<uint64_t> getFunctionAddr(int32_t FuncId) const;
97 
98   /// Provide read-only access to the entries of the instrumentation map.
99   const SledContainer &sleds() const { return Sleds; };
100 };
101 
102 } // end namespace xray
103 
104 namespace yaml {
105 
106 template <> struct ScalarEnumerationTraits<xray::SledEntry::FunctionKinds> {
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     IO.enumCase(Kind, "log-args-enter",
112                 xray::SledEntry::FunctionKinds::LOG_ARGS_ENTER);
113     IO.enumCase(Kind, "custom-event",
114                 xray::SledEntry::FunctionKinds::CUSTOM_EVENT);
115   }
116 };
117 
118 template <> struct MappingTraits<xray::YAMLXRaySledEntry> {
119   static void mapping(IO &IO, xray::YAMLXRaySledEntry &Entry) {
120     IO.mapRequired("id", Entry.FuncId);
121     IO.mapRequired("address", Entry.Address);
122     IO.mapRequired("function", Entry.Function);
123     IO.mapRequired("kind", Entry.Kind);
124     IO.mapRequired("always-instrument", Entry.AlwaysInstrument);
125     IO.mapOptional("function-name", Entry.FunctionName);
126     IO.mapOptional("version", Entry.Version, 0);
127   }
128 
129   static constexpr bool flow = true;
130 };
131 
132 } // end namespace yaml
133 
134 } // end namespace llvm
135 
136 LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRaySledEntry)
137 
138 #endif // LLVM_XRAY_INSTRUMENTATIONMAP_H
139