xref: /aosp_15_r20/external/stg/dwarf_wrappers.h (revision 9e3b08ae94a55201065475453d799e8b1378bea6)
1*9e3b08aeSAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2*9e3b08aeSAndroid Build Coastguard Worker // -*- mode: C++ -*-
3*9e3b08aeSAndroid Build Coastguard Worker //
4*9e3b08aeSAndroid Build Coastguard Worker // Copyright 2022 Google LLC
5*9e3b08aeSAndroid Build Coastguard Worker //
6*9e3b08aeSAndroid Build Coastguard Worker // Licensed under the Apache License v2.0 with LLVM Exceptions (the
7*9e3b08aeSAndroid Build Coastguard Worker // "License"); you may not use this file except in compliance with the
8*9e3b08aeSAndroid Build Coastguard Worker // License.  You may obtain a copy of the License at
9*9e3b08aeSAndroid Build Coastguard Worker //
10*9e3b08aeSAndroid Build Coastguard Worker //     https://llvm.org/LICENSE.txt
11*9e3b08aeSAndroid Build Coastguard Worker //
12*9e3b08aeSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
13*9e3b08aeSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
14*9e3b08aeSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*9e3b08aeSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
16*9e3b08aeSAndroid Build Coastguard Worker // limitations under the License.
17*9e3b08aeSAndroid Build Coastguard Worker //
18*9e3b08aeSAndroid Build Coastguard Worker // Author: Aleksei Vetrov
19*9e3b08aeSAndroid Build Coastguard Worker 
20*9e3b08aeSAndroid Build Coastguard Worker #ifndef STG_DWARF_WRAPPERS_H_
21*9e3b08aeSAndroid Build Coastguard Worker #define STG_DWARF_WRAPPERS_H_
22*9e3b08aeSAndroid Build Coastguard Worker 
23*9e3b08aeSAndroid Build Coastguard Worker #include <elfutils/libdw.h>
24*9e3b08aeSAndroid Build Coastguard Worker 
25*9e3b08aeSAndroid Build Coastguard Worker #include <cstddef>
26*9e3b08aeSAndroid Build Coastguard Worker #include <cstdint>
27*9e3b08aeSAndroid Build Coastguard Worker #include <optional>
28*9e3b08aeSAndroid Build Coastguard Worker #include <ostream>
29*9e3b08aeSAndroid Build Coastguard Worker #include <string>
30*9e3b08aeSAndroid Build Coastguard Worker #include <vector>
31*9e3b08aeSAndroid Build Coastguard Worker 
32*9e3b08aeSAndroid Build Coastguard Worker namespace stg {
33*9e3b08aeSAndroid Build Coastguard Worker namespace dwarf {
34*9e3b08aeSAndroid Build Coastguard Worker 
35*9e3b08aeSAndroid Build Coastguard Worker struct Address {
36*9e3b08aeSAndroid Build Coastguard Worker   // ADDRESS - relocated, section-relative offset
37*9e3b08aeSAndroid Build Coastguard Worker   // TLS - broken (elfutils bug), TLS-relative offset
38*9e3b08aeSAndroid Build Coastguard Worker   //       TODO: match TLS variables by address
39*9e3b08aeSAndroid Build Coastguard Worker   enum class Kind { ADDRESS, TLS };
40*9e3b08aeSAndroid Build Coastguard Worker 
AddressAddress41*9e3b08aeSAndroid Build Coastguard Worker   Address(Kind kind, uint64_t value) : kind(kind), value(value) {}
42*9e3b08aeSAndroid Build Coastguard Worker   auto operator<=>(const Address&) const = default;
43*9e3b08aeSAndroid Build Coastguard Worker 
44*9e3b08aeSAndroid Build Coastguard Worker   Kind kind;
45*9e3b08aeSAndroid Build Coastguard Worker   uint64_t value;
46*9e3b08aeSAndroid Build Coastguard Worker };
47*9e3b08aeSAndroid Build Coastguard Worker 
48*9e3b08aeSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const Address& address);
49*9e3b08aeSAndroid Build Coastguard Worker 
50*9e3b08aeSAndroid Build Coastguard Worker // C++ wrapper over Dwarf_Die, providing interface for its various properties.
51*9e3b08aeSAndroid Build Coastguard Worker struct Entry {
52*9e3b08aeSAndroid Build Coastguard Worker   // All methods in libdw take Dwarf_Die by non-const pointer as libdw caches
53*9e3b08aeSAndroid Build Coastguard Worker   // in it a link to the associated abbreviation table. Updating this link is
54*9e3b08aeSAndroid Build Coastguard Worker   // not thread-safe and so we cannot, for example, hold a std::shared_ptr to a
55*9e3b08aeSAndroid Build Coastguard Worker   // heap-allocated Dwarf_Die.
56*9e3b08aeSAndroid Build Coastguard Worker   //
57*9e3b08aeSAndroid Build Coastguard Worker   // The only options left are holding a std::unique_ptr or storing a value.
58*9e3b08aeSAndroid Build Coastguard Worker   // Unique pointers will add one more level of indirection to a hot path.
59*9e3b08aeSAndroid Build Coastguard Worker   // So we choose to store Dwarf_Die values.
60*9e3b08aeSAndroid Build Coastguard Worker   //
61*9e3b08aeSAndroid Build Coastguard Worker   // Each Entry only contains references to DWARF file memory and is fairly
62*9e3b08aeSAndroid Build Coastguard Worker   // small (32 bytes), so copies can be easily made if necessary. However,
63*9e3b08aeSAndroid Build Coastguard Worker   // within one thread it is preferable to pass it by reference.
64*9e3b08aeSAndroid Build Coastguard Worker   Dwarf_Die die{};
65*9e3b08aeSAndroid Build Coastguard Worker 
66*9e3b08aeSAndroid Build Coastguard Worker   // Get list of direct descendants of an entry in the DWARF tree.
67*9e3b08aeSAndroid Build Coastguard Worker   std::vector<Entry> GetChildren();
68*9e3b08aeSAndroid Build Coastguard Worker 
69*9e3b08aeSAndroid Build Coastguard Worker   // All getters are non-const as libdw may need to modify Dwarf_Die.
70*9e3b08aeSAndroid Build Coastguard Worker   int GetTag();
71*9e3b08aeSAndroid Build Coastguard Worker   Dwarf_Off GetOffset();
72*9e3b08aeSAndroid Build Coastguard Worker   std::optional<std::string> MaybeGetString(uint32_t attribute);
73*9e3b08aeSAndroid Build Coastguard Worker   std::optional<std::string> MaybeGetDirectString(uint32_t attribute);
74*9e3b08aeSAndroid Build Coastguard Worker   std::optional<uint64_t> MaybeGetUnsignedConstant(uint32_t attribute);
75*9e3b08aeSAndroid Build Coastguard Worker   uint64_t MustGetUnsignedConstant(uint32_t attribute);
76*9e3b08aeSAndroid Build Coastguard Worker   bool GetFlag(uint32_t attribute);
77*9e3b08aeSAndroid Build Coastguard Worker   std::optional<Entry> MaybeGetReference(uint32_t attribute);
78*9e3b08aeSAndroid Build Coastguard Worker   std::optional<Address> MaybeGetAddress(uint32_t attribute);
79*9e3b08aeSAndroid Build Coastguard Worker   std::optional<uint64_t> MaybeGetMemberByteOffset();
80*9e3b08aeSAndroid Build Coastguard Worker   std::optional<uint64_t> MaybeGetVtableOffset();
81*9e3b08aeSAndroid Build Coastguard Worker   // Returns value of subrange element count if it is constant or nullopt if it
82*9e3b08aeSAndroid Build Coastguard Worker   // is not defined or cannot be represented as constant.
83*9e3b08aeSAndroid Build Coastguard Worker   std::optional<uint64_t> MaybeGetCount();
84*9e3b08aeSAndroid Build Coastguard Worker };
85*9e3b08aeSAndroid Build Coastguard Worker 
86*9e3b08aeSAndroid Build Coastguard Worker // Metadata and top-level entry of a compilation unit.
87*9e3b08aeSAndroid Build Coastguard Worker struct CompilationUnit {
88*9e3b08aeSAndroid Build Coastguard Worker   int version;
89*9e3b08aeSAndroid Build Coastguard Worker   Entry entry;
90*9e3b08aeSAndroid Build Coastguard Worker };
91*9e3b08aeSAndroid Build Coastguard Worker 
92*9e3b08aeSAndroid Build Coastguard Worker std::vector<CompilationUnit> GetCompilationUnits(Dwarf& dwarf);
93*9e3b08aeSAndroid Build Coastguard Worker 
94*9e3b08aeSAndroid Build Coastguard Worker class Files {
95*9e3b08aeSAndroid Build Coastguard Worker  public:
96*9e3b08aeSAndroid Build Coastguard Worker   Files() = default;
97*9e3b08aeSAndroid Build Coastguard Worker   explicit Files(Entry& compilation_unit);
98*9e3b08aeSAndroid Build Coastguard Worker   std::optional<std::string> MaybeGetFile(Entry& entry,
99*9e3b08aeSAndroid Build Coastguard Worker                                           uint32_t attribute) const;
100*9e3b08aeSAndroid Build Coastguard Worker 
101*9e3b08aeSAndroid Build Coastguard Worker  private:
102*9e3b08aeSAndroid Build Coastguard Worker   Dwarf_Files* files_ = nullptr;
103*9e3b08aeSAndroid Build Coastguard Worker   size_t files_count_ = 0;
104*9e3b08aeSAndroid Build Coastguard Worker };
105*9e3b08aeSAndroid Build Coastguard Worker 
106*9e3b08aeSAndroid Build Coastguard Worker }  // namespace dwarf
107*9e3b08aeSAndroid Build Coastguard Worker }  // namespace stg
108*9e3b08aeSAndroid Build Coastguard Worker 
109*9e3b08aeSAndroid Build Coastguard Worker #endif  // STG_DWARF_WRAPPERS_H_
110