1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <elf.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include <iterator>
24 #include <memory>
25 #include <unordered_map>
26 
27 #include <unwindstack/ElfInterface.h>
28 #include <unwindstack/Memory.h>
29 
30 namespace unwindstack {
31 
32 class ElfInterfaceArm : public ElfInterface32 {
33  public:
ElfInterfaceArm(std::shared_ptr<Memory> & memory)34   ElfInterfaceArm(std::shared_ptr<Memory>& memory) : ElfInterface32(memory) {}
35   virtual ~ElfInterfaceArm() = default;
36 
37   class iterator {
38    public:
39     using iterator_category = std::bidirectional_iterator_tag;
40     using value_type = uint32_t;
41     using difference_type = ptrdiff_t;
42     using pointer = uint32_t*;
43     using reference = uint32_t&;
44 
iterator(ElfInterfaceArm * interface,size_t index)45     iterator(ElfInterfaceArm* interface, size_t index) : interface_(interface), index_(index) { }
46 
47     iterator& operator++() { index_++; return *this; }
48     iterator& operator++(int increment) { index_ += increment; return *this; }
49     iterator& operator--() { index_--; return *this; }
50     iterator& operator--(int decrement) { index_ -= decrement; return *this; }
51 
52     bool operator==(const iterator& rhs) const { return this->index_ == rhs.index_; }
53     bool operator!=(const iterator& rhs) const { return this->index_ != rhs.index_; }
54 
55     uint32_t operator*() {
56       uint32_t addr = interface_->addrs_[index_];
57       if (addr == 0) {
58         if (!interface_->GetPrel31Addr(interface_->start_offset_ + index_ * 8, &addr)) {
59           return 0;
60         }
61         interface_->addrs_[index_] = addr;
62       }
63       return addr;
64     }
65 
66    private:
67     ElfInterfaceArm* interface_ = nullptr;
68     size_t index_ = 0;
69   };
70 
begin()71   iterator begin() { return iterator(this, 0); }
end()72   iterator end() { return iterator(this, total_entries_); }
73 
74   bool Init(int64_t* section_bias) override;
75 
76   bool GetPrel31Addr(uint32_t offset, uint32_t* addr);
77 
78   bool FindEntry(uint32_t pc, uint64_t* entry_offset);
79 
80   void HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) override;
81 
82   bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
83             bool* is_signal_frame) override;
84 
85   bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
86 
87   bool GetFunctionName(uint64_t addr, SharedString* name, uint64_t* offset) override;
88 
start_offset()89   uint64_t start_offset() { return start_offset_; }
90 
total_entries()91   size_t total_entries() { return total_entries_; }
92 
set_load_bias(uint64_t load_bias)93   void set_load_bias(uint64_t load_bias) { load_bias_ = load_bias; }
94 
95  protected:
96   uint64_t start_offset_ = 0;
97   size_t total_entries_ = 0;
98   uint64_t load_bias_ = 0;
99 
100   std::unordered_map<size_t, uint32_t> addrs_;
101 };
102 
103 }  // namespace unwindstack
104