summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Ferris2018-03-19 12:48:59 -0500
committerGerrit Code Review2018-03-19 12:48:59 -0500
commitb22451f178ff063fb99391cc9f7b089394a3018b (patch)
treef31e25b3f6138f385a82bcbe8664ce368ef37a65 /libunwindstack
parente8d1b75c0c9384d476dd929b7215d9d121775081 (diff)
parent11e96fe48a74e6ab97d4de899684d3a61a9d1129 (diff)
downloadplatform-system-core-b22451f178ff063fb99391cc9f7b089394a3018b.tar.gz
platform-system-core-b22451f178ff063fb99391cc9f7b089394a3018b.tar.xz
platform-system-core-b22451f178ff063fb99391cc9f7b089394a3018b.zip
Merge "Always set the sp reg to the cfa for DWARF."
Diffstat (limited to 'libunwindstack')
-rw-r--r--libunwindstack/Android.bp1
-rw-r--r--libunwindstack/DwarfSection.cpp11
-rw-r--r--libunwindstack/ElfInterfaceArm.cpp8
-rw-r--r--libunwindstack/RegsArm.cpp48
-rw-r--r--libunwindstack/RegsArm64.cpp34
-rw-r--r--libunwindstack/RegsMips.cpp34
-rw-r--r--libunwindstack/RegsMips64.cpp39
-rw-r--r--libunwindstack/RegsX86.cpp36
-rw-r--r--libunwindstack/RegsX86_64.cpp34
-rw-r--r--libunwindstack/include/unwindstack/Regs.h23
-rw-r--r--libunwindstack/include/unwindstack/RegsArm.h12
-rw-r--r--libunwindstack/include/unwindstack/RegsArm64.h12
-rw-r--r--libunwindstack/include/unwindstack/RegsGetLocal.h6
-rw-r--r--libunwindstack/include/unwindstack/RegsMips.h12
-rw-r--r--libunwindstack/include/unwindstack/RegsMips64.h12
-rw-r--r--libunwindstack/include/unwindstack/RegsX86.h12
-rw-r--r--libunwindstack/include/unwindstack/RegsX86_64.h12
-rw-r--r--libunwindstack/tests/DwarfOpTest.cpp6
-rw-r--r--libunwindstack/tests/DwarfSectionImplTest.cpp44
-rw-r--r--libunwindstack/tests/ElfFake.cpp4
-rw-r--r--libunwindstack/tests/ElfTest.cpp1
-rw-r--r--libunwindstack/tests/RegsFake.h24
-rw-r--r--libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp9
-rw-r--r--libunwindstack/tests/RegsTest.cpp24
-rw-r--r--libunwindstack/tests/UnwindOfflineTest.cpp116
-rw-r--r--libunwindstack/tests/UnwinderTest.cpp78
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.databin0 -> 24 bytes
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.databin0 -> 32 bytes
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.databin0 -> 32 bytes
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.databin0 -> 624 bytes
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.databin0 -> 612 bytes
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.sobin0 -> 6095540 bytes
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.sobin0 -> 841140 bytes
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt3
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt16
-rw-r--r--libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.databin0 -> 61080 bytes
36 files changed, 417 insertions, 254 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 87172836b..08dcf7724 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -188,6 +188,7 @@ cc_test {
188 data: [ 188 data: [
189 "tests/files/elf32.xz", 189 "tests/files/elf32.xz",
190 "tests/files/elf64.xz", 190 "tests/files/elf64.xz",
191 "tests/files/offline/art_quick_osr_stub_arm/*",
191 "tests/files/offline/bad_eh_frame_hdr_arm64/*", 192 "tests/files/offline/bad_eh_frame_hdr_arm64/*",
192 "tests/files/offline/debug_frame_first_x86/*", 193 "tests/files/offline/debug_frame_first_x86/*",
193 "tests/files/offline/eh_frame_hdr_begin_x86_64/*", 194 "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index ddbc12ef4..5586e725d 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -190,8 +190,6 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
190 // Always set the dex pc to zero when evaluating. 190 // Always set the dex pc to zero when evaluating.
191 cur_regs->set_dex_pc(0); 191 cur_regs->set_dex_pc(0);
192 192
193 AddressType prev_cfa = regs->sp();
194
195 EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs, 193 EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
196 .cie = cie, 194 .cie = cie,
197 .regular_memory = regular_memory, 195 .regular_memory = regular_memory,
@@ -204,14 +202,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
204 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 202 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
205 return false; 203 return false;
206 } 204 }
207 // If the stack pointer register is the CFA, and the stack 205 eval_info.cfa = (*cur_regs)[loc->values[0]];
208 // pointer register does not have any associated location
209 // information, use the current cfa value.
210 if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
211 eval_info.cfa = prev_cfa;
212 } else {
213 eval_info.cfa = (*cur_regs)[loc->values[0]];
214 }
215 eval_info.cfa += loc->values[1]; 206 eval_info.cfa += loc->values[1];
216 break; 207 break;
217 case DWARF_LOCATION_VAL_EXPRESSION: { 208 case DWARF_LOCATION_VAL_EXPRESSION: {
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index a5afc7e5d..f93baeb27 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -127,13 +127,9 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Mem
127 if (arm.ExtractEntryData(entry_offset) && arm.Eval()) { 127 if (arm.ExtractEntryData(entry_offset) && arm.Eval()) {
128 // If the pc was not set, then use the LR registers for the PC. 128 // If the pc was not set, then use the LR registers for the PC.
129 if (!arm.pc_set()) { 129 if (!arm.pc_set()) {
130 regs_arm->set_pc((*regs_arm)[ARM_REG_LR]); 130 (*regs_arm)[ARM_REG_PC] = (*regs_arm)[ARM_REG_LR];
131 (*regs_arm)[ARM_REG_PC] = regs_arm->pc();
132 } else {
133 regs_arm->set_pc((*regs_arm)[ARM_REG_PC]);
134 } 131 }
135 regs_arm->set_sp(arm.cfa()); 132 (*regs_arm)[ARM_REG_SP] = arm.cfa();
136 (*regs_arm)[ARM_REG_SP] = regs_arm->sp();
137 return_value = true; 133 return_value = true;
138 134
139 // If the pc was set to zero, consider this the final frame. 135 // If the pc was set to zero, consider this the final frame.
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index 5502ce1fe..e2a9cb01f 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -28,13 +28,28 @@
28 28
29namespace unwindstack { 29namespace unwindstack {
30 30
31RegsArm::RegsArm() 31RegsArm::RegsArm() : RegsImpl<uint32_t>(ARM_REG_LAST, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
32 : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
33 32
34ArchEnum RegsArm::Arch() { 33ArchEnum RegsArm::Arch() {
35 return ARCH_ARM; 34 return ARCH_ARM;
36} 35}
37 36
37uint64_t RegsArm::pc() {
38 return regs_[ARM_REG_PC];
39}
40
41uint64_t RegsArm::sp() {
42 return regs_[ARM_REG_SP];
43}
44
45void RegsArm::set_pc(uint64_t pc) {
46 regs_[ARM_REG_PC] = pc;
47}
48
49void RegsArm::set_sp(uint64_t sp) {
50 regs_[ARM_REG_SP] = sp;
51}
52
38uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { 53uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 uint64_t load_bias = elf->GetLoadBias(); 54 uint64_t load_bias = elf->GetLoadBias();
40 if (rel_pc < load_bias) { 55 if (rel_pc < load_bias) {
@@ -56,17 +71,13 @@ uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
56 return 4; 71 return 4;
57} 72}
58 73
59void RegsArm::SetFromRaw() {
60 set_pc(regs_[ARM_REG_PC]);
61 set_sp(regs_[ARM_REG_SP]);
62}
63
64bool RegsArm::SetPcFromReturnAddress(Memory*) { 74bool RegsArm::SetPcFromReturnAddress(Memory*) {
65 if (pc() == regs_[ARM_REG_LR]) { 75 uint32_t lr = regs_[ARM_REG_LR];
76 if (regs_[ARM_REG_PC] == lr) {
66 return false; 77 return false;
67 } 78 }
68 79
69 set_pc(regs_[ARM_REG_LR]); 80 regs_[ARM_REG_PC] = lr;
70 return true; 81 return true;
71} 82}
72 83
@@ -94,7 +105,6 @@ Regs* RegsArm::Read(void* remote_data) {
94 105
95 RegsArm* regs = new RegsArm(); 106 RegsArm* regs = new RegsArm();
96 memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t)); 107 memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
97 regs->SetFromRaw();
98 return regs; 108 return regs;
99} 109}
100 110
@@ -103,7 +113,6 @@ Regs* RegsArm::CreateFromUcontext(void* ucontext) {
103 113
104 RegsArm* regs = new RegsArm(); 114 RegsArm* regs = new RegsArm();
105 memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t)); 115 memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
106 regs->SetFromRaw();
107 return regs; 116 return regs;
108} 117}
109 118
@@ -118,6 +127,7 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
118 127
119 uint64_t offset = 0; 128 uint64_t offset = 0;
120 if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) { 129 if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
130 uint64_t sp = regs_[ARM_REG_SP];
121 // non-RT sigreturn call. 131 // non-RT sigreturn call.
122 // __restore: 132 // __restore:
123 // 133 //
@@ -131,17 +141,18 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
131 // Form 3 (thumb): 141 // Form 3 (thumb):
132 // 0x77 0x27 movs r7, #77 142 // 0x77 0x27 movs r7, #77
133 // 0x00 0xdf svc 0 143 // 0x00 0xdf svc 0
134 if (!process_memory->ReadFully(sp(), &data, sizeof(data))) { 144 if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
135 return false; 145 return false;
136 } 146 }
137 if (data == 0x5ac3c35a) { 147 if (data == 0x5ac3c35a) {
138 // SP + uc_mcontext offset + r0 offset. 148 // SP + uc_mcontext offset + r0 offset.
139 offset = sp() + 0x14 + 0xc; 149 offset = sp + 0x14 + 0xc;
140 } else { 150 } else {
141 // SP + r0 offset 151 // SP + r0 offset
142 offset = sp() + 0xc; 152 offset = sp + 0xc;
143 } 153 }
144 } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) { 154 } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
155 uint64_t sp = regs_[ARM_REG_SP];
145 // RT sigreturn call. 156 // RT sigreturn call.
146 // __restore_rt: 157 // __restore_rt:
147 // 158 //
@@ -155,15 +166,15 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
155 // Form 3 (thumb): 166 // Form 3 (thumb):
156 // 0xad 0x27 movs r7, #ad 167 // 0xad 0x27 movs r7, #ad
157 // 0x00 0xdf svc 0 168 // 0x00 0xdf svc 0
158 if (!process_memory->ReadFully(sp(), &data, sizeof(data))) { 169 if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
159 return false; 170 return false;
160 } 171 }
161 if (data == sp() + 8) { 172 if (data == sp + 8) {
162 // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset 173 // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
163 offset = sp() + 8 + 0x80 + 0x14 + 0xc; 174 offset = sp + 8 + 0x80 + 0x14 + 0xc;
164 } else { 175 } else {
165 // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset 176 // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
166 offset = sp() + 0x80 + 0x14 + 0xc; 177 offset = sp + 0x80 + 0x14 + 0xc;
167 } 178 }
168 } 179 }
169 if (offset == 0) { 180 if (offset == 0) {
@@ -173,7 +184,6 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
173 if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) { 184 if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
174 return false; 185 return false;
175 } 186 }
176 SetFromRaw();
177 return true; 187 return true;
178} 188}
179 189
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index cc6f5ce87..fe24c802c 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -29,12 +29,28 @@
29namespace unwindstack { 29namespace unwindstack {
30 30
31RegsArm64::RegsArm64() 31RegsArm64::RegsArm64()
32 : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {} 32 : RegsImpl<uint64_t>(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
33 33
34ArchEnum RegsArm64::Arch() { 34ArchEnum RegsArm64::Arch() {
35 return ARCH_ARM64; 35 return ARCH_ARM64;
36} 36}
37 37
38uint64_t RegsArm64::pc() {
39 return regs_[ARM64_REG_PC];
40}
41
42uint64_t RegsArm64::sp() {
43 return regs_[ARM64_REG_SP];
44}
45
46void RegsArm64::set_pc(uint64_t pc) {
47 regs_[ARM64_REG_PC] = pc;
48}
49
50void RegsArm64::set_sp(uint64_t sp) {
51 regs_[ARM64_REG_SP] = sp;
52}
53
38uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { 54uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid() || rel_pc < 4) { 55 if (!elf->valid() || rel_pc < 4) {
40 return 0; 56 return 0;
@@ -42,17 +58,13 @@ uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
42 return 4; 58 return 4;
43} 59}
44 60
45void RegsArm64::SetFromRaw() {
46 set_pc(regs_[ARM64_REG_PC]);
47 set_sp(regs_[ARM64_REG_SP]);
48}
49
50bool RegsArm64::SetPcFromReturnAddress(Memory*) { 61bool RegsArm64::SetPcFromReturnAddress(Memory*) {
51 if (pc() == regs_[ARM64_REG_LR]) { 62 uint64_t lr = regs_[ARM64_REG_LR];
63 if (regs_[ARM64_REG_PC] == lr) {
52 return false; 64 return false;
53 } 65 }
54 66
55 set_pc(regs_[ARM64_REG_LR]); 67 regs_[ARM64_REG_PC] = lr;
56 return true; 68 return true;
57} 69}
58 70
@@ -100,7 +112,6 @@ Regs* RegsArm64::Read(void* remote_data) {
100 uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData()); 112 uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
101 reg_data[ARM64_REG_PC] = user->pc; 113 reg_data[ARM64_REG_PC] = user->pc;
102 reg_data[ARM64_REG_SP] = user->sp; 114 reg_data[ARM64_REG_SP] = user->sp;
103 regs->SetFromRaw();
104 return regs; 115 return regs;
105} 116}
106 117
@@ -109,7 +120,6 @@ Regs* RegsArm64::CreateFromUcontext(void* ucontext) {
109 120
110 RegsArm64* regs = new RegsArm64(); 121 RegsArm64* regs = new RegsArm64();
111 memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t)); 122 memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
112 regs->SetFromRaw();
113 return regs; 123 return regs;
114} 124}
115 125
@@ -131,12 +141,10 @@ bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_m
131 } 141 }
132 142
133 // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset. 143 // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
134 if (!process_memory->ReadFully(sp() + 0x80 + 0xb0 + 0x08, regs_.data(), 144 if (!process_memory->ReadFully(regs_[ARM64_REG_SP] + 0x80 + 0xb0 + 0x08, regs_.data(),
135 sizeof(uint64_t) * ARM64_REG_LAST)) { 145 sizeof(uint64_t) * ARM64_REG_LAST)) {
136 return false; 146 return false;
137 } 147 }
138
139 SetFromRaw();
140 return true; 148 return true;
141} 149}
142 150
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 5d20bef4a..0b10e2169 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -29,12 +29,28 @@
29namespace unwindstack { 29namespace unwindstack {
30 30
31RegsMips::RegsMips() 31RegsMips::RegsMips()
32 : RegsImpl<uint32_t>(MIPS_REG_LAST, MIPS_REG_SP, Location(LOCATION_REGISTER, MIPS_REG_RA)) {} 32 : RegsImpl<uint32_t>(MIPS_REG_LAST, Location(LOCATION_REGISTER, MIPS_REG_RA)) {}
33 33
34ArchEnum RegsMips::Arch() { 34ArchEnum RegsMips::Arch() {
35 return ARCH_MIPS; 35 return ARCH_MIPS;
36} 36}
37 37
38uint64_t RegsMips::pc() {
39 return regs_[MIPS_REG_PC];
40}
41
42uint64_t RegsMips::sp() {
43 return regs_[MIPS_REG_SP];
44}
45
46void RegsMips::set_pc(uint64_t pc) {
47 regs_[MIPS_REG_PC] = static_cast<uint32_t>(pc);
48}
49
50void RegsMips::set_sp(uint64_t sp) {
51 regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp);
52}
53
38uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { 54uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid() || rel_pc < 8) { 55 if (!elf->valid() || rel_pc < 8) {
40 return 0; 56 return 0;
@@ -43,17 +59,13 @@ uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
43 return 8; 59 return 8;
44} 60}
45 61
46void RegsMips::SetFromRaw() {
47 set_pc(regs_[MIPS_REG_PC]);
48 set_sp(regs_[MIPS_REG_SP]);
49}
50
51bool RegsMips::SetPcFromReturnAddress(Memory*) { 62bool RegsMips::SetPcFromReturnAddress(Memory*) {
52 if (pc() == regs_[MIPS_REG_RA]) { 63 uint32_t ra = regs_[MIPS_REG_RA];
64 if (regs_[MIPS_REG_PC] == ra) {
53 return false; 65 return false;
54 } 66 }
55 67
56 set_pc(regs_[MIPS_REG_RA]); 68 regs_[MIPS_REG_PC] = ra;
57 return true; 69 return true;
58} 70}
59 71
@@ -101,7 +113,6 @@ Regs* RegsMips::Read(void* remote_data) {
101 memcpy(regs->RawData(), &user->regs[MIPS32_EF_R0], (MIPS_REG_R31 + 1) * sizeof(uint32_t)); 113 memcpy(regs->RawData(), &user->regs[MIPS32_EF_R0], (MIPS_REG_R31 + 1) * sizeof(uint32_t));
102 114
103 reg_data[MIPS_REG_PC] = user->regs[MIPS32_EF_CP0_EPC]; 115 reg_data[MIPS_REG_PC] = user->regs[MIPS32_EF_CP0_EPC];
104 regs->SetFromRaw();
105 return regs; 116 return regs;
106} 117}
107 118
@@ -114,7 +125,6 @@ Regs* RegsMips::CreateFromUcontext(void* ucontext) {
114 (*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i]; 125 (*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i];
115 } 126 }
116 (*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc; 127 (*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc;
117 regs->SetFromRaw();
118 return regs; 128 return regs;
119} 129}
120 130
@@ -149,7 +159,7 @@ bool RegsMips::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_me
149 159
150 // read sc_pc and sc_regs[32] from stack 160 // read sc_pc and sc_regs[32] from stack
151 uint64_t values[MIPS_REG_LAST]; 161 uint64_t values[MIPS_REG_LAST];
152 if (!process_memory->Read(sp() + offset, values, sizeof(values))) { 162 if (!process_memory->Read(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
153 return false; 163 return false;
154 } 164 }
155 165
@@ -160,8 +170,6 @@ bool RegsMips::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_me
160 for (int i = 0; i < 32; i++) { 170 for (int i = 0; i < 32; i++) {
161 regs_[MIPS_REG_R0 + i] = values[1 + i]; 171 regs_[MIPS_REG_R0 + i] = values[1 + i];
162 } 172 }
163
164 SetFromRaw();
165 return true; 173 return true;
166} 174}
167 175
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 4a03538e2..8848e3bab 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -29,13 +29,28 @@
29namespace unwindstack { 29namespace unwindstack {
30 30
31RegsMips64::RegsMips64() 31RegsMips64::RegsMips64()
32 : RegsImpl<uint64_t>(MIPS64_REG_LAST, MIPS64_REG_SP, 32 : RegsImpl<uint64_t>(MIPS64_REG_LAST, Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}
33 Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}
34 33
35ArchEnum RegsMips64::Arch() { 34ArchEnum RegsMips64::Arch() {
36 return ARCH_MIPS64; 35 return ARCH_MIPS64;
37} 36}
38 37
38uint64_t RegsMips64::pc() {
39 return regs_[MIPS64_REG_PC];
40}
41
42uint64_t RegsMips64::sp() {
43 return regs_[MIPS64_REG_SP];
44}
45
46void RegsMips64::set_pc(uint64_t pc) {
47 regs_[MIPS64_REG_PC] = pc;
48}
49
50void RegsMips64::set_sp(uint64_t sp) {
51 regs_[MIPS64_REG_SP] = sp;
52}
53
39uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { 54uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
40 if (!elf->valid() || rel_pc < 8) { 55 if (!elf->valid() || rel_pc < 8) {
41 return 0; 56 return 0;
@@ -44,17 +59,13 @@ uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
44 return 8; 59 return 8;
45} 60}
46 61
47void RegsMips64::SetFromRaw() {
48 set_pc(regs_[MIPS64_REG_PC]);
49 set_sp(regs_[MIPS64_REG_SP]);
50}
51
52bool RegsMips64::SetPcFromReturnAddress(Memory*) { 62bool RegsMips64::SetPcFromReturnAddress(Memory*) {
53 if (pc() == regs_[MIPS64_REG_RA]) { 63 uint64_t ra = regs_[MIPS64_REG_RA];
64 if (regs_[MIPS64_REG_PC] == ra) {
54 return false; 65 return false;
55 } 66 }
56 67
57 set_pc(regs_[MIPS64_REG_RA]); 68 regs_[MIPS64_REG_PC] = ra;
58 return true; 69 return true;
59} 70}
60 71
@@ -102,7 +113,6 @@ Regs* RegsMips64::Read(void* remote_data) {
102 memcpy(regs->RawData(), &user->regs[MIPS64_EF_R0], (MIPS64_REG_R31 + 1) * sizeof(uint64_t)); 113 memcpy(regs->RawData(), &user->regs[MIPS64_EF_R0], (MIPS64_REG_R31 + 1) * sizeof(uint64_t));
103 114
104 reg_data[MIPS64_REG_PC] = user->regs[MIPS64_EF_CP0_EPC]; 115 reg_data[MIPS64_REG_PC] = user->regs[MIPS64_EF_CP0_EPC];
105 regs->SetFromRaw();
106 return regs; 116 return regs;
107} 117}
108 118
@@ -113,7 +123,6 @@ Regs* RegsMips64::CreateFromUcontext(void* ucontext) {
113 // Copy 64 bit sc_regs over to 64 bit regs 123 // Copy 64 bit sc_regs over to 64 bit regs
114 memcpy(regs->RawData(), &mips64_ucontext->uc_mcontext.sc_regs[0], 32 * sizeof(uint64_t)); 124 memcpy(regs->RawData(), &mips64_ucontext->uc_mcontext.sc_regs[0], 32 * sizeof(uint64_t));
115 (*regs)[MIPS64_REG_PC] = mips64_ucontext->uc_mcontext.sc_pc; 125 (*regs)[MIPS64_REG_PC] = mips64_ucontext->uc_mcontext.sc_pc;
116 regs->SetFromRaw();
117 return regs; 126 return regs;
118} 127}
119 128
@@ -137,19 +146,17 @@ bool RegsMips64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_
137 // vdso_rt_sigreturn => read rt_sigframe 146 // vdso_rt_sigreturn => read rt_sigframe
138 // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset 147 // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset
139 // read 64 bit sc_regs[32] from stack into 64 bit regs_ 148 // read 64 bit sc_regs[32] from stack into 64 bit regs_
140 if (!process_memory->Read(sp() + 24 + 128 + 40, regs_.data(), 149 uint64_t sp = regs_[MIPS64_REG_SP];
150 if (!process_memory->Read(sp + 24 + 128 + 40, regs_.data(),
141 sizeof(uint64_t) * (MIPS64_REG_LAST - 1))) { 151 sizeof(uint64_t) * (MIPS64_REG_LAST - 1))) {
142 return false; 152 return false;
143 } 153 }
144 154
145 // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset 155 // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
146 // read 64 bit sc_pc from stack into 64 bit regs_[MIPS64_REG_PC] 156 // read 64 bit sc_pc from stack into 64 bit regs_[MIPS64_REG_PC]
147 if (!process_memory->Read(sp() + 24 + 128 + 40 + 576, &regs_[MIPS64_REG_PC], 157 if (!process_memory->Read(sp + 24 + 128 + 40 + 576, &regs_[MIPS64_REG_PC], sizeof(uint64_t))) {
148 sizeof(uint64_t))) {
149 return false; 158 return false;
150 } 159 }
151
152 SetFromRaw();
153 return true; 160 return true;
154} 161}
155 162
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index 573cb2382..bb95a13f2 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -28,13 +28,28 @@
28 28
29namespace unwindstack { 29namespace unwindstack {
30 30
31RegsX86::RegsX86() 31RegsX86::RegsX86() : RegsImpl<uint32_t>(X86_REG_LAST, Location(LOCATION_SP_OFFSET, -4)) {}
32 : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
33 32
34ArchEnum RegsX86::Arch() { 33ArchEnum RegsX86::Arch() {
35 return ARCH_X86; 34 return ARCH_X86;
36} 35}
37 36
37uint64_t RegsX86::pc() {
38 return regs_[X86_REG_PC];
39}
40
41uint64_t RegsX86::sp() {
42 return regs_[X86_REG_SP];
43}
44
45void RegsX86::set_pc(uint64_t pc) {
46 regs_[X86_REG_PC] = static_cast<uint32_t>(pc);
47}
48
49void RegsX86::set_sp(uint64_t sp) {
50 regs_[X86_REG_SP] = static_cast<uint32_t>(sp);
51}
52
38uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { 53uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid() || rel_pc == 0) { 54 if (!elf->valid() || rel_pc == 0) {
40 return 0; 55 return 0;
@@ -42,19 +57,15 @@ uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
42 return 1; 57 return 1;
43} 58}
44 59
45void RegsX86::SetFromRaw() {
46 set_pc(regs_[X86_REG_PC]);
47 set_sp(regs_[X86_REG_SP]);
48}
49
50bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) { 60bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
51 // Attempt to get the return address from the top of the stack. 61 // Attempt to get the return address from the top of the stack.
52 uint32_t new_pc; 62 uint32_t new_pc;
53 if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) { 63 if (!process_memory->ReadFully(regs_[X86_REG_SP], &new_pc, sizeof(new_pc)) ||
64 new_pc == regs_[X86_REG_PC]) {
54 return false; 65 return false;
55 } 66 }
56 67
57 set_pc(new_pc); 68 regs_[X86_REG_PC] = new_pc;
58 return true; 69 return true;
59} 70}
60 71
@@ -84,7 +95,6 @@ Regs* RegsX86::Read(void* user_data) {
84 (*regs)[X86_REG_ESP] = user->esp; 95 (*regs)[X86_REG_ESP] = user->esp;
85 (*regs)[X86_REG_EIP] = user->eip; 96 (*regs)[X86_REG_EIP] = user->eip;
86 97
87 regs->SetFromRaw();
88 return regs; 98 return regs;
89} 99}
90 100
@@ -99,7 +109,6 @@ void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) {
99 regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx; 109 regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx;
100 regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax; 110 regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax;
101 regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip; 111 regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip;
102 SetFromRaw();
103} 112}
104 113
105Regs* RegsX86::CreateFromUcontext(void* ucontext) { 114Regs* RegsX86::CreateFromUcontext(void* ucontext) {
@@ -131,7 +140,7 @@ bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
131 // int signum 140 // int signum
132 // struct sigcontext (same format as mcontext) 141 // struct sigcontext (same format as mcontext)
133 struct x86_mcontext_t context; 142 struct x86_mcontext_t context;
134 if (!process_memory->ReadFully(sp() + 4, &context, sizeof(context))) { 143 if (!process_memory->ReadFully(regs_[X86_REG_SP] + 4, &context, sizeof(context))) {
135 return false; 144 return false;
136 } 145 }
137 regs_[X86_REG_EBP] = context.ebp; 146 regs_[X86_REG_EBP] = context.ebp;
@@ -141,7 +150,6 @@ bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
141 regs_[X86_REG_ECX] = context.ecx; 150 regs_[X86_REG_ECX] = context.ecx;
142 regs_[X86_REG_EAX] = context.eax; 151 regs_[X86_REG_EAX] = context.eax;
143 regs_[X86_REG_EIP] = context.eip; 152 regs_[X86_REG_EIP] = context.eip;
144 SetFromRaw();
145 return true; 153 return true;
146 } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) { 154 } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) {
147 // With SA_SIGINFO set, the return sequence is: 155 // With SA_SIGINFO set, the return sequence is:
@@ -157,7 +165,7 @@ bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
157 165
158 // Get the location of the sigcontext data. 166 // Get the location of the sigcontext data.
159 uint32_t ptr; 167 uint32_t ptr;
160 if (!process_memory->ReadFully(sp() + 8, &ptr, sizeof(ptr))) { 168 if (!process_memory->ReadFully(regs_[X86_REG_SP] + 8, &ptr, sizeof(ptr))) {
161 return false; 169 return false;
162 } 170 }
163 // Only read the portion of the data structure we care about. 171 // Only read the portion of the data structure we care about.
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 3175a90c2..e57e2bca1 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -28,13 +28,28 @@
28 28
29namespace unwindstack { 29namespace unwindstack {
30 30
31RegsX86_64::RegsX86_64() 31RegsX86_64::RegsX86_64() : RegsImpl<uint64_t>(X86_64_REG_LAST, Location(LOCATION_SP_OFFSET, -8)) {}
32 : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
33 32
34ArchEnum RegsX86_64::Arch() { 33ArchEnum RegsX86_64::Arch() {
35 return ARCH_X86_64; 34 return ARCH_X86_64;
36} 35}
37 36
37uint64_t RegsX86_64::pc() {
38 return regs_[X86_64_REG_PC];
39}
40
41uint64_t RegsX86_64::sp() {
42 return regs_[X86_64_REG_SP];
43}
44
45void RegsX86_64::set_pc(uint64_t pc) {
46 regs_[X86_64_REG_PC] = pc;
47}
48
49void RegsX86_64::set_sp(uint64_t sp) {
50 regs_[X86_64_REG_SP] = sp;
51}
52
38uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { 53uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid() || rel_pc == 0) { 54 if (!elf->valid() || rel_pc == 0) {
40 return 0; 55 return 0;
@@ -42,19 +57,15 @@ uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
42 return 1; 57 return 1;
43} 58}
44 59
45void RegsX86_64::SetFromRaw() {
46 set_pc(regs_[X86_64_REG_PC]);
47 set_sp(regs_[X86_64_REG_SP]);
48}
49
50bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) { 60bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
51 // Attempt to get the return address from the top of the stack. 61 // Attempt to get the return address from the top of the stack.
52 uint64_t new_pc; 62 uint64_t new_pc;
53 if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) { 63 if (!process_memory->ReadFully(regs_[X86_64_REG_SP], &new_pc, sizeof(new_pc)) ||
64 new_pc == regs_[X86_64_REG_PC]) {
54 return false; 65 return false;
55 } 66 }
56 67
57 set_pc(new_pc); 68 regs_[X86_64_REG_PC] = new_pc;
58 return true; 69 return true;
59} 70}
60 71
@@ -100,7 +111,6 @@ Regs* RegsX86_64::Read(void* remote_data) {
100 (*regs)[X86_64_REG_RSP] = user->rsp; 111 (*regs)[X86_64_REG_RSP] = user->rsp;
101 (*regs)[X86_64_REG_RIP] = user->rip; 112 (*regs)[X86_64_REG_RIP] = user->rip;
102 113
103 regs->SetFromRaw();
104 return regs; 114 return regs;
105} 115}
106 116
@@ -118,8 +128,6 @@ void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
118 regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx; 128 regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
119 regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp; 129 regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
120 regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip; 130 regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
121
122 SetFromRaw();
123} 131}
124 132
125Regs* RegsX86_64::CreateFromUcontext(void* ucontext) { 133Regs* RegsX86_64::CreateFromUcontext(void* ucontext) {
@@ -152,7 +160,7 @@ bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_
152 // Read the mcontext data from the stack. 160 // Read the mcontext data from the stack.
153 // sp points to the ucontext data structure, read only the mcontext part. 161 // sp points to the ucontext data structure, read only the mcontext part.
154 x86_64_ucontext_t x86_64_ucontext; 162 x86_64_ucontext_t x86_64_ucontext;
155 if (!process_memory->ReadFully(sp() + 0x28, &x86_64_ucontext.uc_mcontext, 163 if (!process_memory->ReadFully(regs_[X86_64_REG_SP] + 0x28, &x86_64_ucontext.uc_mcontext,
156 sizeof(x86_64_mcontext_t))) { 164 sizeof(x86_64_mcontext_t))) {
157 return false; 165 return false;
158 } 166 }
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index b0e7ea152..4bac47313 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -45,8 +45,8 @@ class Regs {
45 int16_t value; 45 int16_t value;
46 }; 46 };
47 47
48 Regs(uint16_t total_regs, uint16_t sp_reg, const Location& return_loc) 48 Regs(uint16_t total_regs, const Location& return_loc)
49 : total_regs_(total_regs), sp_reg_(sp_reg), return_loc_(return_loc) {} 49 : total_regs_(total_regs), return_loc_(return_loc) {}
50 virtual ~Regs() = default; 50 virtual ~Regs() = default;
51 51
52 virtual ArchEnum Arch() = 0; 52 virtual ArchEnum Arch() = 0;
@@ -57,6 +57,9 @@ class Regs {
57 virtual uint64_t pc() = 0; 57 virtual uint64_t pc() = 0;
58 virtual uint64_t sp() = 0; 58 virtual uint64_t sp() = 0;
59 59
60 virtual void set_pc(uint64_t pc) = 0;
61 virtual void set_sp(uint64_t sp) = 0;
62
60 uint64_t dex_pc() { return dex_pc_; } 63 uint64_t dex_pc() { return dex_pc_; }
61 void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; } 64 void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
62 65
@@ -64,13 +67,10 @@ class Regs {
64 67
65 virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0; 68 virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
66 69
67 virtual void SetFromRaw() = 0;
68
69 virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0; 70 virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
70 71
71 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0; 72 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0;
72 73
73 uint16_t sp_reg() { return sp_reg_; }
74 uint16_t total_regs() { return total_regs_; } 74 uint16_t total_regs() { return total_regs_; }
75 75
76 static ArchEnum CurrentArch(); 76 static ArchEnum CurrentArch();
@@ -80,7 +80,6 @@ class Regs {
80 80
81 protected: 81 protected:
82 uint16_t total_regs_; 82 uint16_t total_regs_;
83 uint16_t sp_reg_;
84 Location return_loc_; 83 Location return_loc_;
85 uint64_t dex_pc_ = 0; 84 uint64_t dex_pc_ = 0;
86}; 85};
@@ -88,16 +87,10 @@ class Regs {
88template <typename AddressType> 87template <typename AddressType>
89class RegsImpl : public Regs { 88class RegsImpl : public Regs {
90 public: 89 public:
91 RegsImpl(uint16_t total_regs, uint16_t sp_reg, Location return_loc) 90 RegsImpl(uint16_t total_regs, Location return_loc)
92 : Regs(total_regs, sp_reg, return_loc), regs_(total_regs) {} 91 : Regs(total_regs, return_loc), regs_(total_regs) {}
93 virtual ~RegsImpl() = default; 92 virtual ~RegsImpl() = default;
94 93
95 uint64_t pc() override { return pc_; }
96 uint64_t sp() override { return sp_; }
97
98 void set_pc(AddressType pc) { pc_ = pc; }
99 void set_sp(AddressType sp) { sp_ = sp; }
100
101 bool Is32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); } 94 bool Is32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); }
102 95
103 inline AddressType& operator[](size_t reg) { return regs_[reg]; } 96 inline AddressType& operator[](size_t reg) { return regs_[reg]; }
@@ -111,8 +104,6 @@ class RegsImpl : public Regs {
111 } 104 }
112 105
113 protected: 106 protected:
114 AddressType pc_;
115 AddressType sp_;
116 std::vector<AddressType> regs_; 107 std::vector<AddressType> regs_;
117}; 108};
118 109
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index 5af90d3f5..31e6797fa 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -34,17 +34,21 @@ class RegsArm : public RegsImpl<uint32_t> {
34 RegsArm(); 34 RegsArm();
35 virtual ~RegsArm() = default; 35 virtual ~RegsArm() = default;
36 36
37 virtual ArchEnum Arch() override final; 37 ArchEnum Arch() override final;
38 38
39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override;
42
43 bool SetPcFromReturnAddress(Memory* process_memory) override; 41 bool SetPcFromReturnAddress(Memory* process_memory) override;
44 42
45 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 43 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
46 44
47 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; 45 void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
46
47 uint64_t pc() override;
48 uint64_t sp() override;
49
50 void set_pc(uint64_t pc) override;
51 void set_sp(uint64_t sp) override;
48 52
49 static Regs* Read(void* data); 53 static Regs* Read(void* data);
50 54
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index cb05732ee..0c45ebab8 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -34,17 +34,21 @@ class RegsArm64 : public RegsImpl<uint64_t> {
34 RegsArm64(); 34 RegsArm64();
35 virtual ~RegsArm64() = default; 35 virtual ~RegsArm64() = default;
36 36
37 virtual ArchEnum Arch() override final; 37 ArchEnum Arch() override final;
38 38
39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override;
42
43 bool SetPcFromReturnAddress(Memory* process_memory) override; 41 bool SetPcFromReturnAddress(Memory* process_memory) override;
44 42
45 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 43 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
46 44
47 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; 45 void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
46
47 uint64_t pc() override;
48 uint64_t sp() override;
49
50 void set_pc(uint64_t pc) override;
51 void set_sp(uint64_t sp) override;
48 52
49 static Regs* Read(void* data); 53 static Regs* Read(void* data);
50 54
diff --git a/libunwindstack/include/unwindstack/RegsGetLocal.h b/libunwindstack/include/unwindstack/RegsGetLocal.h
index 557eace32..81c0af374 100644
--- a/libunwindstack/include/unwindstack/RegsGetLocal.h
+++ b/libunwindstack/include/unwindstack/RegsGetLocal.h
@@ -51,8 +51,6 @@ inline __always_inline void RegsGetLocal(Regs* regs) {
51 : [base] "+r"(reg_data) 51 : [base] "+r"(reg_data)
52 : 52 :
53 : "memory"); 53 : "memory");
54
55 regs->SetFromRaw();
56} 54}
57 55
58#elif defined(__aarch64__) 56#elif defined(__aarch64__)
@@ -83,8 +81,6 @@ inline __always_inline void RegsGetLocal(Regs* regs) {
83 : [base] "+r"(reg_data) 81 : [base] "+r"(reg_data)
84 : 82 :
85 : "x12", "x13", "memory"); 83 : "x12", "x13", "memory");
86
87 regs->SetFromRaw();
88} 84}
89 85
90#elif defined(__i386__) || defined(__x86_64__) || defined(__mips__) 86#elif defined(__i386__) || defined(__x86_64__) || defined(__mips__)
@@ -93,8 +89,6 @@ extern "C" void AsmGetRegs(void* regs);
93 89
94inline void RegsGetLocal(Regs* regs) { 90inline void RegsGetLocal(Regs* regs) {
95 AsmGetRegs(regs->RawData()); 91 AsmGetRegs(regs->RawData());
96
97 regs->SetFromRaw();
98} 92}
99 93
100#endif 94#endif
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index 8e3c01f20..709f9e2c7 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -34,17 +34,21 @@ class RegsMips : public RegsImpl<uint32_t> {
34 RegsMips(); 34 RegsMips();
35 virtual ~RegsMips() = default; 35 virtual ~RegsMips() = default;
36 36
37 virtual ArchEnum Arch() override final; 37 ArchEnum Arch() override final;
38 38
39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override;
42
43 bool SetPcFromReturnAddress(Memory* process_memory) override; 41 bool SetPcFromReturnAddress(Memory* process_memory) override;
44 42
45 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 43 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
46 44
47 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; 45 void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
46
47 uint64_t pc() override;
48 uint64_t sp() override;
49
50 void set_pc(uint64_t pc) override;
51 void set_sp(uint64_t sp) override;
48 52
49 static Regs* Read(void* data); 53 static Regs* Read(void* data);
50 54
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 8c2d4437f..1de83ea9d 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -34,17 +34,21 @@ class RegsMips64 : public RegsImpl<uint64_t> {
34 RegsMips64(); 34 RegsMips64();
35 virtual ~RegsMips64() = default; 35 virtual ~RegsMips64() = default;
36 36
37 virtual ArchEnum Arch() override final; 37 ArchEnum Arch() override final;
38 38
39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override;
42
43 bool SetPcFromReturnAddress(Memory* process_memory) override; 41 bool SetPcFromReturnAddress(Memory* process_memory) override;
44 42
45 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 43 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
46 44
47 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; 45 void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
46
47 uint64_t pc() override;
48 uint64_t sp() override;
49
50 void set_pc(uint64_t pc) override;
51 void set_sp(uint64_t sp) override;
48 52
49 static Regs* Read(void* data); 53 static Regs* Read(void* data);
50 54
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index 1bc145d97..586c9d85c 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -35,19 +35,23 @@ class RegsX86 : public RegsImpl<uint32_t> {
35 RegsX86(); 35 RegsX86();
36 virtual ~RegsX86() = default; 36 virtual ~RegsX86() = default;
37 37
38 virtual ArchEnum Arch() override final; 38 ArchEnum Arch() override final;
39 39
40 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; 40 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
41 41
42 void SetFromRaw() override;
43
44 bool SetPcFromReturnAddress(Memory* process_memory) override; 42 bool SetPcFromReturnAddress(Memory* process_memory) override;
45 43
46 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 44 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
47 45
48 void SetFromUcontext(x86_ucontext_t* ucontext); 46 void SetFromUcontext(x86_ucontext_t* ucontext);
49 47
50 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; 48 void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
49
50 uint64_t pc() override;
51 uint64_t sp() override;
52
53 void set_pc(uint64_t pc) override;
54 void set_sp(uint64_t sp) override;
51 55
52 static Regs* Read(void* data); 56 static Regs* Read(void* data);
53 57
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index 4cd45d4b9..061f479a0 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -35,19 +35,23 @@ class RegsX86_64 : public RegsImpl<uint64_t> {
35 RegsX86_64(); 35 RegsX86_64();
36 virtual ~RegsX86_64() = default; 36 virtual ~RegsX86_64() = default;
37 37
38 virtual ArchEnum Arch() override final; 38 ArchEnum Arch() override final;
39 39
40 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; 40 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
41 41
42 void SetFromRaw() override;
43
44 bool SetPcFromReturnAddress(Memory* process_memory) override; 42 bool SetPcFromReturnAddress(Memory* process_memory) override;
45 43
46 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 44 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
47 45
48 void SetFromUcontext(x86_64_ucontext_t* ucontext); 46 void SetFromUcontext(x86_64_ucontext_t* ucontext);
49 47
50 virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final; 48 void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
49
50 uint64_t pc() override;
51 uint64_t sp() override;
52
53 void set_pc(uint64_t pc) override;
54 void set_sp(uint64_t sp) override;
51 55
52 static Regs* Read(void* data); 56 static Regs* Read(void* data);
53 57
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index 6e15227b3..d424d5f43 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -1468,7 +1468,7 @@ TYPED_TEST_P(DwarfOpTest, op_breg) {
1468 } 1468 }
1469 this->op_memory_.SetMemory(0, opcode_buffer); 1469 this->op_memory_.SetMemory(0, opcode_buffer);
1470 1470
1471 RegsImplFake<TypeParam> regs(32, 10); 1471 RegsImplFake<TypeParam> regs(32);
1472 for (size_t i = 0; i < 32; i++) { 1472 for (size_t i = 0; i < 32; i++) {
1473 regs[i] = i + 10; 1473 regs[i] = i + 10;
1474 } 1474 }
@@ -1499,7 +1499,7 @@ TYPED_TEST_P(DwarfOpTest, op_breg_invalid_register) {
1499 }; 1499 };
1500 this->op_memory_.SetMemory(0, opcode_buffer); 1500 this->op_memory_.SetMemory(0, opcode_buffer);
1501 1501
1502 RegsImplFake<TypeParam> regs(16, 10); 1502 RegsImplFake<TypeParam> regs(16);
1503 for (size_t i = 0; i < 16; i++) { 1503 for (size_t i = 0; i < 16; i++) {
1504 regs[i] = i + 10; 1504 regs[i] = i + 10;
1505 } 1505 }
@@ -1526,7 +1526,7 @@ TYPED_TEST_P(DwarfOpTest, op_bregx) {
1526 0x92, 0x80, 0x15, 0x80, 0x02}; 1526 0x92, 0x80, 0x15, 0x80, 0x02};
1527 this->op_memory_.SetMemory(0, opcode_buffer); 1527 this->op_memory_.SetMemory(0, opcode_buffer);
1528 1528
1529 RegsImplFake<TypeParam> regs(10, 10); 1529 RegsImplFake<TypeParam> regs(10);
1530 regs[5] = 0x45; 1530 regs[5] = 0x45;
1531 regs[6] = 0x190; 1531 regs[6] = 0x190;
1532 RegsInfo<TypeParam> regs_info(&regs); 1532 RegsInfo<TypeParam> regs_info(&regs);
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index 99f4d873f..c85764c78 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -92,7 +92,7 @@ TYPED_TEST_CASE_P(DwarfSectionImplTest);
92 92
93TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) { 93TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
94 DwarfCie cie{.version = 3, .return_address_register = 5}; 94 DwarfCie cie{.version = 3, .return_address_register = 5};
95 RegsImplFake<TypeParam> regs(10, 9); 95 RegsImplFake<TypeParam> regs(10);
96 dwarf_loc_regs_t loc_regs; 96 dwarf_loc_regs_t loc_regs;
97 97
98 regs.set_pc(0x100); 98 regs.set_pc(0x100);
@@ -108,7 +108,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
108 108
109TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) { 109TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
110 DwarfCie cie{.version = 3, .return_address_register = 5}; 110 DwarfCie cie{.version = 3, .return_address_register = 5};
111 RegsImplFake<TypeParam> regs(10, 9); 111 RegsImplFake<TypeParam> regs(10);
112 dwarf_loc_regs_t loc_regs; 112 dwarf_loc_regs_t loc_regs;
113 113
114 regs.set_pc(0x100); 114 regs.set_pc(0x100);
@@ -124,7 +124,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
124 124
125TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) { 125TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
126 DwarfCie cie{.version = 3, .return_address_register = 5}; 126 DwarfCie cie{.version = 3, .return_address_register = 5};
127 RegsImplFake<TypeParam> regs(10, 9); 127 RegsImplFake<TypeParam> regs(10);
128 dwarf_loc_regs_t loc_regs; 128 dwarf_loc_regs_t loc_regs;
129 129
130 regs.set_pc(0x100); 130 regs.set_pc(0x100);
@@ -142,7 +142,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
142 142
143TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) { 143TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
144 DwarfCie cie{.version = 3, .return_address_register = 5}; 144 DwarfCie cie{.version = 3, .return_address_register = 5};
145 RegsImplFake<TypeParam> regs(10, 9); 145 RegsImplFake<TypeParam> regs(10);
146 dwarf_loc_regs_t loc_regs; 146 dwarf_loc_regs_t loc_regs;
147 147
148 regs.set_pc(0x100); 148 regs.set_pc(0x100);
@@ -160,7 +160,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
160 160
161TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) { 161TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
162 DwarfCie cie{.version = 3, .return_address_register = 5}; 162 DwarfCie cie{.version = 3, .return_address_register = 5};
163 RegsImplFake<TypeParam> regs(10, 9); 163 RegsImplFake<TypeParam> regs(10);
164 dwarf_loc_regs_t loc_regs; 164 dwarf_loc_regs_t loc_regs;
165 165
166 regs.set_pc(0x100); 166 regs.set_pc(0x100);
@@ -176,7 +176,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
176 176
177TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) { 177TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
178 DwarfCie cie{.return_address_register = 60}; 178 DwarfCie cie{.return_address_register = 60};
179 RegsImplFake<TypeParam> regs(10, 9); 179 RegsImplFake<TypeParam> regs(10);
180 dwarf_loc_regs_t loc_regs; 180 dwarf_loc_regs_t loc_regs;
181 181
182 bool finished; 182 bool finished;
@@ -186,7 +186,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
186 186
187TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) { 187TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
188 DwarfCie cie{.return_address_register = 5}; 188 DwarfCie cie{.return_address_register = 5};
189 RegsImplFake<TypeParam> regs(10, 9); 189 RegsImplFake<TypeParam> regs(10);
190 dwarf_loc_regs_t loc_regs; 190 dwarf_loc_regs_t loc_regs;
191 191
192 bool finished; 192 bool finished;
@@ -196,7 +196,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
196 196
197TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) { 197TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
198 DwarfCie cie{.return_address_register = 5}; 198 DwarfCie cie{.return_address_register = 5};
199 RegsImplFake<TypeParam> regs(10, 9); 199 RegsImplFake<TypeParam> regs(10);
200 dwarf_loc_regs_t loc_regs; 200 dwarf_loc_regs_t loc_regs;
201 201
202 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}}; 202 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
@@ -225,7 +225,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
225 225
226TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) { 226TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
227 DwarfCie cie{.return_address_register = 5}; 227 DwarfCie cie{.return_address_register = 5};
228 RegsImplFake<TypeParam> regs(10, 9); 228 RegsImplFake<TypeParam> regs(10);
229 dwarf_loc_regs_t loc_regs; 229 dwarf_loc_regs_t loc_regs;
230 230
231 regs.set_pc(0x100); 231 regs.set_pc(0x100);
@@ -237,12 +237,12 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
237 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 237 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
238 EXPECT_FALSE(finished); 238 EXPECT_FALSE(finished);
239 EXPECT_EQ(0x20U, regs.pc()); 239 EXPECT_EQ(0x20U, regs.pc());
240 EXPECT_EQ(0x2000U, regs.sp()); 240 EXPECT_EQ(0x3000U, regs.sp());
241} 241}
242 242
243TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) { 243TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
244 DwarfCie cie{.return_address_register = 5}; 244 DwarfCie cie{.return_address_register = 5};
245 RegsImplFake<TypeParam> regs(10, 9); 245 RegsImplFake<TypeParam> regs(10);
246 dwarf_loc_regs_t loc_regs; 246 dwarf_loc_regs_t loc_regs;
247 247
248 regs.set_pc(0x100); 248 regs.set_pc(0x100);
@@ -260,7 +260,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
260 260
261TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) { 261TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
262 DwarfCie cie{.return_address_register = 5}; 262 DwarfCie cie{.return_address_register = 5};
263 RegsImplFake<TypeParam> regs(10, 9); 263 RegsImplFake<TypeParam> regs(10);
264 dwarf_loc_regs_t loc_regs; 264 dwarf_loc_regs_t loc_regs;
265 265
266 regs.set_pc(0x100); 266 regs.set_pc(0x100);
@@ -281,7 +281,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
281 281
282TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) { 282TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
283 DwarfCie cie{.return_address_register = 5}; 283 DwarfCie cie{.return_address_register = 5};
284 RegsImplFake<TypeParam> regs(10, 9); 284 RegsImplFake<TypeParam> regs(10);
285 dwarf_loc_regs_t loc_regs; 285 dwarf_loc_regs_t loc_regs;
286 286
287 regs.set_pc(0x100); 287 regs.set_pc(0x100);
@@ -312,7 +312,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
312 312
313TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) { 313TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
314 DwarfCie cie{.return_address_register = 5}; 314 DwarfCie cie{.return_address_register = 5};
315 RegsImplFake<TypeParam> regs(10, 9); 315 RegsImplFake<TypeParam> regs(10);
316 dwarf_loc_regs_t loc_regs; 316 dwarf_loc_regs_t loc_regs;
317 317
318 regs.set_pc(0x100); 318 regs.set_pc(0x100);
@@ -331,7 +331,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
331 331
332TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) { 332TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
333 DwarfCie cie{.return_address_register = 5}; 333 DwarfCie cie{.return_address_register = 5};
334 RegsImplFake<TypeParam> regs(10, 9); 334 RegsImplFake<TypeParam> regs(10);
335 dwarf_loc_regs_t loc_regs; 335 dwarf_loc_regs_t loc_regs;
336 336
337 regs.set_pc(0x100); 337 regs.set_pc(0x100);
@@ -346,7 +346,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
346 346
347TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) { 347TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
348 DwarfCie cie{.return_address_register = 5}; 348 DwarfCie cie{.return_address_register = 5};
349 RegsImplFake<TypeParam> regs(10, 9); 349 RegsImplFake<TypeParam> regs(10);
350 dwarf_loc_regs_t loc_regs; 350 dwarf_loc_regs_t loc_regs;
351 351
352 if (sizeof(TypeParam) == sizeof(uint64_t)) { 352 if (sizeof(TypeParam) == sizeof(uint64_t)) {
@@ -380,7 +380,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
380 380
381TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) { 381TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
382 DwarfCie cie{.return_address_register = 5}; 382 DwarfCie cie{.return_address_register = 5};
383 RegsImplFake<TypeParam> regs(10, 9); 383 RegsImplFake<TypeParam> regs(10);
384 dwarf_loc_regs_t loc_regs; 384 dwarf_loc_regs_t loc_regs;
385 385
386 regs.set_pc(0x100); 386 regs.set_pc(0x100);
@@ -398,7 +398,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
398 398
399TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) { 399TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
400 DwarfCie cie{.return_address_register = 5}; 400 DwarfCie cie{.return_address_register = 5};
401 RegsImplFake<TypeParam> regs(10, 9); 401 RegsImplFake<TypeParam> regs(10);
402 dwarf_loc_regs_t loc_regs; 402 dwarf_loc_regs_t loc_regs;
403 403
404 regs.set_pc(0x100); 404 regs.set_pc(0x100);
@@ -415,7 +415,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
415 415
416TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) { 416TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
417 DwarfCie cie{.return_address_register = 5}; 417 DwarfCie cie{.return_address_register = 5};
418 RegsImplFake<TypeParam> regs(10, 9); 418 RegsImplFake<TypeParam> regs(10);
419 dwarf_loc_regs_t loc_regs; 419 dwarf_loc_regs_t loc_regs;
420 420
421 regs.set_pc(0x100); 421 regs.set_pc(0x100);
@@ -432,7 +432,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
432 432
433TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) { 433TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
434 DwarfCie cie{.return_address_register = 5}; 434 DwarfCie cie{.return_address_register = 5};
435 RegsImplFake<TypeParam> regs(10, 9); 435 RegsImplFake<TypeParam> regs(10);
436 dwarf_loc_regs_t loc_regs; 436 dwarf_loc_regs_t loc_regs;
437 437
438 regs.set_pc(0x100); 438 regs.set_pc(0x100);
@@ -451,7 +451,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
451 451
452TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) { 452TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
453 DwarfCie cie{.version = 3, .return_address_register = 5}; 453 DwarfCie cie{.version = 3, .return_address_register = 5};
454 RegsImplFake<TypeParam> regs(10, 9); 454 RegsImplFake<TypeParam> regs(10);
455 dwarf_loc_regs_t loc_regs; 455 dwarf_loc_regs_t loc_regs;
456 456
457 regs.set_pc(0x100); 457 regs.set_pc(0x100);
@@ -471,7 +471,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
471 471
472TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) { 472TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
473 DwarfCie cie{.version = 3, .return_address_register = 5}; 473 DwarfCie cie{.version = 3, .return_address_register = 5};
474 RegsImplFake<TypeParam> regs(10, 9); 474 RegsImplFake<TypeParam> regs(10);
475 dwarf_loc_regs_t loc_regs; 475 dwarf_loc_regs_t loc_regs;
476 476
477 regs.set_pc(0x100); 477 regs.set_pc(0x100);
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
index ae9da5eb4..66207dbd1 100644
--- a/libunwindstack/tests/ElfFake.cpp
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -65,8 +65,8 @@ bool ElfInterfaceFake::Step(uint64_t, uint64_t, Regs* regs, Memory*, bool* finis
65 } 65 }
66 66
67 RegsFake* fake_regs = reinterpret_cast<RegsFake*>(regs); 67 RegsFake* fake_regs = reinterpret_cast<RegsFake*>(regs);
68 fake_regs->FakeSetPc(entry.pc); 68 fake_regs->set_pc(entry.pc);
69 fake_regs->FakeSetSp(entry.sp); 69 fake_regs->set_sp(entry.sp);
70 *finished = entry.finished; 70 *finished = entry.finished;
71 return true; 71 return true;
72} 72}
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index eb850336b..f9028c4a5 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -316,7 +316,6 @@ TEST_F(ElfTest, step_in_signal_map) {
316 RegsArm regs; 316 RegsArm regs;
317 regs[13] = 0x50000; 317 regs[13] = 0x50000;
318 regs[15] = 0x8000; 318 regs[15] = 0x8000;
319 regs.SetFromRaw();
320 319
321 ElfInterfaceFake* interface = new ElfInterfaceFake(memory_); 320 ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
322 elf.FakeSetInterface(interface); 321 elf.FakeSetInterface(interface);
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index ab23194e5..ede16b32b 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -27,14 +27,16 @@ namespace unwindstack {
27 27
28class RegsFake : public Regs { 28class RegsFake : public Regs {
29 public: 29 public:
30 RegsFake(uint16_t total_regs, uint16_t sp_reg) 30 RegsFake(uint16_t total_regs) : Regs(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
31 : Regs(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
32 virtual ~RegsFake() = default; 31 virtual ~RegsFake() = default;
33 32
34 ArchEnum Arch() override { return fake_arch_; } 33 ArchEnum Arch() override { return fake_arch_; }
35 void* RawData() override { return nullptr; } 34 void* RawData() override { return nullptr; }
36 uint64_t pc() override { return fake_pc_; } 35 uint64_t pc() override { return fake_pc_; }
37 uint64_t sp() override { return fake_sp_; } 36 uint64_t sp() override { return fake_sp_; }
37 void set_pc(uint64_t pc) override { fake_pc_ = pc; }
38 void set_sp(uint64_t sp) override { fake_sp_ = sp; }
39
38 bool SetPcFromReturnAddress(Memory*) override { 40 bool SetPcFromReturnAddress(Memory*) override {
39 if (!fake_return_address_valid_) { 41 if (!fake_return_address_valid_) {
40 return false; 42 return false;
@@ -51,11 +53,7 @@ class RegsFake : public Regs {
51 53
52 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } 54 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
53 55
54 void SetFromRaw() override {}
55
56 void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; } 56 void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; }
57 void FakeSetPc(uint64_t pc) { fake_pc_ = pc; }
58 void FakeSetSp(uint64_t sp) { fake_sp_ = sp; }
59 void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; } 57 void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
60 void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; } 58 void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
61 void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; } 59 void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
@@ -71,19 +69,23 @@ class RegsFake : public Regs {
71template <typename TypeParam> 69template <typename TypeParam>
72class RegsImplFake : public RegsImpl<TypeParam> { 70class RegsImplFake : public RegsImpl<TypeParam> {
73 public: 71 public:
74 RegsImplFake(uint16_t total_regs, uint16_t sp_reg) 72 RegsImplFake(uint16_t total_regs)
75 : RegsImpl<TypeParam>(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {} 73 : RegsImpl<TypeParam>(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
76 virtual ~RegsImplFake() = default; 74 virtual ~RegsImplFake() = default;
77 75
78 ArchEnum Arch() override { return ARCH_UNKNOWN; } 76 ArchEnum Arch() override { return ARCH_UNKNOWN; }
77 uint64_t pc() override { return fake_pc_; }
78 uint64_t sp() override { return fake_sp_; }
79 void set_pc(uint64_t pc) override { fake_pc_ = pc; }
80 void set_sp(uint64_t sp) override { fake_sp_ = sp; }
79 81
80 uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 0; } 82 uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 0; }
81 void SetFromRaw() override {}
82 bool SetPcFromReturnAddress(Memory*) override { return false; } 83 bool SetPcFromReturnAddress(Memory*) override { return false; }
83 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } 84 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
84 85
85 void FakeSetPc(uint64_t pc) { this->pc_ = pc; } 86 private:
86 void FakeSetSp(uint64_t sp) { this->sp_ = sp; } 87 uint64_t fake_pc_ = 0;
88 uint64_t fake_sp_ = 0;
87}; 89};
88 90
89} // namespace unwindstack 91} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
index ecd40518b..eac12ca64 100644
--- a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
+++ b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
@@ -56,7 +56,6 @@ void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerNonRt(uint32_t pc_data)
56 RegsArm regs; 56 RegsArm regs;
57 regs[ARM_REG_PC] = 0x5000; 57 regs[ARM_REG_PC] = 0x5000;
58 regs[ARM_REG_SP] = addr; 58 regs[ARM_REG_SP] = addr;
59 regs.SetFromRaw();
60 59
61 elf_memory_->SetData32(0x5000, pc_data); 60 elf_memory_->SetData32(0x5000, pc_data);
62 61
@@ -87,7 +86,6 @@ void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerRt(uint32_t pc_data) {
87 RegsArm regs; 86 RegsArm regs;
88 regs[ARM_REG_PC] = 0x5000; 87 regs[ARM_REG_PC] = 0x5000;
89 regs[ARM_REG_SP] = addr; 88 regs[ARM_REG_SP] = addr;
90 regs.SetFromRaw();
91 89
92 elf_memory_->SetData32(0x5000, pc_data); 90 elf_memory_->SetData32(0x5000, pc_data);
93 91
@@ -118,7 +116,6 @@ TEST_F(RegsStepIfSignalHandlerTest, arm64_step_if_signal_handler) {
118 RegsArm64 regs; 116 RegsArm64 regs;
119 regs[ARM64_REG_PC] = 0x8000; 117 regs[ARM64_REG_PC] = 0x8000;
120 regs[ARM64_REG_SP] = addr; 118 regs[ARM64_REG_SP] = addr;
121 regs.SetFromRaw();
122 119
123 elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL); 120 elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL);
124 121
@@ -138,7 +135,6 @@ TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_no_siginfo) {
138 RegsX86 regs; 135 RegsX86 regs;
139 regs[X86_REG_EIP] = 0x4100; 136 regs[X86_REG_EIP] = 0x4100;
140 regs[X86_REG_ESP] = addr; 137 regs[X86_REG_ESP] = addr;
141 regs.SetFromRaw();
142 138
143 elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL); 139 elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL);
144 for (uint64_t index = 0; index <= 25; index++) { 140 for (uint64_t index = 0; index <= 25; index++) {
@@ -162,7 +158,6 @@ TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_siginfo) {
162 RegsX86 regs; 158 RegsX86 regs;
163 regs[X86_REG_EIP] = 0x4100; 159 regs[X86_REG_EIP] = 0x4100;
164 regs[X86_REG_ESP] = addr; 160 regs[X86_REG_ESP] = addr;
165 regs.SetFromRaw();
166 161
167 elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL); 162 elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL);
168 addr += 8; 163 addr += 8;
@@ -191,7 +186,6 @@ TEST_F(RegsStepIfSignalHandlerTest, x86_64_step_if_signal_handler) {
191 RegsX86_64 regs; 186 RegsX86_64 regs;
192 regs[X86_64_REG_RIP] = 0x7000; 187 regs[X86_64_REG_RIP] = 0x7000;
193 regs[X86_64_REG_RSP] = addr; 188 regs[X86_64_REG_RSP] = addr;
194 regs.SetFromRaw();
195 189
196 elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748); 190 elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748);
197 elf_memory_->SetData16(0x7008, 0x0f05); 191 elf_memory_->SetData16(0x7008, 0x0f05);
@@ -212,7 +206,6 @@ TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_non_rt) {
212 RegsMips regs; 206 RegsMips regs;
213 regs[MIPS_REG_PC] = 0x8000; 207 regs[MIPS_REG_PC] = 0x8000;
214 regs[MIPS_REG_SP] = addr; 208 regs[MIPS_REG_SP] = addr;
215 regs.SetFromRaw();
216 209
217 elf_memory_->SetData64(0x8000, 0x0000000c24021017ULL); 210 elf_memory_->SetData64(0x8000, 0x0000000c24021017ULL);
218 211
@@ -232,7 +225,6 @@ TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_rt) {
232 RegsMips regs; 225 RegsMips regs;
233 regs[MIPS_REG_PC] = 0x8000; 226 regs[MIPS_REG_PC] = 0x8000;
234 regs[MIPS_REG_SP] = addr; 227 regs[MIPS_REG_SP] = addr;
235 regs.SetFromRaw();
236 228
237 elf_memory_->SetData64(0x8000, 0x0000000c24021061ULL); 229 elf_memory_->SetData64(0x8000, 0x0000000c24021061ULL);
238 230
@@ -252,7 +244,6 @@ TEST_F(RegsStepIfSignalHandlerTest, mips64_step_if_signal_handler) {
252 RegsMips64 regs; 244 RegsMips64 regs;
253 regs[MIPS64_REG_PC] = 0x8000; 245 regs[MIPS64_REG_PC] = 0x8000;
254 regs[MIPS64_REG_SP] = addr; 246 regs[MIPS64_REG_SP] = addr;
255 regs.SetFromRaw();
256 247
257 elf_memory_->SetData64(0x8000, 0x0000000c2402145bULL); 248 elf_memory_->SetData64(0x8000, 0x0000000c2402145bULL);
258 249
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 8b2f6c83f..3e80733bf 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -49,9 +49,8 @@ class RegsTest : public ::testing::Test {
49}; 49};
50 50
51TEST_F(RegsTest, regs32) { 51TEST_F(RegsTest, regs32) {
52 RegsImplFake<uint32_t> regs32(50, 10); 52 RegsImplFake<uint32_t> regs32(50);
53 ASSERT_EQ(50U, regs32.total_regs()); 53 ASSERT_EQ(50U, regs32.total_regs());
54 ASSERT_EQ(10U, regs32.sp_reg());
55 54
56 uint32_t* raw = reinterpret_cast<uint32_t*>(regs32.RawData()); 55 uint32_t* raw = reinterpret_cast<uint32_t*>(regs32.RawData());
57 for (size_t i = 0; i < 50; i++) { 56 for (size_t i = 0; i < 50; i++) {
@@ -72,9 +71,8 @@ TEST_F(RegsTest, regs32) {
72} 71}
73 72
74TEST_F(RegsTest, regs64) { 73TEST_F(RegsTest, regs64) {
75 RegsImplFake<uint64_t> regs64(30, 12); 74 RegsImplFake<uint64_t> regs64(30);
76 ASSERT_EQ(30U, regs64.total_regs()); 75 ASSERT_EQ(30U, regs64.total_regs());
77 ASSERT_EQ(12U, regs64.sp_reg());
78 76
79 uint64_t* raw = reinterpret_cast<uint64_t*>(regs64.RawData()); 77 uint64_t* raw = reinterpret_cast<uint64_t*>(regs64.RawData());
80 for (size_t i = 0; i < 30; i++) { 78 for (size_t i = 0; i < 30; i++) {
@@ -211,62 +209,56 @@ TEST_F(RegsTest, elf_invalid) {
211 EXPECT_EQ(0U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf)); 209 EXPECT_EQ(0U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf));
212} 210}
213 211
214TEST_F(RegsTest, arm_set_from_raw) { 212TEST_F(RegsTest, arm_verify_sp_pc) {
215 RegsArm arm; 213 RegsArm arm;
216 uint32_t* regs = reinterpret_cast<uint32_t*>(arm.RawData()); 214 uint32_t* regs = reinterpret_cast<uint32_t*>(arm.RawData());
217 regs[13] = 0x100; 215 regs[13] = 0x100;
218 regs[15] = 0x200; 216 regs[15] = 0x200;
219 arm.SetFromRaw();
220 EXPECT_EQ(0x100U, arm.sp()); 217 EXPECT_EQ(0x100U, arm.sp());
221 EXPECT_EQ(0x200U, arm.pc()); 218 EXPECT_EQ(0x200U, arm.pc());
222} 219}
223 220
224TEST_F(RegsTest, arm64_set_from_raw) { 221TEST_F(RegsTest, arm64_verify_sp_pc) {
225 RegsArm64 arm64; 222 RegsArm64 arm64;
226 uint64_t* regs = reinterpret_cast<uint64_t*>(arm64.RawData()); 223 uint64_t* regs = reinterpret_cast<uint64_t*>(arm64.RawData());
227 regs[31] = 0xb100000000ULL; 224 regs[31] = 0xb100000000ULL;
228 regs[32] = 0xc200000000ULL; 225 regs[32] = 0xc200000000ULL;
229 arm64.SetFromRaw();
230 EXPECT_EQ(0xb100000000U, arm64.sp()); 226 EXPECT_EQ(0xb100000000U, arm64.sp());
231 EXPECT_EQ(0xc200000000U, arm64.pc()); 227 EXPECT_EQ(0xc200000000U, arm64.pc());
232} 228}
233 229
234TEST_F(RegsTest, x86_set_from_raw) { 230TEST_F(RegsTest, x86_verify_sp_pc) {
235 RegsX86 x86; 231 RegsX86 x86;
236 uint32_t* regs = reinterpret_cast<uint32_t*>(x86.RawData()); 232 uint32_t* regs = reinterpret_cast<uint32_t*>(x86.RawData());
237 regs[4] = 0x23450000; 233 regs[4] = 0x23450000;
238 regs[8] = 0xabcd0000; 234 regs[8] = 0xabcd0000;
239 x86.SetFromRaw();
240 EXPECT_EQ(0x23450000U, x86.sp()); 235 EXPECT_EQ(0x23450000U, x86.sp());
241 EXPECT_EQ(0xabcd0000U, x86.pc()); 236 EXPECT_EQ(0xabcd0000U, x86.pc());
242} 237}
243 238
244TEST_F(RegsTest, x86_64_set_from_raw) { 239TEST_F(RegsTest, x86_64_verify_sp_pc) {
245 RegsX86_64 x86_64; 240 RegsX86_64 x86_64;
246 uint64_t* regs = reinterpret_cast<uint64_t*>(x86_64.RawData()); 241 uint64_t* regs = reinterpret_cast<uint64_t*>(x86_64.RawData());
247 regs[7] = 0x1200000000ULL; 242 regs[7] = 0x1200000000ULL;
248 regs[16] = 0x4900000000ULL; 243 regs[16] = 0x4900000000ULL;
249 x86_64.SetFromRaw();
250 EXPECT_EQ(0x1200000000U, x86_64.sp()); 244 EXPECT_EQ(0x1200000000U, x86_64.sp());
251 EXPECT_EQ(0x4900000000U, x86_64.pc()); 245 EXPECT_EQ(0x4900000000U, x86_64.pc());
252} 246}
253 247
254TEST_F(RegsTest, mips_set_from_raw) { 248TEST_F(RegsTest, mips_verify_sp_pc) {
255 RegsMips mips; 249 RegsMips mips;
256 uint32_t* regs = reinterpret_cast<uint32_t*>(mips.RawData()); 250 uint32_t* regs = reinterpret_cast<uint32_t*>(mips.RawData());
257 regs[29] = 0x100; 251 regs[29] = 0x100;
258 regs[32] = 0x200; 252 regs[32] = 0x200;
259 mips.SetFromRaw();
260 EXPECT_EQ(0x100U, mips.sp()); 253 EXPECT_EQ(0x100U, mips.sp());
261 EXPECT_EQ(0x200U, mips.pc()); 254 EXPECT_EQ(0x200U, mips.pc());
262} 255}
263 256
264TEST_F(RegsTest, mips64_set_from_raw) { 257TEST_F(RegsTest, mips64_verify_sp_pc) {
265 RegsMips64 mips64; 258 RegsMips64 mips64;
266 uint64_t* regs = reinterpret_cast<uint64_t*>(mips64.RawData()); 259 uint64_t* regs = reinterpret_cast<uint64_t*>(mips64.RawData());
267 regs[29] = 0xb100000000ULL; 260 regs[29] = 0xb100000000ULL;
268 regs[32] = 0xc200000000ULL; 261 regs[32] = 0xc200000000ULL;
269 mips64.SetFromRaw();
270 EXPECT_EQ(0xb100000000U, mips64.sp()); 262 EXPECT_EQ(0xb100000000U, mips64.sp());
271 EXPECT_EQ(0xc200000000U, mips64.pc()); 263 EXPECT_EQ(0xc200000000U, mips64.pc());
272} 264}
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 515bc8cc7..532640f38 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -122,7 +122,6 @@ class UnwindOfflineTest : public ::testing::Test {
122 (*regs)[entry->second] = value; 122 (*regs)[entry->second] = value;
123 } 123 }
124 fclose(fp); 124 fclose(fp);
125 regs->SetFromRaw();
126 } 125 }
127 126
128 static std::unordered_map<std::string, uint32_t> arm_regs_; 127 static std::unordered_map<std::string, uint32_t> arm_regs_;
@@ -956,4 +955,119 @@ TEST_F(UnwindOfflineTest, eh_frame_hdr_begin_x86_64) {
956 EXPECT_EQ(0x7ffcc85971a0U, unwinder.frames()[4].sp); 955 EXPECT_EQ(0x7ffcc85971a0U, unwinder.frames()[4].sp);
957} 956}
958 957
958TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) {
959 Init("art_quick_osr_stub_arm/", ARCH_ARM);
960
961 MemoryOfflineParts* memory = new MemoryOfflineParts;
962 AddMemory(dir_ + "descriptor.data", memory);
963 AddMemory(dir_ + "stack.data", memory);
964 for (size_t i = 0; i < 2; i++) {
965 AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
966 AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
967 }
968 process_memory_.reset(memory);
969
970 JitDebug jit_debug(process_memory_);
971 Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
972 unwinder.SetJitDebug(&jit_debug, regs_->Arch());
973 unwinder.Unwind();
974
975 std::string frame_info(DumpFrames(unwinder));
976 ASSERT_EQ(25U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
977 EXPECT_EQ(
978 " #00 pc 0000c788 <anonymous:d0250000> "
979 "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
980 " #01 pc 0000cdd5 <anonymous:d0250000> "
981 "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
982 " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
983 " #03 pc 002657a5 libart.so "
984 "(_ZN3art3jit3Jit25MaybeDoOnStackReplacementEPNS_6ThreadEPNS_9ArtMethodEjiPNS_6JValueE+876)\n"
985 " #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n"
986 " #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n"
987 " #06 pc cd8365b0 <unknown>\n" // symbol in dex file
988 " #07 pc 001d7f1b libart.so "
989 "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
990 "6JValueEb+374)\n"
991 " #08 pc 001dc593 libart.so "
992 "(_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadERKNS_"
993 "20CodeItemDataAccessorEPNS_11ShadowFrameEPNS_6JValueE+154)\n"
994 " #09 pc 001f4d01 libart.so "
995 "(_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_"
996 "11InstructionEtPNS_6JValueE+732)\n"
997 " #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n"
998 " #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n"
999 " #12 pc 7004873e <unknown>\n" // symbol in dex file
1000 " #13 pc 001d7f1b libart.so "
1001 "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
1002 "6JValueEb+374)\n"
1003 " #14 pc 001dc4d5 libart.so "
1004 "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
1005 "20CodeItemDataAccessorEPNS_11ShadowFrameE+92)\n"
1006 " #15 pc 003f25ab libart.so (artQuickToInterpreterBridge+970)\n"
1007 " #16 pc 00417aff libart.so (art_quick_to_interpreter_bridge+30)\n"
1008 " #17 pc 00413575 libart.so (art_quick_invoke_stub_internal+68)\n"
1009 " #18 pc 00418531 libart.so (art_quick_invoke_stub+236)\n"
1010 " #19 pc 000b468d libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+136)\n"
1011 " #20 pc 00362f49 libart.so "
1012 "(_ZN3art12_GLOBAL__N_118InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_"
1013 "9ArtMethodEPNS0_8ArgArrayEPNS_6JValueEPKc+52)\n"
1014 " #21 pc 00363cd9 libart.so "
1015 "(_ZN3art35InvokeVirtualOrInterfaceWithJValuesERKNS_33ScopedObjectAccessAlreadyRunnableEP8_"
1016 "jobjectP10_jmethodIDP6jvalue+332)\n"
1017 " #22 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
1018 " #23 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
1019 " #24 pc 0001de39 libc.so (__start_thread+24)\n",
1020 frame_info);
1021 EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
1022 EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
1023 EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
1024 EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp);
1025 EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc);
1026 EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp);
1027 EXPECT_EQ(0xe48c77a5U, unwinder.frames()[3].pc);
1028 EXPECT_EQ(0xcd4ff190U, unwinder.frames()[3].sp);
1029 EXPECT_EQ(0xe4a641a7U, unwinder.frames()[4].pc);
1030 EXPECT_EQ(0xcd4ff298U, unwinder.frames()[4].sp);
1031 EXPECT_EQ(0xe4a74474U, unwinder.frames()[5].pc);
1032 EXPECT_EQ(0xcd4ff2b8U, unwinder.frames()[5].sp);
1033 EXPECT_EQ(0xcd8365b0U, unwinder.frames()[6].pc);
1034 EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[6].sp);
1035 EXPECT_EQ(0xe4839f1bU, unwinder.frames()[7].pc);
1036 EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[7].sp);
1037 EXPECT_EQ(0xe483e593U, unwinder.frames()[8].pc);
1038 EXPECT_EQ(0xcd4ff330U, unwinder.frames()[8].sp);
1039 EXPECT_EQ(0xe4856d01U, unwinder.frames()[9].pc);
1040 EXPECT_EQ(0xcd4ff380U, unwinder.frames()[9].sp);
1041 EXPECT_EQ(0xe4a60427U, unwinder.frames()[10].pc);
1042 EXPECT_EQ(0xcd4ff430U, unwinder.frames()[10].sp);
1043 EXPECT_EQ(0xe4a67b94U, unwinder.frames()[11].pc);
1044 EXPECT_EQ(0xcd4ff498U, unwinder.frames()[11].sp);
1045 EXPECT_EQ(0x7004873eU, unwinder.frames()[12].pc);
1046 EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[12].sp);
1047 EXPECT_EQ(0xe4839f1bU, unwinder.frames()[13].pc);
1048 EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[13].sp);
1049 EXPECT_EQ(0xe483e4d5U, unwinder.frames()[14].pc);
1050 EXPECT_EQ(0xcd4ff510U, unwinder.frames()[14].sp);
1051 EXPECT_EQ(0xe4a545abU, unwinder.frames()[15].pc);
1052 EXPECT_EQ(0xcd4ff538U, unwinder.frames()[15].sp);
1053 EXPECT_EQ(0xe4a79affU, unwinder.frames()[16].pc);
1054 EXPECT_EQ(0xcd4ff640U, unwinder.frames()[16].sp);
1055 EXPECT_EQ(0xe4a75575U, unwinder.frames()[17].pc);
1056 EXPECT_EQ(0xcd4ff6b0U, unwinder.frames()[17].sp);
1057 EXPECT_EQ(0xe4a7a531U, unwinder.frames()[18].pc);
1058 EXPECT_EQ(0xcd4ff6e8U, unwinder.frames()[18].sp);
1059 EXPECT_EQ(0xe471668dU, unwinder.frames()[19].pc);
1060 EXPECT_EQ(0xcd4ff770U, unwinder.frames()[19].sp);
1061 EXPECT_EQ(0xe49c4f49U, unwinder.frames()[20].pc);
1062 EXPECT_EQ(0xcd4ff7c8U, unwinder.frames()[20].sp);
1063 EXPECT_EQ(0xe49c5cd9U, unwinder.frames()[21].pc);
1064 EXPECT_EQ(0xcd4ff850U, unwinder.frames()[21].sp);
1065 EXPECT_EQ(0xe49e71ddU, unwinder.frames()[22].pc);
1066 EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[22].sp);
1067 EXPECT_EQ(0xe7df3925U, unwinder.frames()[23].pc);
1068 EXPECT_EQ(0xcd4ff958U, unwinder.frames()[23].sp);
1069 EXPECT_EQ(0xe7daee39U, unwinder.frames()[24].pc);
1070 EXPECT_EQ(0xcd4ff960U, unwinder.frames()[24].sp);
1071}
1072
959} // namespace unwindstack 1073} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 551f46c7b..2428f68fd 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -133,7 +133,7 @@ class UnwinderTest : public ::testing::Test {
133}; 133};
134 134
135MapsFake UnwinderTest::maps_; 135MapsFake UnwinderTest::maps_;
136RegsFake UnwinderTest::regs_(5, 0); 136RegsFake UnwinderTest::regs_(5);
137std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr); 137std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr);
138 138
139TEST_F(UnwinderTest, multiple_frames) { 139TEST_F(UnwinderTest, multiple_frames) {
@@ -141,8 +141,8 @@ TEST_F(UnwinderTest, multiple_frames) {
141 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 141 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
142 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); 142 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
143 143
144 regs_.FakeSetPc(0x1000); 144 regs_.set_pc(0x1000);
145 regs_.FakeSetSp(0x10000); 145 regs_.set_sp(0x10000);
146 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false)); 146 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
147 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false)); 147 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
148 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 148 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -201,8 +201,8 @@ TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) {
201 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 201 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
202 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); 202 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
203 203
204 regs_.FakeSetPc(0x1000); 204 regs_.set_pc(0x1000);
205 regs_.FakeSetSp(0x10000); 205 regs_.set_sp(0x10000);
206 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false)); 206 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
207 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false)); 207 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
208 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 208 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -260,8 +260,8 @@ TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) {
260TEST_F(UnwinderTest, non_zero_load_bias) { 260TEST_F(UnwinderTest, non_zero_load_bias) {
261 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 261 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
262 262
263 regs_.FakeSetPc(0xa5500); 263 regs_.set_pc(0xa5500);
264 regs_.FakeSetSp(0x10000); 264 regs_.set_sp(0x10000);
265 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 265 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
266 266
267 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 267 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
@@ -288,8 +288,8 @@ TEST_F(UnwinderTest, non_zero_load_bias) {
288TEST_F(UnwinderTest, non_zero_elf_offset) { 288TEST_F(UnwinderTest, non_zero_elf_offset) {
289 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 289 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
290 290
291 regs_.FakeSetPc(0xa7500); 291 regs_.set_pc(0xa7500);
292 regs_.FakeSetSp(0x10000); 292 regs_.set_sp(0x10000);
293 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 293 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
294 294
295 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 295 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
@@ -316,8 +316,8 @@ TEST_F(UnwinderTest, non_zero_elf_offset) {
316TEST_F(UnwinderTest, non_zero_map_offset) { 316TEST_F(UnwinderTest, non_zero_map_offset) {
317 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 317 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
318 318
319 regs_.FakeSetPc(0x43000); 319 regs_.set_pc(0x43000);
320 regs_.FakeSetSp(0x10000); 320 regs_.set_sp(0x10000);
321 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 321 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
322 322
323 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 323 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
@@ -349,8 +349,8 @@ TEST_F(UnwinderTest, no_frames_after_finished) {
349 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3)); 349 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
350 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4)); 350 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
351 351
352 regs_.FakeSetPc(0x1000); 352 regs_.set_pc(0x1000);
353 regs_.FakeSetSp(0x10000); 353 regs_.set_sp(0x10000);
354 ElfInterfaceFake::FakePushStepData(StepData(0x1000, 0x10000, true)); 354 ElfInterfaceFake::FakePushStepData(StepData(0x1000, 0x10000, true));
355 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false)); 355 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
356 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false)); 356 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
@@ -383,8 +383,8 @@ TEST_F(UnwinderTest, max_frames) {
383 ElfInterfaceFake::FakePushStepData(StepData(0x1102 + i * 0x100, 0x10010 + i * 0x10, false)); 383 ElfInterfaceFake::FakePushStepData(StepData(0x1102 + i * 0x100, 0x10010 + i * 0x10, false));
384 } 384 }
385 385
386 regs_.FakeSetPc(0x1000); 386 regs_.set_pc(0x1000);
387 regs_.FakeSetSp(0x10000); 387 regs_.set_sp(0x10000);
388 388
389 Unwinder unwinder(20, &maps_, &regs_, process_memory_); 389 Unwinder unwinder(20, &maps_, &regs_, process_memory_);
390 unwinder.Unwind(); 390 unwinder.Unwind();
@@ -415,8 +415,8 @@ TEST_F(UnwinderTest, verify_frames_skipped) {
415 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 415 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
416 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); 416 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
417 417
418 regs_.FakeSetPc(0x20000); 418 regs_.set_pc(0x20000);
419 regs_.FakeSetSp(0x10000); 419 regs_.set_sp(0x10000);
420 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false)); 420 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
421 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false)); 421 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
422 ElfInterfaceFake::FakePushStepData(StepData(0x20002, 0x10030, false)); 422 ElfInterfaceFake::FakePushStepData(StepData(0x20002, 0x10030, false));
@@ -481,8 +481,8 @@ TEST_F(UnwinderTest, sp_not_in_map) {
481 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 481 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
482 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 482 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
483 483
484 regs_.FakeSetPc(0x1000); 484 regs_.set_pc(0x1000);
485 regs_.FakeSetSp(0x63000); 485 regs_.set_sp(0x63000);
486 ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false)); 486 ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false));
487 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 487 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
488 488
@@ -527,8 +527,8 @@ TEST_F(UnwinderTest, pc_in_device_stops_unwind) {
527 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 527 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
528 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); 528 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
529 529
530 regs_.FakeSetPc(0x13000); 530 regs_.set_pc(0x13000);
531 regs_.FakeSetSp(0x10000); 531 regs_.set_sp(0x10000);
532 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false)); 532 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
533 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false)); 533 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
534 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 534 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -546,8 +546,8 @@ TEST_F(UnwinderTest, sp_in_device_stops_unwind) {
546 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 546 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
547 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); 547 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
548 548
549 regs_.FakeSetPc(0x1000); 549 regs_.set_pc(0x1000);
550 regs_.FakeSetSp(0x13000); 550 regs_.set_sp(0x13000);
551 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false)); 551 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
552 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false)); 552 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
553 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 553 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -563,8 +563,8 @@ TEST_F(UnwinderTest, sp_in_device_stops_unwind) {
563TEST_F(UnwinderTest, pc_without_map) { 563TEST_F(UnwinderTest, pc_without_map) {
564 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 564 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
565 565
566 regs_.FakeSetPc(0x41000); 566 regs_.set_pc(0x41000);
567 regs_.FakeSetSp(0x13000); 567 regs_.set_sp(0x13000);
568 568
569 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 569 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
570 unwinder.Unwind(); 570 unwinder.Unwind();
@@ -593,8 +593,8 @@ TEST_F(UnwinderTest, speculative_frame) {
593 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 593 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
594 594
595 // Fake as if code called a nullptr function. 595 // Fake as if code called a nullptr function.
596 regs_.FakeSetPc(0); 596 regs_.set_pc(0);
597 regs_.FakeSetSp(0x10000); 597 regs_.set_sp(0x10000);
598 regs_.FakeSetReturnAddress(0x1202); 598 regs_.FakeSetReturnAddress(0x1202);
599 regs_.FakeSetReturnAddressValid(true); 599 regs_.FakeSetReturnAddressValid(true);
600 600
@@ -657,8 +657,8 @@ TEST_F(UnwinderTest, speculative_frame_removed) {
657 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 657 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
658 658
659 // Fake as if code called a nullptr function. 659 // Fake as if code called a nullptr function.
660 regs_.FakeSetPc(0); 660 regs_.set_pc(0);
661 regs_.FakeSetSp(0x10000); 661 regs_.set_sp(0x10000);
662 regs_.FakeSetReturnAddress(0x1202); 662 regs_.FakeSetReturnAddress(0x1202);
663 regs_.FakeSetReturnAddressValid(true); 663 regs_.FakeSetReturnAddressValid(true);
664 664
@@ -691,8 +691,8 @@ TEST_F(UnwinderTest, map_ignore_suffixes) {
691 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3)); 691 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
692 692
693 // Fake as if code called a nullptr function. 693 // Fake as if code called a nullptr function.
694 regs_.FakeSetPc(0x1000); 694 regs_.set_pc(0x1000);
695 regs_.FakeSetSp(0x10000); 695 regs_.set_sp(0x10000);
696 ElfInterfaceFake::FakePushStepData(StepData(0x43402, 0x10010, false)); 696 ElfInterfaceFake::FakePushStepData(StepData(0x43402, 0x10010, false));
697 ElfInterfaceFake::FakePushStepData(StepData(0x53502, 0x10020, false)); 697 ElfInterfaceFake::FakePushStepData(StepData(0x53502, 0x10020, false));
698 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 698 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -745,8 +745,8 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) {
745 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3)); 745 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
746 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4)); 746 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
747 747
748 regs_.FakeSetPc(0x1000); 748 regs_.set_pc(0x1000);
749 regs_.FakeSetSp(0x10000); 749 regs_.set_sp(0x10000);
750 ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false)); 750 ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
751 ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false)); 751 ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
752 ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false)); 752 ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
@@ -805,8 +805,8 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) {
805 805
806TEST_F(UnwinderTest, dex_pc_in_map) { 806TEST_F(UnwinderTest, dex_pc_in_map) {
807 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 807 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
808 regs_.FakeSetPc(0x1000); 808 regs_.set_pc(0x1000);
809 regs_.FakeSetSp(0x10000); 809 regs_.set_sp(0x10000);
810 regs_.FakeSetDexPc(0xa3400); 810 regs_.FakeSetDexPc(0xa3400);
811 811
812 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 812 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
@@ -846,8 +846,8 @@ TEST_F(UnwinderTest, dex_pc_in_map) {
846 846
847TEST_F(UnwinderTest, dex_pc_not_in_map) { 847TEST_F(UnwinderTest, dex_pc_not_in_map) {
848 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 848 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
849 regs_.FakeSetPc(0x1000); 849 regs_.set_pc(0x1000);
850 regs_.FakeSetSp(0x10000); 850 regs_.set_sp(0x10000);
851 regs_.FakeSetDexPc(0x50000); 851 regs_.FakeSetDexPc(0x50000);
852 852
853 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 853 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
@@ -888,8 +888,8 @@ TEST_F(UnwinderTest, dex_pc_not_in_map) {
888TEST_F(UnwinderTest, dex_pc_multiple_frames) { 888TEST_F(UnwinderTest, dex_pc_multiple_frames) {
889 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 889 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
890 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); 890 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
891 regs_.FakeSetPc(0x1000); 891 regs_.set_pc(0x1000);
892 regs_.FakeSetSp(0x10000); 892 regs_.set_sp(0x10000);
893 regs_.FakeSetDexPc(0xa3400); 893 regs_.FakeSetDexPc(0xa3400);
894 ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false)); 894 ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
895 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); 895 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data
new file mode 100644
index 000000000..300646b7b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data
new file mode 100644
index 000000000..999cb790a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data
new file mode 100644
index 000000000..6aa1c824f
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data
new file mode 100644
index 000000000..19d7b65cf
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data
new file mode 100644
index 000000000..edcd3e169
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so
new file mode 100644
index 000000000..09ba49532
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so
new file mode 100644
index 000000000..39c9025db
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
new file mode 100644
index 000000000..55aaaf63f
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
@@ -0,0 +1,3 @@
1d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
2e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
3e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
new file mode 100644
index 000000000..0b518143a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
@@ -0,0 +1,16 @@
1r0: e814103c
2r1: 12dcf218
3r2: 1a90df75
4r3: ffffffbf
5r4: 0
6r5: 12dc0800
7r6: 12dcf218
8r7: 1a90df75
9r8: 0
10r9: dd23cc00
11r10: 1c
12r11: cd4ff16c
13ip: 0
14sp: cd4ff140
15lr: d025cdd7
16pc: d025c788
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data
new file mode 100644
index 000000000..f00917b77
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data
Binary files differ