blob: 69e6512ddf534c860cf3d0bd4b03b8e9d469481d [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
Christopher Ferris3958f802017-02-01 15:44:40 -080017#include <elf.h>
18#include <stdint.h>
19#include <sys/ptrace.h>
20#include <sys/uio.h>
21
22#include <vector>
23
Christopher Ferrisd226a512017-07-14 10:37:19 -070024#include <unwindstack/Elf.h>
25#include <unwindstack/MapInfo.h>
26#include <unwindstack/Memory.h>
27#include <unwindstack/Regs.h>
28
Christopher Ferris94167032017-06-28 18:56:52 -070029#include "Check.h"
Christopher Ferris3958f802017-02-01 15:44:40 -080030#include "Machine.h"
Christopher Ferris2a25c4a2017-07-07 16:35:48 -070031#include "Ucontext.h"
Christopher Ferris3958f802017-02-01 15:44:40 -080032#include "User.h"
33
Christopher Ferrisd226a512017-07-14 10:37:19 -070034namespace unwindstack {
Christopher Ferris3958f802017-02-01 15:44:40 -080035
Christopher Ferris7b8e4672017-06-01 17:55:25 -070036RegsArm::RegsArm()
37 : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
Christopher Ferris3958f802017-02-01 15:44:40 -080038
Josh Gao0953ecd2017-08-25 13:55:06 -070039uint32_t RegsArm::MachineType() {
40 return EM_ARM;
41}
42
Christopher Ferris3958f802017-02-01 15:44:40 -080043uint64_t RegsArm::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
44 if (!elf->valid()) {
45 return rel_pc;
46 }
47
48 uint64_t load_bias = elf->interface()->load_bias();
49 if (rel_pc < load_bias) {
50 return rel_pc;
51 }
52 uint64_t adjusted_rel_pc = rel_pc - load_bias;
53
54 if (adjusted_rel_pc < 5) {
55 return rel_pc;
56 }
57
58 if (adjusted_rel_pc & 1) {
59 // This is a thumb instruction, it could be 2 or 4 bytes.
60 uint32_t value;
61 if (rel_pc < 5 || !elf->memory()->Read(adjusted_rel_pc - 5, &value, sizeof(value)) ||
62 (value & 0xe000f000) != 0xe000f000) {
63 return rel_pc - 2;
64 }
65 }
66 return rel_pc - 4;
67}
68
Christopher Ferris2a25c4a2017-07-07 16:35:48 -070069void RegsArm::SetFromRaw() {
70 set_pc(regs_[ARM_REG_PC]);
71 set_sp(regs_[ARM_REG_SP]);
72}
73
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070074bool RegsArm::SetPcFromReturnAddress(Memory*) {
75 if (pc() == regs_[ARM_REG_LR]) {
76 return false;
77 }
78
79 set_pc(regs_[ARM_REG_LR]);
80 return true;
81}
82
Christopher Ferris7b8e4672017-06-01 17:55:25 -070083RegsArm64::RegsArm64()
84 : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
Christopher Ferris3958f802017-02-01 15:44:40 -080085
Josh Gao0953ecd2017-08-25 13:55:06 -070086uint32_t RegsArm64::MachineType() {
87 return EM_AARCH64;
88}
89
Christopher Ferris3958f802017-02-01 15:44:40 -080090uint64_t RegsArm64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
91 if (!elf->valid()) {
92 return rel_pc;
93 }
94
95 if (rel_pc < 4) {
96 return rel_pc;
97 }
98 return rel_pc - 4;
99}
100
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700101void RegsArm64::SetFromRaw() {
102 set_pc(regs_[ARM64_REG_PC]);
103 set_sp(regs_[ARM64_REG_SP]);
104}
105
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700106bool RegsArm64::SetPcFromReturnAddress(Memory*) {
107 if (pc() == regs_[ARM64_REG_LR]) {
108 return false;
109 }
110
111 set_pc(regs_[ARM64_REG_LR]);
112 return true;
113}
114
Christopher Ferris7b8e4672017-06-01 17:55:25 -0700115RegsX86::RegsX86()
116 : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
Christopher Ferris3958f802017-02-01 15:44:40 -0800117
Josh Gao0953ecd2017-08-25 13:55:06 -0700118uint32_t RegsX86::MachineType() {
119 return EM_386;
120}
121
Christopher Ferris3958f802017-02-01 15:44:40 -0800122uint64_t RegsX86::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
123 if (!elf->valid()) {
124 return rel_pc;
125 }
126
127 if (rel_pc == 0) {
128 return 0;
129 }
130 return rel_pc - 1;
131}
132
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700133void RegsX86::SetFromRaw() {
134 set_pc(regs_[X86_REG_PC]);
135 set_sp(regs_[X86_REG_SP]);
136}
137
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700138bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
139 // Attempt to get the return address from the top of the stack.
140 uint32_t new_pc;
141 if (!process_memory->Read(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
142 return false;
143 }
144
145 set_pc(new_pc);
146 return true;
147}
148
Christopher Ferris7b8e4672017-06-01 17:55:25 -0700149RegsX86_64::RegsX86_64()
150 : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
Christopher Ferris3958f802017-02-01 15:44:40 -0800151
Josh Gao0953ecd2017-08-25 13:55:06 -0700152uint32_t RegsX86_64::MachineType() {
153 return EM_X86_64;
154}
155
Christopher Ferris3958f802017-02-01 15:44:40 -0800156uint64_t RegsX86_64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
157 if (!elf->valid()) {
158 return rel_pc;
159 }
160
161 if (rel_pc == 0) {
162 return 0;
163 }
164
165 return rel_pc - 1;
166}
167
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700168void RegsX86_64::SetFromRaw() {
169 set_pc(regs_[X86_64_REG_PC]);
170 set_sp(regs_[X86_64_REG_SP]);
171}
172
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700173bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
174 // Attempt to get the return address from the top of the stack.
175 uint64_t new_pc;
176 if (!process_memory->Read(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
177 return false;
178 }
179
180 set_pc(new_pc);
181 return true;
182}
183
Christopher Ferris3958f802017-02-01 15:44:40 -0800184static Regs* ReadArm(void* remote_data) {
185 arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
186
187 RegsArm* regs = new RegsArm();
188 memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700189 regs->SetFromRaw();
Christopher Ferris3958f802017-02-01 15:44:40 -0800190 return regs;
191}
192
193static Regs* ReadArm64(void* remote_data) {
194 arm64_user_regs* user = reinterpret_cast<arm64_user_regs*>(remote_data);
195
196 RegsArm64* regs = new RegsArm64();
197 memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700198 uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
199 reg_data[ARM64_REG_PC] = user->pc;
200 reg_data[ARM64_REG_SP] = user->sp;
201 regs->SetFromRaw();
Christopher Ferris3958f802017-02-01 15:44:40 -0800202 return regs;
203}
204
205static Regs* ReadX86(void* remote_data) {
206 x86_user_regs* user = reinterpret_cast<x86_user_regs*>(remote_data);
207
208 RegsX86* regs = new RegsX86();
209 (*regs)[X86_REG_EAX] = user->eax;
210 (*regs)[X86_REG_EBX] = user->ebx;
211 (*regs)[X86_REG_ECX] = user->ecx;
212 (*regs)[X86_REG_EDX] = user->edx;
213 (*regs)[X86_REG_EBP] = user->ebp;
214 (*regs)[X86_REG_EDI] = user->edi;
215 (*regs)[X86_REG_ESI] = user->esi;
216 (*regs)[X86_REG_ESP] = user->esp;
217 (*regs)[X86_REG_EIP] = user->eip;
218
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700219 regs->SetFromRaw();
Christopher Ferris3958f802017-02-01 15:44:40 -0800220 return regs;
221}
222
223static Regs* ReadX86_64(void* remote_data) {
224 x86_64_user_regs* user = reinterpret_cast<x86_64_user_regs*>(remote_data);
225
226 RegsX86_64* regs = new RegsX86_64();
227 (*regs)[X86_64_REG_RAX] = user->rax;
228 (*regs)[X86_64_REG_RBX] = user->rbx;
229 (*regs)[X86_64_REG_RCX] = user->rcx;
230 (*regs)[X86_64_REG_RDX] = user->rdx;
231 (*regs)[X86_64_REG_R8] = user->r8;
232 (*regs)[X86_64_REG_R9] = user->r9;
233 (*regs)[X86_64_REG_R10] = user->r10;
234 (*regs)[X86_64_REG_R11] = user->r11;
235 (*regs)[X86_64_REG_R12] = user->r12;
236 (*regs)[X86_64_REG_R13] = user->r13;
237 (*regs)[X86_64_REG_R14] = user->r14;
238 (*regs)[X86_64_REG_R15] = user->r15;
239 (*regs)[X86_64_REG_RDI] = user->rdi;
240 (*regs)[X86_64_REG_RSI] = user->rsi;
241 (*regs)[X86_64_REG_RBP] = user->rbp;
242 (*regs)[X86_64_REG_RSP] = user->rsp;
243 (*regs)[X86_64_REG_RIP] = user->rip;
244
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700245 regs->SetFromRaw();
Christopher Ferris3958f802017-02-01 15:44:40 -0800246 return regs;
247}
248
249// This function assumes that reg_data is already aligned to a 64 bit value.
250// If not this could crash with an unaligned access.
Josh Gao0953ecd2017-08-25 13:55:06 -0700251Regs* Regs::RemoteGet(pid_t pid) {
Christopher Ferris3958f802017-02-01 15:44:40 -0800252 // Make the buffer large enough to contain the largest registers type.
253 std::vector<uint64_t> buffer(MAX_USER_REGS_SIZE / sizeof(uint64_t));
254 struct iovec io;
255 io.iov_base = buffer.data();
256 io.iov_len = buffer.size() * sizeof(uint64_t);
257
258 if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, reinterpret_cast<void*>(&io)) == -1) {
259 return nullptr;
260 }
261
262 switch (io.iov_len) {
263 case sizeof(x86_user_regs):
Christopher Ferris3958f802017-02-01 15:44:40 -0800264 return ReadX86(buffer.data());
265 case sizeof(x86_64_user_regs):
Christopher Ferris3958f802017-02-01 15:44:40 -0800266 return ReadX86_64(buffer.data());
267 case sizeof(arm_user_regs):
Christopher Ferris3958f802017-02-01 15:44:40 -0800268 return ReadArm(buffer.data());
269 case sizeof(arm64_user_regs):
Christopher Ferris3958f802017-02-01 15:44:40 -0800270 return ReadArm64(buffer.data());
271 }
272 return nullptr;
273}
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700274
275static Regs* CreateFromArmUcontext(void* ucontext) {
276 arm_ucontext_t* arm_ucontext = reinterpret_cast<arm_ucontext_t*>(ucontext);
277
278 RegsArm* regs = new RegsArm();
279 memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
280 regs->SetFromRaw();
281 return regs;
282}
283
284static Regs* CreateFromArm64Ucontext(void* ucontext) {
285 arm64_ucontext_t* arm64_ucontext = reinterpret_cast<arm64_ucontext_t*>(ucontext);
286
287 RegsArm64* regs = new RegsArm64();
288 memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
289 regs->SetFromRaw();
290 return regs;
291}
292
Christopher Ferrisa0196652017-07-18 16:09:20 -0700293void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) {
294 // Put the registers in the expected order.
295 regs_[X86_REG_EDI] = ucontext->uc_mcontext.edi;
296 regs_[X86_REG_ESI] = ucontext->uc_mcontext.esi;
297 regs_[X86_REG_EBP] = ucontext->uc_mcontext.ebp;
298 regs_[X86_REG_ESP] = ucontext->uc_mcontext.esp;
299 regs_[X86_REG_EBX] = ucontext->uc_mcontext.ebx;
300 regs_[X86_REG_EDX] = ucontext->uc_mcontext.edx;
301 regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx;
302 regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax;
303 regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip;
304 SetFromRaw();
305}
306
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700307static Regs* CreateFromX86Ucontext(void* ucontext) {
308 x86_ucontext_t* x86_ucontext = reinterpret_cast<x86_ucontext_t*>(ucontext);
309
310 RegsX86* regs = new RegsX86();
Christopher Ferrisa0196652017-07-18 16:09:20 -0700311 regs->SetFromUcontext(x86_ucontext);
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700312 return regs;
313}
314
Christopher Ferrisa0196652017-07-18 16:09:20 -0700315void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
316 // R8-R15
317 memcpy(&regs_[X86_64_REG_R8], &ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));
318
319 // Rest of the registers.
320 regs_[X86_64_REG_RDI] = ucontext->uc_mcontext.rdi;
321 regs_[X86_64_REG_RSI] = ucontext->uc_mcontext.rsi;
322 regs_[X86_64_REG_RBP] = ucontext->uc_mcontext.rbp;
323 regs_[X86_64_REG_RBX] = ucontext->uc_mcontext.rbx;
324 regs_[X86_64_REG_RDX] = ucontext->uc_mcontext.rdx;
325 regs_[X86_64_REG_RAX] = ucontext->uc_mcontext.rax;
326 regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
327 regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
328 regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
329
330 SetFromRaw();
331}
332
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700333static Regs* CreateFromX86_64Ucontext(void* ucontext) {
334 x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);
335
336 RegsX86_64* regs = new RegsX86_64();
Christopher Ferrisa0196652017-07-18 16:09:20 -0700337 regs->SetFromUcontext(x86_64_ucontext);
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700338 return regs;
339}
340
341Regs* Regs::CreateFromUcontext(uint32_t machine_type, void* ucontext) {
342 switch (machine_type) {
343 case EM_386:
344 return CreateFromX86Ucontext(ucontext);
345 case EM_X86_64:
346 return CreateFromX86_64Ucontext(ucontext);
347 case EM_ARM:
348 return CreateFromArmUcontext(ucontext);
349 case EM_AARCH64:
350 return CreateFromArm64Ucontext(ucontext);
351 }
352 return nullptr;
353}
354
Josh Gao0953ecd2017-08-25 13:55:06 -0700355uint32_t Regs::CurrentMachineType() {
Christopher Ferris2a25c4a2017-07-07 16:35:48 -0700356#if defined(__arm__)
357 return EM_ARM;
358#elif defined(__aarch64__)
359 return EM_AARCH64;
360#elif defined(__i386__)
361 return EM_386;
362#elif defined(__x86_64__)
363 return EM_X86_64;
364#else
365 abort();
366#endif
367}
368
369Regs* Regs::CreateFromLocal() {
370 Regs* regs;
371#if defined(__arm__)
372 regs = new RegsArm();
373#elif defined(__aarch64__)
374 regs = new RegsArm64();
375#elif defined(__i386__)
376 regs = new RegsX86();
377#elif defined(__x86_64__)
378 regs = new RegsX86_64();
379#else
380 abort();
381#endif
382 return regs;
383}
Christopher Ferrisd226a512017-07-14 10:37:19 -0700384
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700385bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700386 uint32_t data;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700387 Memory* elf_memory = elf->memory();
388 // Read from elf memory since it is usually more expensive to read from
389 // process memory.
390 if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700391 return false;
392 }
393
394 uint64_t offset = 0;
395 if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
396 // non-RT sigreturn call.
397 // __restore:
398 //
399 // Form 1 (arm):
400 // 0x77 0x70 mov r7, #0x77
401 // 0xa0 0xe3 svc 0x00000000
402 //
403 // Form 2 (arm):
404 // 0x77 0x00 0x90 0xef svc 0x00900077
405 //
406 // Form 3 (thumb):
407 // 0x77 0x27 movs r7, #77
408 // 0x00 0xdf svc 0
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700409 if (!process_memory->Read(sp(), &data, sizeof(data))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700410 return false;
411 }
412 if (data == 0x5ac3c35a) {
413 // SP + uc_mcontext offset + r0 offset.
414 offset = sp() + 0x14 + 0xc;
415 } else {
416 // SP + r0 offset
417 offset = sp() + 0xc;
418 }
419 } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
420 // RT sigreturn call.
421 // __restore_rt:
422 //
423 // Form 1 (arm):
424 // 0xad 0x70 mov r7, #0xad
425 // 0xa0 0xe3 svc 0x00000000
426 //
427 // Form 2 (arm):
428 // 0xad 0x00 0x90 0xef svc 0x009000ad
429 //
430 // Form 3 (thumb):
431 // 0xad 0x27 movs r7, #ad
432 // 0x00 0xdf svc 0
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700433 if (!process_memory->Read(sp(), &data, sizeof(data))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700434 return false;
435 }
436 if (data == sp() + 8) {
437 // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
438 offset = sp() + 8 + 0x80 + 0x14 + 0xc;
439 } else {
440 // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
441 offset = sp() + 0x80 + 0x14 + 0xc;
442 }
443 }
444 if (offset == 0) {
445 return false;
446 }
447
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700448 if (!process_memory->Read(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700449 return false;
450 }
451 SetFromRaw();
452 return true;
453}
454
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700455bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700456 uint64_t data;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700457 Memory* elf_memory = elf->memory();
458 // Read from elf memory since it is usually more expensive to read from
459 // process memory.
460 if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700461 return false;
462 }
463
464 // Look for the kernel sigreturn function.
465 // __kernel_rt_sigreturn:
466 // 0xd2801168 mov x8, #0x8b
467 // 0xd4000001 svc #0x0
468 if (data != 0xd4000001d2801168ULL) {
469 return false;
470 }
471
472 // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700473 if (!process_memory->Read(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
474 sizeof(uint64_t) * ARM64_REG_LAST)) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700475 return false;
476 }
477
478 SetFromRaw();
479 return true;
480}
481
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700482bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700483 uint64_t data;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700484 Memory* elf_memory = elf->memory();
485 // Read from elf memory since it is usually more expensive to read from
486 // process memory.
487 if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700488 return false;
489 }
490
491 if (data == 0x80cd00000077b858ULL) {
492 // Without SA_SIGINFO set, the return sequence is:
493 //
494 // __restore:
495 // 0x58 pop %eax
496 // 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
497 // 0xcd 0x80 int 0x80
498 //
499 // SP points at arguments:
500 // int signum
501 // struct sigcontext (same format as mcontext)
502 struct x86_mcontext_t context;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700503 if (!process_memory->Read(sp() + 4, &context, sizeof(context))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700504 return false;
505 }
506 regs_[X86_REG_EBP] = context.ebp;
507 regs_[X86_REG_ESP] = context.esp;
508 regs_[X86_REG_EBX] = context.ebx;
509 regs_[X86_REG_EDX] = context.edx;
510 regs_[X86_REG_ECX] = context.ecx;
511 regs_[X86_REG_EAX] = context.eax;
512 regs_[X86_REG_EIP] = context.eip;
513 SetFromRaw();
514 return true;
515 } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) {
516 // With SA_SIGINFO set, the return sequence is:
517 //
518 // __restore_rt:
519 // 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
520 // 0xcd 0x80 int 0x80
521 //
522 // SP points at arguments:
523 // int signum
524 // siginfo*
525 // ucontext*
526
527 // Get the location of the sigcontext data.
528 uint32_t ptr;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700529 if (!process_memory->Read(sp() + 8, &ptr, sizeof(ptr))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700530 return false;
531 }
532 // Only read the portion of the data structure we care about.
533 x86_ucontext_t x86_ucontext;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700534 if (!process_memory->Read(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700535 return false;
536 }
537 SetFromUcontext(&x86_ucontext);
538 return true;
539 }
540 return false;
541}
542
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700543bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700544 uint64_t data;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700545 Memory* elf_memory = elf->memory();
546 // Read from elf memory since it is usually more expensive to read from
547 // process memory.
548 if (!elf_memory->Read(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700549 return false;
550 }
551
552 uint16_t data2;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700553 if (!elf_memory->Read(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700554 return false;
555 }
556
557 // __restore_rt:
558 // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax
559 // 0x0f 0x05 syscall
560 // 0x0f nopl 0x0($rax)
561
562 // Read the mcontext data from the stack.
563 // sp points to the ucontext data structure, read only the mcontext part.
564 x86_64_ucontext_t x86_64_ucontext;
Christopher Ferriseb4a6db2017-07-19 12:37:45 -0700565 if (!process_memory->Read(sp() + 0x28, &x86_64_ucontext.uc_mcontext, sizeof(x86_64_mcontext_t))) {
Christopher Ferrisa0196652017-07-18 16:09:20 -0700566 return false;
567 }
568 SetFromUcontext(&x86_64_ucontext);
569 return true;
570}
571
Christopher Ferrisd226a512017-07-14 10:37:19 -0700572} // namespace unwindstack