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 #include <assert.h>
18 #include <elf.h>
19 #include <stdint.h>
20 #include <sys/ptrace.h>
21 #include <sys/uio.h>
22
23 #include <vector>
24
25 #include "Elf.h"
26 #include "ElfInterface.h"
27 #include "Machine.h"
28 #include "MapInfo.h"
29 #include "Regs.h"
30 #include "User.h"
31
32 template <typename AddressType>
GetRelPc(Elf * elf,const MapInfo * map_info)33 uint64_t RegsTmpl<AddressType>::GetRelPc(Elf* elf, const MapInfo* map_info) {
34 uint64_t load_bias = 0;
35 if (elf->valid()) {
36 load_bias = elf->interface()->load_bias();
37 }
38
39 return pc_ - map_info->start + load_bias + map_info->elf_offset;
40 }
41
42 template <typename AddressType>
GetReturnAddressFromDefault(Memory * memory,uint64_t * value)43 bool RegsTmpl<AddressType>::GetReturnAddressFromDefault(Memory* memory, uint64_t* value) {
44 switch (return_loc_.type) {
45 case LOCATION_REGISTER:
46 assert(return_loc_.value < total_regs_);
47 *value = regs_[return_loc_.value];
48 return true;
49 case LOCATION_SP_OFFSET:
50 AddressType return_value;
51 if (!memory->Read(sp_ + return_loc_.value, &return_value, sizeof(return_value))) {
52 return false;
53 }
54 *value = return_value;
55 return true;
56 case LOCATION_UNKNOWN:
57 default:
58 return false;
59 }
60 }
61
RegsArm()62 RegsArm::RegsArm() : RegsTmpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP,
63 Location(LOCATION_REGISTER, ARM_REG_LR)) {
64 }
65
GetAdjustedPc(uint64_t rel_pc,Elf * elf)66 uint64_t RegsArm::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
67 if (!elf->valid()) {
68 return rel_pc;
69 }
70
71 uint64_t load_bias = elf->interface()->load_bias();
72 if (rel_pc < load_bias) {
73 return rel_pc;
74 }
75 uint64_t adjusted_rel_pc = rel_pc - load_bias;
76
77 if (adjusted_rel_pc < 5) {
78 return rel_pc;
79 }
80
81 if (adjusted_rel_pc & 1) {
82 // This is a thumb instruction, it could be 2 or 4 bytes.
83 uint32_t value;
84 if (rel_pc < 5 || !elf->memory()->Read(adjusted_rel_pc - 5, &value, sizeof(value)) ||
85 (value & 0xe000f000) != 0xe000f000) {
86 return rel_pc - 2;
87 }
88 }
89 return rel_pc - 4;
90 }
91
RegsArm64()92 RegsArm64::RegsArm64() : RegsTmpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP,
93 Location(LOCATION_REGISTER, ARM64_REG_LR)) {
94 }
95
GetAdjustedPc(uint64_t rel_pc,Elf * elf)96 uint64_t RegsArm64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
97 if (!elf->valid()) {
98 return rel_pc;
99 }
100
101 if (rel_pc < 4) {
102 return rel_pc;
103 }
104 return rel_pc - 4;
105 }
106
RegsX86()107 RegsX86::RegsX86() : RegsTmpl<uint32_t>(X86_REG_LAST, X86_REG_SP,
108 Location(LOCATION_SP_OFFSET, -4)) {
109 }
110
GetAdjustedPc(uint64_t rel_pc,Elf * elf)111 uint64_t RegsX86::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
112 if (!elf->valid()) {
113 return rel_pc;
114 }
115
116 if (rel_pc == 0) {
117 return 0;
118 }
119 return rel_pc - 1;
120 }
121
RegsX86_64()122 RegsX86_64::RegsX86_64() : RegsTmpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP,
123 Location(LOCATION_SP_OFFSET, -8)) {
124 }
125
GetAdjustedPc(uint64_t rel_pc,Elf * elf)126 uint64_t RegsX86_64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
127 if (!elf->valid()) {
128 return rel_pc;
129 }
130
131 if (rel_pc == 0) {
132 return 0;
133 }
134
135 return rel_pc - 1;
136 }
137
ReadArm(void * remote_data)138 static Regs* ReadArm(void* remote_data) {
139 arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
140
141 RegsArm* regs = new RegsArm();
142 memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
143
144 regs->set_pc(user->regs[ARM_REG_PC]);
145 regs->set_sp(user->regs[ARM_REG_SP]);
146
147 return regs;
148 }
149
ReadArm64(void * remote_data)150 static Regs* ReadArm64(void* remote_data) {
151 arm64_user_regs* user = reinterpret_cast<arm64_user_regs*>(remote_data);
152
153 RegsArm64* regs = new RegsArm64();
154 memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
155 regs->set_pc(user->pc);
156 regs->set_sp(user->sp);
157
158 return regs;
159 }
160
ReadX86(void * remote_data)161 static Regs* ReadX86(void* remote_data) {
162 x86_user_regs* user = reinterpret_cast<x86_user_regs*>(remote_data);
163
164 RegsX86* regs = new RegsX86();
165 (*regs)[X86_REG_EAX] = user->eax;
166 (*regs)[X86_REG_EBX] = user->ebx;
167 (*regs)[X86_REG_ECX] = user->ecx;
168 (*regs)[X86_REG_EDX] = user->edx;
169 (*regs)[X86_REG_EBP] = user->ebp;
170 (*regs)[X86_REG_EDI] = user->edi;
171 (*regs)[X86_REG_ESI] = user->esi;
172 (*regs)[X86_REG_ESP] = user->esp;
173 (*regs)[X86_REG_EIP] = user->eip;
174
175 regs->set_pc(user->eip);
176 regs->set_sp(user->esp);
177
178 return regs;
179 }
180
ReadX86_64(void * remote_data)181 static Regs* ReadX86_64(void* remote_data) {
182 x86_64_user_regs* user = reinterpret_cast<x86_64_user_regs*>(remote_data);
183
184 RegsX86_64* regs = new RegsX86_64();
185 (*regs)[X86_64_REG_RAX] = user->rax;
186 (*regs)[X86_64_REG_RBX] = user->rbx;
187 (*regs)[X86_64_REG_RCX] = user->rcx;
188 (*regs)[X86_64_REG_RDX] = user->rdx;
189 (*regs)[X86_64_REG_R8] = user->r8;
190 (*regs)[X86_64_REG_R9] = user->r9;
191 (*regs)[X86_64_REG_R10] = user->r10;
192 (*regs)[X86_64_REG_R11] = user->r11;
193 (*regs)[X86_64_REG_R12] = user->r12;
194 (*regs)[X86_64_REG_R13] = user->r13;
195 (*regs)[X86_64_REG_R14] = user->r14;
196 (*regs)[X86_64_REG_R15] = user->r15;
197 (*regs)[X86_64_REG_RDI] = user->rdi;
198 (*regs)[X86_64_REG_RSI] = user->rsi;
199 (*regs)[X86_64_REG_RBP] = user->rbp;
200 (*regs)[X86_64_REG_RSP] = user->rsp;
201 (*regs)[X86_64_REG_RIP] = user->rip;
202
203 regs->set_pc(user->rip);
204 regs->set_sp(user->rsp);
205
206 return regs;
207 }
208
209 // This function assumes that reg_data is already aligned to a 64 bit value.
210 // If not this could crash with an unaligned access.
RemoteGet(pid_t pid,uint32_t * machine_type)211 Regs* Regs::RemoteGet(pid_t pid, uint32_t* machine_type) {
212 // Make the buffer large enough to contain the largest registers type.
213 std::vector<uint64_t> buffer(MAX_USER_REGS_SIZE / sizeof(uint64_t));
214 struct iovec io;
215 io.iov_base = buffer.data();
216 io.iov_len = buffer.size() * sizeof(uint64_t);
217
218 if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, reinterpret_cast<void*>(&io)) == -1) {
219 return nullptr;
220 }
221
222 switch (io.iov_len) {
223 case sizeof(x86_user_regs):
224 *machine_type = EM_386;
225 return ReadX86(buffer.data());
226 case sizeof(x86_64_user_regs):
227 *machine_type = EM_X86_64;
228 return ReadX86_64(buffer.data());
229 case sizeof(arm_user_regs):
230 *machine_type = EM_ARM;
231 return ReadArm(buffer.data());
232 case sizeof(arm64_user_regs):
233 *machine_type = EM_AARCH64;
234 return ReadArm64(buffer.data());
235 }
236 return nullptr;
237 }
238