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 #ifndef _LIBUNWINDSTACK_ARM_EXIDX_H
18 #define _LIBUNWINDSTACK_ARM_EXIDX_H
19 
20 #include <stdint.h>
21 
22 #include <deque>
23 
24 // Forward declarations.
25 class Memory;
26 class RegsArm;
27 
28 enum ArmStatus : size_t {
29   ARM_STATUS_NONE = 0,
30   ARM_STATUS_NO_UNWIND,
31   ARM_STATUS_FINISH,
32   ARM_STATUS_RESERVED,
33   ARM_STATUS_SPARE,
34   ARM_STATUS_TRUNCATED,
35   ARM_STATUS_READ_FAILED,
36   ARM_STATUS_MALFORMED,
37   ARM_STATUS_INVALID_ALIGNMENT,
38   ARM_STATUS_INVALID_PERSONALITY,
39 };
40 
41 enum ArmOp : uint8_t {
42   ARM_OP_FINISH = 0xb0,
43 };
44 
45 class ArmExidx {
46  public:
ArmExidx(RegsArm * regs,Memory * elf_memory,Memory * process_memory)47   ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory)
48       : regs_(regs), elf_memory_(elf_memory), process_memory_(process_memory) {}
~ArmExidx()49   virtual ~ArmExidx() {}
50 
51   void LogRawData();
52 
53   bool ExtractEntryData(uint32_t entry_offset);
54 
55   bool Eval();
56 
57   bool Decode();
58 
data()59   std::deque<uint8_t>* data() { return &data_; }
60 
status()61   ArmStatus status() { return status_; }
62 
regs()63   RegsArm* regs() { return regs_; }
64 
cfa()65   uint32_t cfa() { return cfa_; }
set_cfa(uint32_t cfa)66   void set_cfa(uint32_t cfa) { cfa_ = cfa; }
67 
pc_set()68   bool pc_set() { return pc_set_; }
set_pc_set(bool pc_set)69   void set_pc_set(bool pc_set) { pc_set_ = pc_set; }
70 
set_log(bool log)71   void set_log(bool log) { log_ = log; }
set_log_skip_execution(bool skip_execution)72   void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; }
set_log_indent(uint8_t indent)73   void set_log_indent(uint8_t indent) { log_indent_ = indent; }
74 
75  private:
76   bool GetByte(uint8_t* byte);
77 
78   bool DecodePrefix_10_00(uint8_t byte);
79   bool DecodePrefix_10_01(uint8_t byte);
80   bool DecodePrefix_10_10(uint8_t byte);
81   bool DecodePrefix_10_11_0000();
82   bool DecodePrefix_10_11_0001();
83   bool DecodePrefix_10_11_0010();
84   bool DecodePrefix_10_11_0011();
85   bool DecodePrefix_10_11_01nn();
86   bool DecodePrefix_10_11_1nnn(uint8_t byte);
87   bool DecodePrefix_10(uint8_t byte);
88 
89   bool DecodePrefix_11_000(uint8_t byte);
90   bool DecodePrefix_11_001(uint8_t byte);
91   bool DecodePrefix_11_010(uint8_t byte);
92   bool DecodePrefix_11(uint8_t byte);
93 
94   RegsArm* regs_ = nullptr;
95   uint32_t cfa_ = 0;
96   std::deque<uint8_t> data_;
97   ArmStatus status_ = ARM_STATUS_NONE;
98 
99   Memory* elf_memory_;
100   Memory* process_memory_;
101 
102   bool log_ = false;
103   uint8_t log_indent_ = 0;
104   bool log_skip_execution_ = false;
105   bool pc_set_ = false;
106 };
107 
108 #endif  // _LIBUNWINDSTACK_ARM_EXIDX_H
109