xref: /aosp_15_r20/system/unwinding/libunwindstack/include/unwindstack/ElfInterface.h (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #pragma once
18*eb293b8fSAndroid Build Coastguard Worker 
19*eb293b8fSAndroid Build Coastguard Worker #include <elf.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
21*eb293b8fSAndroid Build Coastguard Worker 
22*eb293b8fSAndroid Build Coastguard Worker #include <memory>
23*eb293b8fSAndroid Build Coastguard Worker #include <string>
24*eb293b8fSAndroid Build Coastguard Worker #include <unordered_map>
25*eb293b8fSAndroid Build Coastguard Worker #include <utility>
26*eb293b8fSAndroid Build Coastguard Worker #include <vector>
27*eb293b8fSAndroid Build Coastguard Worker 
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfSection.h>
29*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Error.h>
30*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/SharedString.h>
31*eb293b8fSAndroid Build Coastguard Worker 
32*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
33*eb293b8fSAndroid Build Coastguard Worker 
34*eb293b8fSAndroid Build Coastguard Worker // Forward declarations.
35*eb293b8fSAndroid Build Coastguard Worker class Memory;
36*eb293b8fSAndroid Build Coastguard Worker class Regs;
37*eb293b8fSAndroid Build Coastguard Worker class Symbols;
38*eb293b8fSAndroid Build Coastguard Worker 
39*eb293b8fSAndroid Build Coastguard Worker struct LoadInfo {
40*eb293b8fSAndroid Build Coastguard Worker   uint64_t offset;
41*eb293b8fSAndroid Build Coastguard Worker   uint64_t table_offset;
42*eb293b8fSAndroid Build Coastguard Worker   size_t table_size;
43*eb293b8fSAndroid Build Coastguard Worker };
44*eb293b8fSAndroid Build Coastguard Worker 
45*eb293b8fSAndroid Build Coastguard Worker struct SectionInfo {
46*eb293b8fSAndroid Build Coastguard Worker   uint64_t offset;
47*eb293b8fSAndroid Build Coastguard Worker   uint64_t size;
48*eb293b8fSAndroid Build Coastguard Worker   uint64_t flags;
49*eb293b8fSAndroid Build Coastguard Worker   int64_t bias;
50*eb293b8fSAndroid Build Coastguard Worker };
51*eb293b8fSAndroid Build Coastguard Worker 
52*eb293b8fSAndroid Build Coastguard Worker enum : uint8_t {
53*eb293b8fSAndroid Build Coastguard Worker   SONAME_UNKNOWN = 0,
54*eb293b8fSAndroid Build Coastguard Worker   SONAME_VALID,
55*eb293b8fSAndroid Build Coastguard Worker   SONAME_INVALID,
56*eb293b8fSAndroid Build Coastguard Worker };
57*eb293b8fSAndroid Build Coastguard Worker 
58*eb293b8fSAndroid Build Coastguard Worker struct ElfTypes32 {
59*eb293b8fSAndroid Build Coastguard Worker   using AddressType = uint32_t;
60*eb293b8fSAndroid Build Coastguard Worker   using Chdr = Elf32_Chdr;
61*eb293b8fSAndroid Build Coastguard Worker   using Dyn = Elf32_Dyn;
62*eb293b8fSAndroid Build Coastguard Worker   using Ehdr = Elf32_Ehdr;
63*eb293b8fSAndroid Build Coastguard Worker   using Nhdr = Elf32_Nhdr;
64*eb293b8fSAndroid Build Coastguard Worker   using Phdr = Elf32_Phdr;
65*eb293b8fSAndroid Build Coastguard Worker   using Shdr = Elf32_Shdr;
66*eb293b8fSAndroid Build Coastguard Worker   using Sym = Elf32_Sym;
67*eb293b8fSAndroid Build Coastguard Worker };
68*eb293b8fSAndroid Build Coastguard Worker 
69*eb293b8fSAndroid Build Coastguard Worker struct ElfTypes64 {
70*eb293b8fSAndroid Build Coastguard Worker   using AddressType = uint64_t;
71*eb293b8fSAndroid Build Coastguard Worker   using Chdr = Elf64_Chdr;
72*eb293b8fSAndroid Build Coastguard Worker   using Dyn = Elf64_Dyn;
73*eb293b8fSAndroid Build Coastguard Worker   using Ehdr = Elf64_Ehdr;
74*eb293b8fSAndroid Build Coastguard Worker   using Nhdr = Elf64_Nhdr;
75*eb293b8fSAndroid Build Coastguard Worker   using Phdr = Elf64_Phdr;
76*eb293b8fSAndroid Build Coastguard Worker   using Shdr = Elf64_Shdr;
77*eb293b8fSAndroid Build Coastguard Worker   using Sym = Elf64_Sym;
78*eb293b8fSAndroid Build Coastguard Worker };
79*eb293b8fSAndroid Build Coastguard Worker 
80*eb293b8fSAndroid Build Coastguard Worker class ElfInterface {
81*eb293b8fSAndroid Build Coastguard Worker  public:
ElfInterface(std::shared_ptr<Memory> & memory)82*eb293b8fSAndroid Build Coastguard Worker   ElfInterface(std::shared_ptr<Memory>& memory) : memory_(memory) {}
83*eb293b8fSAndroid Build Coastguard Worker   virtual ~ElfInterface();
84*eb293b8fSAndroid Build Coastguard Worker 
85*eb293b8fSAndroid Build Coastguard Worker   virtual bool Init(int64_t* load_bias) = 0;
86*eb293b8fSAndroid Build Coastguard Worker 
87*eb293b8fSAndroid Build Coastguard Worker   virtual void InitHeaders() = 0;
88*eb293b8fSAndroid Build Coastguard Worker 
89*eb293b8fSAndroid Build Coastguard Worker   virtual std::string GetSoname() = 0;
90*eb293b8fSAndroid Build Coastguard Worker 
91*eb293b8fSAndroid Build Coastguard Worker   virtual bool GetFunctionName(uint64_t addr, SharedString* name, uint64_t* offset) = 0;
92*eb293b8fSAndroid Build Coastguard Worker 
93*eb293b8fSAndroid Build Coastguard Worker   virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0;
94*eb293b8fSAndroid Build Coastguard Worker 
95*eb293b8fSAndroid Build Coastguard Worker   virtual std::string GetBuildID() = 0;
96*eb293b8fSAndroid Build Coastguard Worker 
97*eb293b8fSAndroid Build Coastguard Worker   virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished,
98*eb293b8fSAndroid Build Coastguard Worker                     bool* is_signal_frame);
99*eb293b8fSAndroid Build Coastguard Worker 
100*eb293b8fSAndroid Build Coastguard Worker   virtual bool IsValidPc(uint64_t pc);
101*eb293b8fSAndroid Build Coastguard Worker 
102*eb293b8fSAndroid Build Coastguard Worker   bool GetTextRange(uint64_t* addr, uint64_t* size);
103*eb293b8fSAndroid Build Coastguard Worker 
104*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<Memory> CreateGnuDebugdataMemory();
105*eb293b8fSAndroid Build Coastguard Worker 
memory()106*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<Memory> memory() { return memory_; }
107*eb293b8fSAndroid Build Coastguard Worker 
pt_loads()108*eb293b8fSAndroid Build Coastguard Worker   const std::unordered_map<uint64_t, LoadInfo>& pt_loads() { return pt_loads_; }
109*eb293b8fSAndroid Build Coastguard Worker 
SetGnuDebugdataInterface(ElfInterface * interface)110*eb293b8fSAndroid Build Coastguard Worker   void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; }
111*eb293b8fSAndroid Build Coastguard Worker 
dynamic_offset()112*eb293b8fSAndroid Build Coastguard Worker   uint64_t dynamic_offset() { return dynamic_offset_; }
dynamic_vaddr_start()113*eb293b8fSAndroid Build Coastguard Worker   uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; }
dynamic_vaddr_end()114*eb293b8fSAndroid Build Coastguard Worker   uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; }
115*eb293b8fSAndroid Build Coastguard Worker 
data_offset()116*eb293b8fSAndroid Build Coastguard Worker   uint64_t data_offset() { return data_offset_; }
data_vaddr_start()117*eb293b8fSAndroid Build Coastguard Worker   uint64_t data_vaddr_start() { return data_vaddr_start_; }
data_vaddr_end()118*eb293b8fSAndroid Build Coastguard Worker   uint64_t data_vaddr_end() { return data_vaddr_end_; }
119*eb293b8fSAndroid Build Coastguard Worker 
eh_frame_hdr_info()120*eb293b8fSAndroid Build Coastguard Worker   const SectionInfo& eh_frame_hdr_info() { return eh_frame_hdr_info_; }
eh_frame_info()121*eb293b8fSAndroid Build Coastguard Worker   const SectionInfo& eh_frame_info() { return eh_frame_info_; }
debug_frame_info()122*eb293b8fSAndroid Build Coastguard Worker   const SectionInfo& debug_frame_info() { return debug_frame_info_; }
123*eb293b8fSAndroid Build Coastguard Worker 
gnu_debugdata_offset()124*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_debugdata_offset() { return gnu_debugdata_offset_; }
gnu_debugdata_size()125*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_debugdata_size() { return gnu_debugdata_size_; }
126*eb293b8fSAndroid Build Coastguard Worker 
gnu_build_id_offset()127*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; }
gnu_build_id_size()128*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_build_id_size() { return gnu_build_id_size_; }
129*eb293b8fSAndroid Build Coastguard Worker 
eh_frame()130*eb293b8fSAndroid Build Coastguard Worker   DwarfSection* eh_frame() { return eh_frame_.get(); }
debug_frame()131*eb293b8fSAndroid Build Coastguard Worker   DwarfSection* debug_frame() { return debug_frame_.get(); }
132*eb293b8fSAndroid Build Coastguard Worker 
last_error()133*eb293b8fSAndroid Build Coastguard Worker   const ErrorData& last_error() { return last_error_; }
LastErrorCode()134*eb293b8fSAndroid Build Coastguard Worker   ErrorCode LastErrorCode() { return last_error_.code; }
LastErrorAddress()135*eb293b8fSAndroid Build Coastguard Worker   uint64_t LastErrorAddress() { return last_error_.address; }
136*eb293b8fSAndroid Build Coastguard Worker 
137*eb293b8fSAndroid Build Coastguard Worker   template <typename EhdrType, typename PhdrType>
138*eb293b8fSAndroid Build Coastguard Worker   static int64_t GetLoadBias(Memory* memory);
139*eb293b8fSAndroid Build Coastguard Worker 
140*eb293b8fSAndroid Build Coastguard Worker   template <typename EhdrType, typename ShdrType, typename NhdrType>
141*eb293b8fSAndroid Build Coastguard Worker   static std::string ReadBuildIDFromMemory(Memory* memory);
142*eb293b8fSAndroid Build Coastguard Worker 
143*eb293b8fSAndroid Build Coastguard Worker  protected:
HandleUnknownType(uint32_t,uint64_t,uint64_t)144*eb293b8fSAndroid Build Coastguard Worker   virtual void HandleUnknownType(uint32_t, uint64_t, uint64_t) {}
145*eb293b8fSAndroid Build Coastguard Worker 
146*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<Memory> memory_;
147*eb293b8fSAndroid Build Coastguard Worker   std::unordered_map<uint64_t, LoadInfo> pt_loads_;
148*eb293b8fSAndroid Build Coastguard Worker 
149*eb293b8fSAndroid Build Coastguard Worker   // Stored elf data.
150*eb293b8fSAndroid Build Coastguard Worker   uint64_t dynamic_offset_ = 0;
151*eb293b8fSAndroid Build Coastguard Worker   uint64_t dynamic_vaddr_start_ = 0;
152*eb293b8fSAndroid Build Coastguard Worker   uint64_t dynamic_vaddr_end_ = 0;
153*eb293b8fSAndroid Build Coastguard Worker 
154*eb293b8fSAndroid Build Coastguard Worker   uint64_t data_offset_ = 0;
155*eb293b8fSAndroid Build Coastguard Worker   uint64_t data_vaddr_start_ = 0;
156*eb293b8fSAndroid Build Coastguard Worker   uint64_t data_vaddr_end_ = 0;
157*eb293b8fSAndroid Build Coastguard Worker 
158*eb293b8fSAndroid Build Coastguard Worker   SectionInfo eh_frame_hdr_info_ = {};
159*eb293b8fSAndroid Build Coastguard Worker   SectionInfo eh_frame_info_ = {};
160*eb293b8fSAndroid Build Coastguard Worker   SectionInfo debug_frame_info_ = {};
161*eb293b8fSAndroid Build Coastguard Worker 
162*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_debugdata_offset_ = 0;
163*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_debugdata_size_ = 0;
164*eb293b8fSAndroid Build Coastguard Worker 
165*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_build_id_offset_ = 0;
166*eb293b8fSAndroid Build Coastguard Worker   uint64_t gnu_build_id_size_ = 0;
167*eb293b8fSAndroid Build Coastguard Worker 
168*eb293b8fSAndroid Build Coastguard Worker   uint64_t text_addr_ = 0;
169*eb293b8fSAndroid Build Coastguard Worker   uint64_t text_size_ = 0;
170*eb293b8fSAndroid Build Coastguard Worker 
171*eb293b8fSAndroid Build Coastguard Worker   uint8_t soname_type_ = SONAME_UNKNOWN;
172*eb293b8fSAndroid Build Coastguard Worker   std::string soname_;
173*eb293b8fSAndroid Build Coastguard Worker 
174*eb293b8fSAndroid Build Coastguard Worker   ErrorData last_error_{ERROR_NONE, 0};
175*eb293b8fSAndroid Build Coastguard Worker 
176*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<DwarfSection> eh_frame_;
177*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<DwarfSection> debug_frame_;
178*eb293b8fSAndroid Build Coastguard Worker   // The Elf object owns the gnu_debugdata interface object.
179*eb293b8fSAndroid Build Coastguard Worker   ElfInterface* gnu_debugdata_interface_ = nullptr;
180*eb293b8fSAndroid Build Coastguard Worker 
181*eb293b8fSAndroid Build Coastguard Worker   std::vector<Symbols*> symbols_;
182*eb293b8fSAndroid Build Coastguard Worker   std::vector<std::pair<uint64_t, uint64_t>> strtabs_;
183*eb293b8fSAndroid Build Coastguard Worker };
184*eb293b8fSAndroid Build Coastguard Worker 
185*eb293b8fSAndroid Build Coastguard Worker template <typename ElfTypes>
186*eb293b8fSAndroid Build Coastguard Worker class ElfInterfaceImpl : public ElfInterface {
187*eb293b8fSAndroid Build Coastguard Worker  public:
188*eb293b8fSAndroid Build Coastguard Worker   using AddressType = typename ElfTypes::AddressType;
189*eb293b8fSAndroid Build Coastguard Worker   using ChdrType = typename ElfTypes::Chdr;
190*eb293b8fSAndroid Build Coastguard Worker   using DynType = typename ElfTypes::Dyn;
191*eb293b8fSAndroid Build Coastguard Worker   using EhdrType = typename ElfTypes::Ehdr;
192*eb293b8fSAndroid Build Coastguard Worker   using NhdrType = typename ElfTypes::Nhdr;
193*eb293b8fSAndroid Build Coastguard Worker   using PhdrType = typename ElfTypes::Phdr;
194*eb293b8fSAndroid Build Coastguard Worker   using ShdrType = typename ElfTypes::Shdr;
195*eb293b8fSAndroid Build Coastguard Worker   using SymType = typename ElfTypes::Sym;
196*eb293b8fSAndroid Build Coastguard Worker 
ElfInterfaceImpl(std::shared_ptr<Memory> & memory)197*eb293b8fSAndroid Build Coastguard Worker   ElfInterfaceImpl(std::shared_ptr<Memory>& memory) : ElfInterface(memory) {}
198*eb293b8fSAndroid Build Coastguard Worker   virtual ~ElfInterfaceImpl() = default;
199*eb293b8fSAndroid Build Coastguard Worker 
Init(int64_t * load_bias)200*eb293b8fSAndroid Build Coastguard Worker   bool Init(int64_t* load_bias) override { return ReadAllHeaders(load_bias); }
201*eb293b8fSAndroid Build Coastguard Worker 
202*eb293b8fSAndroid Build Coastguard Worker   void InitHeaders() override;
203*eb293b8fSAndroid Build Coastguard Worker 
204*eb293b8fSAndroid Build Coastguard Worker   std::string GetSoname() override;
205*eb293b8fSAndroid Build Coastguard Worker 
206*eb293b8fSAndroid Build Coastguard Worker   bool GetFunctionName(uint64_t addr, SharedString* name, uint64_t* func_offset) override;
207*eb293b8fSAndroid Build Coastguard Worker 
208*eb293b8fSAndroid Build Coastguard Worker   bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override;
209*eb293b8fSAndroid Build Coastguard Worker 
GetBuildID()210*eb293b8fSAndroid Build Coastguard Worker   std::string GetBuildID() override { return ReadBuildID(); }
211*eb293b8fSAndroid Build Coastguard Worker 
212*eb293b8fSAndroid Build Coastguard Worker   static void GetMaxSize(Memory* memory, uint64_t* size);
213*eb293b8fSAndroid Build Coastguard Worker 
214*eb293b8fSAndroid Build Coastguard Worker  protected:
215*eb293b8fSAndroid Build Coastguard Worker   bool ReadAllHeaders(int64_t* load_bias);
216*eb293b8fSAndroid Build Coastguard Worker 
217*eb293b8fSAndroid Build Coastguard Worker   void ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias);
218*eb293b8fSAndroid Build Coastguard Worker 
219*eb293b8fSAndroid Build Coastguard Worker   void ReadSectionHeaders(const EhdrType& ehdr);
220*eb293b8fSAndroid Build Coastguard Worker 
221*eb293b8fSAndroid Build Coastguard Worker   std::string ReadBuildID();
222*eb293b8fSAndroid Build Coastguard Worker };
223*eb293b8fSAndroid Build Coastguard Worker 
224*eb293b8fSAndroid Build Coastguard Worker using ElfInterface32 = ElfInterfaceImpl<ElfTypes32>;
225*eb293b8fSAndroid Build Coastguard Worker using ElfInterface64 = ElfInterfaceImpl<ElfTypes64>;
226*eb293b8fSAndroid Build Coastguard Worker 
227*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
228