1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
18*eb293b8fSAndroid Build Coastguard Worker
19*eb293b8fSAndroid Build Coastguard Worker #include <functional>
20*eb293b8fSAndroid Build Coastguard Worker
21*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
22*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineX86.h>
23*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
24*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsX86.h>
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UcontextX86.h>
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UserX86.h>
28*eb293b8fSAndroid Build Coastguard Worker
29*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
30*eb293b8fSAndroid Build Coastguard Worker
RegsX86()31*eb293b8fSAndroid Build Coastguard Worker RegsX86::RegsX86() : RegsImpl<uint32_t>(X86_REG_LAST, Location(LOCATION_SP_OFFSET, -4)) {}
32*eb293b8fSAndroid Build Coastguard Worker
Arch()33*eb293b8fSAndroid Build Coastguard Worker ArchEnum RegsX86::Arch() {
34*eb293b8fSAndroid Build Coastguard Worker return ARCH_X86;
35*eb293b8fSAndroid Build Coastguard Worker }
36*eb293b8fSAndroid Build Coastguard Worker
pc()37*eb293b8fSAndroid Build Coastguard Worker uint64_t RegsX86::pc() {
38*eb293b8fSAndroid Build Coastguard Worker return regs_[X86_REG_PC];
39*eb293b8fSAndroid Build Coastguard Worker }
40*eb293b8fSAndroid Build Coastguard Worker
sp()41*eb293b8fSAndroid Build Coastguard Worker uint64_t RegsX86::sp() {
42*eb293b8fSAndroid Build Coastguard Worker return regs_[X86_REG_SP];
43*eb293b8fSAndroid Build Coastguard Worker }
44*eb293b8fSAndroid Build Coastguard Worker
set_pc(uint64_t pc)45*eb293b8fSAndroid Build Coastguard Worker void RegsX86::set_pc(uint64_t pc) {
46*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_PC] = static_cast<uint32_t>(pc);
47*eb293b8fSAndroid Build Coastguard Worker }
48*eb293b8fSAndroid Build Coastguard Worker
set_sp(uint64_t sp)49*eb293b8fSAndroid Build Coastguard Worker void RegsX86::set_sp(uint64_t sp) {
50*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_SP] = static_cast<uint32_t>(sp);
51*eb293b8fSAndroid Build Coastguard Worker }
52*eb293b8fSAndroid Build Coastguard Worker
SetPcFromReturnAddress(Memory * process_memory)53*eb293b8fSAndroid Build Coastguard Worker bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
54*eb293b8fSAndroid Build Coastguard Worker // Attempt to get the return address from the top of the stack.
55*eb293b8fSAndroid Build Coastguard Worker uint32_t new_pc;
56*eb293b8fSAndroid Build Coastguard Worker if (!process_memory->ReadFully(regs_[X86_REG_SP], &new_pc, sizeof(new_pc)) ||
57*eb293b8fSAndroid Build Coastguard Worker new_pc == regs_[X86_REG_PC]) {
58*eb293b8fSAndroid Build Coastguard Worker return false;
59*eb293b8fSAndroid Build Coastguard Worker }
60*eb293b8fSAndroid Build Coastguard Worker
61*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_PC] = new_pc;
62*eb293b8fSAndroid Build Coastguard Worker return true;
63*eb293b8fSAndroid Build Coastguard Worker }
64*eb293b8fSAndroid Build Coastguard Worker
IterateRegisters(std::function<void (const char *,uint64_t)> fn)65*eb293b8fSAndroid Build Coastguard Worker void RegsX86::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
66*eb293b8fSAndroid Build Coastguard Worker fn("eax", regs_[X86_REG_EAX]);
67*eb293b8fSAndroid Build Coastguard Worker fn("ebx", regs_[X86_REG_EBX]);
68*eb293b8fSAndroid Build Coastguard Worker fn("ecx", regs_[X86_REG_ECX]);
69*eb293b8fSAndroid Build Coastguard Worker fn("edx", regs_[X86_REG_EDX]);
70*eb293b8fSAndroid Build Coastguard Worker fn("ebp", regs_[X86_REG_EBP]);
71*eb293b8fSAndroid Build Coastguard Worker fn("edi", regs_[X86_REG_EDI]);
72*eb293b8fSAndroid Build Coastguard Worker fn("esi", regs_[X86_REG_ESI]);
73*eb293b8fSAndroid Build Coastguard Worker fn("esp", regs_[X86_REG_ESP]);
74*eb293b8fSAndroid Build Coastguard Worker fn("eip", regs_[X86_REG_EIP]);
75*eb293b8fSAndroid Build Coastguard Worker }
76*eb293b8fSAndroid Build Coastguard Worker
Read(const void * user_data)77*eb293b8fSAndroid Build Coastguard Worker Regs* RegsX86::Read(const void* user_data) {
78*eb293b8fSAndroid Build Coastguard Worker const x86_user_regs* user = reinterpret_cast<const x86_user_regs*>(user_data);
79*eb293b8fSAndroid Build Coastguard Worker
80*eb293b8fSAndroid Build Coastguard Worker RegsX86* regs = new RegsX86();
81*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_EAX] = user->eax;
82*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_EBX] = user->ebx;
83*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_ECX] = user->ecx;
84*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_EDX] = user->edx;
85*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_EBP] = user->ebp;
86*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_EDI] = user->edi;
87*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_ESI] = user->esi;
88*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_ESP] = user->esp;
89*eb293b8fSAndroid Build Coastguard Worker (*regs)[X86_REG_EIP] = user->eip;
90*eb293b8fSAndroid Build Coastguard Worker
91*eb293b8fSAndroid Build Coastguard Worker return regs;
92*eb293b8fSAndroid Build Coastguard Worker }
93*eb293b8fSAndroid Build Coastguard Worker
SetFromUcontext(x86_ucontext_t * ucontext)94*eb293b8fSAndroid Build Coastguard Worker void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) {
95*eb293b8fSAndroid Build Coastguard Worker // Put the registers in the expected order.
96*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EDI] = ucontext->uc_mcontext.edi;
97*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_ESI] = ucontext->uc_mcontext.esi;
98*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EBP] = ucontext->uc_mcontext.ebp;
99*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_ESP] = ucontext->uc_mcontext.esp;
100*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EBX] = ucontext->uc_mcontext.ebx;
101*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EDX] = ucontext->uc_mcontext.edx;
102*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx;
103*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax;
104*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip;
105*eb293b8fSAndroid Build Coastguard Worker }
106*eb293b8fSAndroid Build Coastguard Worker
CreateFromUcontext(void * ucontext)107*eb293b8fSAndroid Build Coastguard Worker Regs* RegsX86::CreateFromUcontext(void* ucontext) {
108*eb293b8fSAndroid Build Coastguard Worker x86_ucontext_t* x86_ucontext = reinterpret_cast<x86_ucontext_t*>(ucontext);
109*eb293b8fSAndroid Build Coastguard Worker
110*eb293b8fSAndroid Build Coastguard Worker RegsX86* regs = new RegsX86();
111*eb293b8fSAndroid Build Coastguard Worker regs->SetFromUcontext(x86_ucontext);
112*eb293b8fSAndroid Build Coastguard Worker return regs;
113*eb293b8fSAndroid Build Coastguard Worker }
114*eb293b8fSAndroid Build Coastguard Worker
StepIfSignalHandler(uint64_t elf_offset,Elf * elf,Memory * process_memory)115*eb293b8fSAndroid Build Coastguard Worker bool RegsX86::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
116*eb293b8fSAndroid Build Coastguard Worker // Read from elf memory since it is usually more expensive to read from
117*eb293b8fSAndroid Build Coastguard Worker // process memory.
118*eb293b8fSAndroid Build Coastguard Worker uint64_t data;
119*eb293b8fSAndroid Build Coastguard Worker if (!elf->memory()->ReadFully(elf_offset, &data, sizeof(data))) {
120*eb293b8fSAndroid Build Coastguard Worker return false;
121*eb293b8fSAndroid Build Coastguard Worker }
122*eb293b8fSAndroid Build Coastguard Worker
123*eb293b8fSAndroid Build Coastguard Worker if (data == 0x80cd00000077b858ULL) {
124*eb293b8fSAndroid Build Coastguard Worker // Without SA_SIGINFO set, the return sequence is:
125*eb293b8fSAndroid Build Coastguard Worker //
126*eb293b8fSAndroid Build Coastguard Worker // __restore:
127*eb293b8fSAndroid Build Coastguard Worker // 0x58 pop %eax
128*eb293b8fSAndroid Build Coastguard Worker // 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
129*eb293b8fSAndroid Build Coastguard Worker // 0xcd 0x80 int 0x80
130*eb293b8fSAndroid Build Coastguard Worker //
131*eb293b8fSAndroid Build Coastguard Worker // SP points at arguments:
132*eb293b8fSAndroid Build Coastguard Worker // int signum
133*eb293b8fSAndroid Build Coastguard Worker // struct sigcontext (same format as mcontext)
134*eb293b8fSAndroid Build Coastguard Worker struct x86_mcontext_t context;
135*eb293b8fSAndroid Build Coastguard Worker if (!process_memory->ReadFully(regs_[X86_REG_SP] + 4, &context, sizeof(context))) {
136*eb293b8fSAndroid Build Coastguard Worker return false;
137*eb293b8fSAndroid Build Coastguard Worker }
138*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EBP] = context.ebp;
139*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_ESP] = context.esp;
140*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EBX] = context.ebx;
141*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EDX] = context.edx;
142*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_ECX] = context.ecx;
143*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EAX] = context.eax;
144*eb293b8fSAndroid Build Coastguard Worker regs_[X86_REG_EIP] = context.eip;
145*eb293b8fSAndroid Build Coastguard Worker return true;
146*eb293b8fSAndroid Build Coastguard Worker } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) {
147*eb293b8fSAndroid Build Coastguard Worker // With SA_SIGINFO set, the return sequence is:
148*eb293b8fSAndroid Build Coastguard Worker //
149*eb293b8fSAndroid Build Coastguard Worker // __restore_rt:
150*eb293b8fSAndroid Build Coastguard Worker // 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
151*eb293b8fSAndroid Build Coastguard Worker // 0xcd 0x80 int 0x80
152*eb293b8fSAndroid Build Coastguard Worker //
153*eb293b8fSAndroid Build Coastguard Worker // SP points at arguments:
154*eb293b8fSAndroid Build Coastguard Worker // int signum
155*eb293b8fSAndroid Build Coastguard Worker // siginfo*
156*eb293b8fSAndroid Build Coastguard Worker // ucontext*
157*eb293b8fSAndroid Build Coastguard Worker
158*eb293b8fSAndroid Build Coastguard Worker // Get the location of the sigcontext data.
159*eb293b8fSAndroid Build Coastguard Worker uint32_t ptr;
160*eb293b8fSAndroid Build Coastguard Worker if (!process_memory->ReadFully(regs_[X86_REG_SP] + 8, &ptr, sizeof(ptr))) {
161*eb293b8fSAndroid Build Coastguard Worker return false;
162*eb293b8fSAndroid Build Coastguard Worker }
163*eb293b8fSAndroid Build Coastguard Worker // Only read the portion of the data structure we care about.
164*eb293b8fSAndroid Build Coastguard Worker x86_ucontext_t x86_ucontext;
165*eb293b8fSAndroid Build Coastguard Worker if (!process_memory->ReadFully(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
166*eb293b8fSAndroid Build Coastguard Worker return false;
167*eb293b8fSAndroid Build Coastguard Worker }
168*eb293b8fSAndroid Build Coastguard Worker SetFromUcontext(&x86_ucontext);
169*eb293b8fSAndroid Build Coastguard Worker return true;
170*eb293b8fSAndroid Build Coastguard Worker }
171*eb293b8fSAndroid Build Coastguard Worker return false;
172*eb293b8fSAndroid Build Coastguard Worker }
173*eb293b8fSAndroid Build Coastguard Worker
Clone()174*eb293b8fSAndroid Build Coastguard Worker Regs* RegsX86::Clone() {
175*eb293b8fSAndroid Build Coastguard Worker return new RegsX86(*this);
176*eb293b8fSAndroid Build Coastguard Worker }
177*eb293b8fSAndroid Build Coastguard Worker
178*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
179