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