xref: /aosp_15_r20/system/unwinding/libunwindstack/ElfInterfaceArm.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 <stddef.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
22*eb293b8fSAndroid Build Coastguard Worker 
23*eb293b8fSAndroid Build Coastguard Worker #include <iterator>
24*eb293b8fSAndroid Build Coastguard Worker #include <memory>
25*eb293b8fSAndroid Build Coastguard Worker #include <unordered_map>
26*eb293b8fSAndroid Build Coastguard Worker 
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/ElfInterface.h>
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
29*eb293b8fSAndroid Build Coastguard Worker 
30*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
31*eb293b8fSAndroid Build Coastguard Worker 
32*eb293b8fSAndroid Build Coastguard Worker class ElfInterfaceArm : public ElfInterface32 {
33*eb293b8fSAndroid Build Coastguard Worker  public:
ElfInterfaceArm(std::shared_ptr<Memory> & memory)34*eb293b8fSAndroid Build Coastguard Worker   ElfInterfaceArm(std::shared_ptr<Memory>& memory) : ElfInterface32(memory) {}
35*eb293b8fSAndroid Build Coastguard Worker   virtual ~ElfInterfaceArm() = default;
36*eb293b8fSAndroid Build Coastguard Worker 
37*eb293b8fSAndroid Build Coastguard Worker   class iterator {
38*eb293b8fSAndroid Build Coastguard Worker    public:
39*eb293b8fSAndroid Build Coastguard Worker     using iterator_category = std::bidirectional_iterator_tag;
40*eb293b8fSAndroid Build Coastguard Worker     using value_type = uint32_t;
41*eb293b8fSAndroid Build Coastguard Worker     using difference_type = ptrdiff_t;
42*eb293b8fSAndroid Build Coastguard Worker     using pointer = uint32_t*;
43*eb293b8fSAndroid Build Coastguard Worker     using reference = uint32_t&;
44*eb293b8fSAndroid Build Coastguard Worker 
iterator(ElfInterfaceArm * interface,size_t index)45*eb293b8fSAndroid Build Coastguard Worker     iterator(ElfInterfaceArm* interface, size_t index) : interface_(interface), index_(index) { }
46*eb293b8fSAndroid Build Coastguard Worker 
47*eb293b8fSAndroid Build Coastguard Worker     iterator& operator++() { index_++; return *this; }
48*eb293b8fSAndroid Build Coastguard Worker     iterator& operator++(int increment) { index_ += increment; return *this; }
49*eb293b8fSAndroid Build Coastguard Worker     iterator& operator--() { index_--; return *this; }
50*eb293b8fSAndroid Build Coastguard Worker     iterator& operator--(int decrement) { index_ -= decrement; return *this; }
51*eb293b8fSAndroid Build Coastguard Worker 
52*eb293b8fSAndroid Build Coastguard Worker     bool operator==(const iterator& rhs) const { return this->index_ == rhs.index_; }
53*eb293b8fSAndroid Build Coastguard Worker     bool operator!=(const iterator& rhs) const { return this->index_ != rhs.index_; }
54*eb293b8fSAndroid Build Coastguard Worker 
55*eb293b8fSAndroid Build Coastguard Worker     uint32_t operator*() {
56*eb293b8fSAndroid Build Coastguard Worker       uint32_t addr = interface_->addrs_[index_];
57*eb293b8fSAndroid Build Coastguard Worker       if (addr == 0) {
58*eb293b8fSAndroid Build Coastguard Worker         if (!interface_->GetPrel31Addr(interface_->start_offset_ + index_ * 8, &addr)) {
59*eb293b8fSAndroid Build Coastguard Worker           return 0;
60*eb293b8fSAndroid Build Coastguard Worker         }
61*eb293b8fSAndroid Build Coastguard Worker         interface_->addrs_[index_] = addr;
62*eb293b8fSAndroid Build Coastguard Worker       }
63*eb293b8fSAndroid Build Coastguard Worker       return addr;
64*eb293b8fSAndroid Build Coastguard Worker     }
65*eb293b8fSAndroid Build Coastguard Worker 
66*eb293b8fSAndroid Build Coastguard Worker    private:
67*eb293b8fSAndroid Build Coastguard Worker     ElfInterfaceArm* interface_ = nullptr;
68*eb293b8fSAndroid Build Coastguard Worker     size_t index_ = 0;
69*eb293b8fSAndroid Build Coastguard Worker   };
70*eb293b8fSAndroid Build Coastguard Worker 
begin()71*eb293b8fSAndroid Build Coastguard Worker   iterator begin() { return iterator(this, 0); }
end()72*eb293b8fSAndroid Build Coastguard Worker   iterator end() { return iterator(this, total_entries_); }
73*eb293b8fSAndroid Build Coastguard Worker 
74*eb293b8fSAndroid Build Coastguard Worker   bool Init(int64_t* section_bias) override;
75*eb293b8fSAndroid Build Coastguard Worker 
76*eb293b8fSAndroid Build Coastguard Worker   bool GetPrel31Addr(uint32_t offset, uint32_t* addr);
77*eb293b8fSAndroid Build Coastguard Worker 
78*eb293b8fSAndroid Build Coastguard Worker   bool FindEntry(uint32_t pc, uint64_t* entry_offset);
79*eb293b8fSAndroid Build Coastguard Worker 
80*eb293b8fSAndroid Build Coastguard Worker   void HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) override;
81*eb293b8fSAndroid Build Coastguard Worker 
82*eb293b8fSAndroid Build Coastguard Worker   bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
83*eb293b8fSAndroid Build Coastguard Worker             bool* is_signal_frame) override;
84*eb293b8fSAndroid Build Coastguard Worker 
85*eb293b8fSAndroid Build Coastguard Worker   bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
86*eb293b8fSAndroid Build Coastguard Worker 
87*eb293b8fSAndroid Build Coastguard Worker   bool GetFunctionName(uint64_t addr, SharedString* name, uint64_t* offset) override;
88*eb293b8fSAndroid Build Coastguard Worker 
start_offset()89*eb293b8fSAndroid Build Coastguard Worker   uint64_t start_offset() { return start_offset_; }
90*eb293b8fSAndroid Build Coastguard Worker 
total_entries()91*eb293b8fSAndroid Build Coastguard Worker   size_t total_entries() { return total_entries_; }
92*eb293b8fSAndroid Build Coastguard Worker 
set_load_bias(uint64_t load_bias)93*eb293b8fSAndroid Build Coastguard Worker   void set_load_bias(uint64_t load_bias) { load_bias_ = load_bias; }
94*eb293b8fSAndroid Build Coastguard Worker 
95*eb293b8fSAndroid Build Coastguard Worker  protected:
96*eb293b8fSAndroid Build Coastguard Worker   uint64_t start_offset_ = 0;
97*eb293b8fSAndroid Build Coastguard Worker   size_t total_entries_ = 0;
98*eb293b8fSAndroid Build Coastguard Worker   uint64_t load_bias_ = 0;
99*eb293b8fSAndroid Build Coastguard Worker 
100*eb293b8fSAndroid Build Coastguard Worker   std::unordered_map<size_t, uint32_t> addrs_;
101*eb293b8fSAndroid Build Coastguard Worker };
102*eb293b8fSAndroid Build Coastguard Worker 
103*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
104