blob: adb652224824de14b47bfc316b61afcdfe599b52 [file] [log] [blame]
Christopher Ferris3958f802017-02-01 15:44:40 -08001/*
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
32template <typename AddressType>
33uint64_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
42template <typename AddressType>
43bool 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
62RegsArm::RegsArm() : RegsTmpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP,
63 Location(LOCATION_REGISTER, ARM_REG_LR)) {
64}
65
66uint64_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
92RegsArm64::RegsArm64() : RegsTmpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP,
93 Location(LOCATION_REGISTER, ARM64_REG_LR)) {
94}
95
96uint64_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
107RegsX86::RegsX86() : RegsTmpl<uint32_t>(X86_REG_LAST, X86_REG_SP,
108 Location(LOCATION_SP_OFFSET, -4)) {
109}
110
111uint64_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
122RegsX86_64::RegsX86_64() : RegsTmpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP,
123 Location(LOCATION_SP_OFFSET, -8)) {
124}
125
126uint64_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
138static 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
150static 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
161static 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
181static 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.
211Regs* 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}