Split arch data into separate files.
Add an ArchEnum to express the arch of the Elf objects and Reg objects.
Split out the regs code into per arch pieces and generic parts.
Also, split out the header files for each arch.
Do not break out the test code yet, there isn't enough and it doesn't
help to maintain the tests.
Test: libunwindstack/libbacktrace/debuggerd unit tests pass.
Test: Running debuggerd -b <PIDS> yields valid data on bullhead.
Change-Id: If61f6c730c9ff2249f986b41de8c4d62f7158325
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 3a38839..d61384e 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -99,8 +99,7 @@
// one extra function call appearing in the unwind.
unwindstack::RegsGetLocal(regs.get());
} else {
- regs.reset(
- unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentMachineType(), ucontext));
+ regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
}
error_ = BACKTRACE_UNWIND_NO_ERROR;
@@ -120,8 +119,7 @@
if (context == nullptr) {
regs.reset(unwindstack::Regs::RemoteGet(Tid()));
} else {
- regs.reset(
- unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentMachineType(), context));
+ regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), context));
}
error_ = BACKTRACE_UNWIND_NO_ERROR;
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 74930d6..4125b12 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -60,6 +60,10 @@
"Maps.cpp",
"Memory.cpp",
"Regs.cpp",
+ "RegsArm.cpp",
+ "RegsArm64.cpp",
+ "RegsX86.cpp",
+ "RegsX86_64.cpp",
"Unwinder.cpp",
"Symbols.cpp",
],
diff --git a/libunwindstack/ArmExidx.cpp b/libunwindstack/ArmExidx.cpp
index fed3e0e..6b0646f 100644
--- a/libunwindstack/ArmExidx.cpp
+++ b/libunwindstack/ArmExidx.cpp
@@ -23,11 +23,11 @@
#include <unwindstack/Log.h>
#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
#include "ArmExidx.h"
#include "Check.h"
-#include "Machine.h"
+#include "MachineArm.h"
namespace unwindstack {
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 5f307ed..025429f 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -31,7 +31,6 @@
#include <unwindstack/Regs.h>
#include "ElfInterfaceArm.h"
-#include "Machine.h"
#include "Symbols.h"
namespace unwindstack {
@@ -183,18 +182,15 @@
return nullptr;
}
- if (e_machine != EM_ARM && e_machine != EM_386) {
- // Unsupported.
- ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine);
- return nullptr;
- }
-
machine_type_ = e_machine;
if (e_machine == EM_ARM) {
+ arch_ = ARCH_ARM;
interface.reset(new ElfInterfaceArm(memory));
} else if (e_machine == EM_386) {
+ arch_ = ARCH_X86;
interface.reset(new ElfInterface32(memory));
} else {
+ // Unsupported.
ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine);
return nullptr;
}
@@ -203,12 +199,17 @@
if (!memory->ReadFully(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
return nullptr;
}
- if (e_machine != EM_AARCH64 && e_machine != EM_X86_64) {
+
+ machine_type_ = e_machine;
+ if (e_machine == EM_AARCH64) {
+ arch_ = ARCH_ARM64;
+ } else if (e_machine == EM_X86_64) {
+ arch_ = ARCH_X86_64;
+ } else {
// Unsupported.
ALOGI("64 bit elf that is neither aarch64 nor x86_64: e_machine = %d\n", e_machine);
return nullptr;
}
- machine_type_ = e_machine;
interface.reset(new ElfInterface64(memory));
}
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index 170a5cd..9841e24 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -18,11 +18,11 @@
#include <stdint.h>
#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
#include "ArmExidx.h"
#include "ElfInterfaceArm.h"
-#include "Machine.h"
+#include "MachineArm.h"
namespace unwindstack {
diff --git a/libunwindstack/Machine.h b/libunwindstack/Machine.h
deleted file mode 100644
index 1fb9309..0000000
--- a/libunwindstack/Machine.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _LIBUNWINDSTACK_MACHINE_H
-#define _LIBUNWINDSTACK_MACHINE_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-enum ArmReg : uint16_t {
- ARM_REG_R0 = 0,
- ARM_REG_R1,
- ARM_REG_R2,
- ARM_REG_R3,
- ARM_REG_R4,
- ARM_REG_R5,
- ARM_REG_R6,
- ARM_REG_R7,
- ARM_REG_R8,
- ARM_REG_R9,
- ARM_REG_R10,
- ARM_REG_R11,
- ARM_REG_R12,
- ARM_REG_R13,
- ARM_REG_R14,
- ARM_REG_R15,
- ARM_REG_LAST,
-
- ARM_REG_SP = ARM_REG_R13,
- ARM_REG_LR = ARM_REG_R14,
- ARM_REG_PC = ARM_REG_R15,
-};
-
-enum Arm64Reg : uint16_t {
- ARM64_REG_R0 = 0,
- ARM64_REG_R1,
- ARM64_REG_R2,
- ARM64_REG_R3,
- ARM64_REG_R4,
- ARM64_REG_R5,
- ARM64_REG_R6,
- ARM64_REG_R7,
- ARM64_REG_R8,
- ARM64_REG_R9,
- ARM64_REG_R10,
- ARM64_REG_R11,
- ARM64_REG_R12,
- ARM64_REG_R13,
- ARM64_REG_R14,
- ARM64_REG_R15,
- ARM64_REG_R16,
- ARM64_REG_R17,
- ARM64_REG_R18,
- ARM64_REG_R19,
- ARM64_REG_R20,
- ARM64_REG_R21,
- ARM64_REG_R22,
- ARM64_REG_R23,
- ARM64_REG_R24,
- ARM64_REG_R25,
- ARM64_REG_R26,
- ARM64_REG_R27,
- ARM64_REG_R28,
- ARM64_REG_R29,
- ARM64_REG_R30,
- ARM64_REG_R31,
- ARM64_REG_PC,
- ARM64_REG_LAST,
-
- ARM64_REG_SP = ARM64_REG_R31,
- ARM64_REG_LR = ARM64_REG_R30,
-};
-
-// Matches the numbers for the registers as generated by compilers.
-// If this is changed, then unwinding will fail.
-enum X86Reg : uint16_t {
- X86_REG_EAX = 0,
- X86_REG_ECX = 1,
- X86_REG_EDX = 2,
- X86_REG_EBX = 3,
- X86_REG_ESP = 4,
- X86_REG_EBP = 5,
- X86_REG_ESI = 6,
- X86_REG_EDI = 7,
- X86_REG_EIP = 8,
- X86_REG_EFL = 9,
- X86_REG_CS = 10,
- X86_REG_SS = 11,
- X86_REG_DS = 12,
- X86_REG_ES = 13,
- X86_REG_FS = 14,
- X86_REG_GS = 15,
- X86_REG_LAST,
-
- X86_REG_SP = X86_REG_ESP,
- X86_REG_PC = X86_REG_EIP,
-};
-
-// Matches the numbers for the registers as generated by compilers.
-// If this is changed, then unwinding will fail.
-enum X86_64Reg : uint16_t {
- X86_64_REG_RAX = 0,
- X86_64_REG_RDX = 1,
- X86_64_REG_RCX = 2,
- X86_64_REG_RBX = 3,
- X86_64_REG_RSI = 4,
- X86_64_REG_RDI = 5,
- X86_64_REG_RBP = 6,
- X86_64_REG_RSP = 7,
- X86_64_REG_R8 = 8,
- X86_64_REG_R9 = 9,
- X86_64_REG_R10 = 10,
- X86_64_REG_R11 = 11,
- X86_64_REG_R12 = 12,
- X86_64_REG_R13 = 13,
- X86_64_REG_R14 = 14,
- X86_64_REG_R15 = 15,
- X86_64_REG_RIP = 16,
- X86_64_REG_LAST,
-
- X86_64_REG_SP = X86_64_REG_RSP,
- X86_64_REG_PC = X86_64_REG_RIP,
-};
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_MACHINE_H
diff --git a/libunwindstack/MachineArm.h b/libunwindstack/MachineArm.h
new file mode 100644
index 0000000..3f902b1
--- /dev/null
+++ b/libunwindstack/MachineArm.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_MACHINE_ARM_H
+#define _LIBUNWINDSTACK_MACHINE_ARM_H
+
+#include <stdint.h>
+
+namespace unwindstack {
+
+enum ArmReg : uint16_t {
+ ARM_REG_R0 = 0,
+ ARM_REG_R1,
+ ARM_REG_R2,
+ ARM_REG_R3,
+ ARM_REG_R4,
+ ARM_REG_R5,
+ ARM_REG_R6,
+ ARM_REG_R7,
+ ARM_REG_R8,
+ ARM_REG_R9,
+ ARM_REG_R10,
+ ARM_REG_R11,
+ ARM_REG_R12,
+ ARM_REG_R13,
+ ARM_REG_R14,
+ ARM_REG_R15,
+ ARM_REG_LAST,
+
+ ARM_REG_SP = ARM_REG_R13,
+ ARM_REG_LR = ARM_REG_R14,
+ ARM_REG_PC = ARM_REG_R15,
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_MACHINE_ARM_H
diff --git a/libunwindstack/MachineArm64.h b/libunwindstack/MachineArm64.h
new file mode 100644
index 0000000..e8b778b
--- /dev/null
+++ b/libunwindstack/MachineArm64.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_MACHINE_ARM64_H
+#define _LIBUNWINDSTACK_MACHINE_ARM64_H
+
+#include <stdint.h>
+
+namespace unwindstack {
+
+enum Arm64Reg : uint16_t {
+ ARM64_REG_R0 = 0,
+ ARM64_REG_R1,
+ ARM64_REG_R2,
+ ARM64_REG_R3,
+ ARM64_REG_R4,
+ ARM64_REG_R5,
+ ARM64_REG_R6,
+ ARM64_REG_R7,
+ ARM64_REG_R8,
+ ARM64_REG_R9,
+ ARM64_REG_R10,
+ ARM64_REG_R11,
+ ARM64_REG_R12,
+ ARM64_REG_R13,
+ ARM64_REG_R14,
+ ARM64_REG_R15,
+ ARM64_REG_R16,
+ ARM64_REG_R17,
+ ARM64_REG_R18,
+ ARM64_REG_R19,
+ ARM64_REG_R20,
+ ARM64_REG_R21,
+ ARM64_REG_R22,
+ ARM64_REG_R23,
+ ARM64_REG_R24,
+ ARM64_REG_R25,
+ ARM64_REG_R26,
+ ARM64_REG_R27,
+ ARM64_REG_R28,
+ ARM64_REG_R29,
+ ARM64_REG_R30,
+ ARM64_REG_R31,
+ ARM64_REG_PC,
+ ARM64_REG_LAST,
+
+ ARM64_REG_SP = ARM64_REG_R31,
+ ARM64_REG_LR = ARM64_REG_R30,
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_MACHINE_ARM64_H
diff --git a/libunwindstack/MachineX86.h b/libunwindstack/MachineX86.h
new file mode 100644
index 0000000..02adb98
--- /dev/null
+++ b/libunwindstack/MachineX86.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_MACHINE_X86_H
+#define _LIBUNWINDSTACK_MACHINE_X86_H
+
+#include <stdint.h>
+
+namespace unwindstack {
+
+// Matches the numbers for the registers as generated by compilers.
+// If this is changed, then unwinding will fail.
+enum X86Reg : uint16_t {
+ X86_REG_EAX = 0,
+ X86_REG_ECX = 1,
+ X86_REG_EDX = 2,
+ X86_REG_EBX = 3,
+ X86_REG_ESP = 4,
+ X86_REG_EBP = 5,
+ X86_REG_ESI = 6,
+ X86_REG_EDI = 7,
+ X86_REG_EIP = 8,
+ X86_REG_EFL = 9,
+ X86_REG_CS = 10,
+ X86_REG_SS = 11,
+ X86_REG_DS = 12,
+ X86_REG_ES = 13,
+ X86_REG_FS = 14,
+ X86_REG_GS = 15,
+ X86_REG_LAST,
+
+ X86_REG_SP = X86_REG_ESP,
+ X86_REG_PC = X86_REG_EIP,
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_MACHINE_X86_H
diff --git a/libunwindstack/MachineX86_64.h b/libunwindstack/MachineX86_64.h
new file mode 100644
index 0000000..af33fea
--- /dev/null
+++ b/libunwindstack/MachineX86_64.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_MACHINE_X86_64_H
+#define _LIBUNWINDSTACK_MACHINE_X86_64_H
+
+#include <stdint.h>
+
+namespace unwindstack {
+
+// Matches the numbers for the registers as generated by compilers.
+// If this is changed, then unwinding will fail.
+enum X86_64Reg : uint16_t {
+ X86_64_REG_RAX = 0,
+ X86_64_REG_RDX = 1,
+ X86_64_REG_RCX = 2,
+ X86_64_REG_RBX = 3,
+ X86_64_REG_RSI = 4,
+ X86_64_REG_RDI = 5,
+ X86_64_REG_RBP = 6,
+ X86_64_REG_RSP = 7,
+ X86_64_REG_R8 = 8,
+ X86_64_REG_R9 = 9,
+ X86_64_REG_R10 = 10,
+ X86_64_REG_R11 = 11,
+ X86_64_REG_R12 = 12,
+ X86_64_REG_R13 = 13,
+ X86_64_REG_R14 = 14,
+ X86_64_REG_R15 = 15,
+ X86_64_REG_RIP = 16,
+ X86_64_REG_LAST,
+
+ X86_64_REG_SP = X86_64_REG_RSP,
+ X86_64_REG_PC = X86_64_REG_RIP,
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_MACHINE_X86_64_H
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index 28a77dc..29dbf9d 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <elf.h>
#include <stdint.h>
#include <sys/ptrace.h>
#include <sys/uio.h>
@@ -23,315 +22,21 @@
#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
-#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
-#include "Check.h"
-#include "Machine.h"
-#include "Ucontext.h"
-#include "User.h"
+#include "UserArm.h"
+#include "UserArm64.h"
+#include "UserX86.h"
+#include "UserX86_64.h"
namespace unwindstack {
-RegsArm::RegsArm()
- : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
-
-uint32_t RegsArm::MachineType() {
- return EM_ARM;
-}
-
-uint64_t RegsArm::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
- }
-
- uint64_t load_bias = elf->GetLoadBias();
- if (rel_pc < load_bias) {
- return rel_pc;
- }
- uint64_t adjusted_rel_pc = rel_pc - load_bias;
-
- if (adjusted_rel_pc < 5) {
- return rel_pc;
- }
-
- if (adjusted_rel_pc & 1) {
- // This is a thumb instruction, it could be 2 or 4 bytes.
- uint32_t value;
- if (rel_pc < 5 || !elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) ||
- (value & 0xe000f000) != 0xe000f000) {
- return rel_pc - 2;
- }
- }
- return rel_pc - 4;
-}
-
-void RegsArm::SetFromRaw() {
- set_pc(regs_[ARM_REG_PC]);
- set_sp(regs_[ARM_REG_SP]);
-}
-
-bool RegsArm::SetPcFromReturnAddress(Memory*) {
- if (pc() == regs_[ARM_REG_LR]) {
- return false;
- }
-
- set_pc(regs_[ARM_REG_LR]);
- return true;
-}
-
-void RegsArm::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("r0", regs_[ARM_REG_R0]);
- fn("r1", regs_[ARM_REG_R1]);
- fn("r2", regs_[ARM_REG_R2]);
- fn("r3", regs_[ARM_REG_R3]);
- fn("r4", regs_[ARM_REG_R4]);
- fn("r5", regs_[ARM_REG_R5]);
- fn("r6", regs_[ARM_REG_R6]);
- fn("r7", regs_[ARM_REG_R7]);
- fn("r8", regs_[ARM_REG_R8]);
- fn("r9", regs_[ARM_REG_R9]);
- fn("r10", regs_[ARM_REG_R10]);
- fn("r11", regs_[ARM_REG_R11]);
- fn("ip", regs_[ARM_REG_R12]);
- fn("sp", regs_[ARM_REG_SP]);
- fn("lr", regs_[ARM_REG_LR]);
- fn("pc", regs_[ARM_REG_PC]);
-}
-
-RegsArm64::RegsArm64()
- : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
-
-uint32_t RegsArm64::MachineType() {
- return EM_AARCH64;
-}
-
-uint64_t RegsArm64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
- }
-
- if (rel_pc < 4) {
- return rel_pc;
- }
- return rel_pc - 4;
-}
-
-void RegsArm64::SetFromRaw() {
- set_pc(regs_[ARM64_REG_PC]);
- set_sp(regs_[ARM64_REG_SP]);
-}
-
-bool RegsArm64::SetPcFromReturnAddress(Memory*) {
- if (pc() == regs_[ARM64_REG_LR]) {
- return false;
- }
-
- set_pc(regs_[ARM64_REG_LR]);
- return true;
-}
-
-void RegsArm64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("x0", regs_[ARM64_REG_R0]);
- fn("x1", regs_[ARM64_REG_R1]);
- fn("x2", regs_[ARM64_REG_R2]);
- fn("x3", regs_[ARM64_REG_R3]);
- fn("x4", regs_[ARM64_REG_R4]);
- fn("x5", regs_[ARM64_REG_R5]);
- fn("x6", regs_[ARM64_REG_R6]);
- fn("x7", regs_[ARM64_REG_R7]);
- fn("x8", regs_[ARM64_REG_R8]);
- fn("x9", regs_[ARM64_REG_R9]);
- fn("x10", regs_[ARM64_REG_R10]);
- fn("x11", regs_[ARM64_REG_R11]);
- fn("x12", regs_[ARM64_REG_R12]);
- fn("x13", regs_[ARM64_REG_R13]);
- fn("x14", regs_[ARM64_REG_R14]);
- fn("x15", regs_[ARM64_REG_R15]);
- fn("x16", regs_[ARM64_REG_R16]);
- fn("x17", regs_[ARM64_REG_R17]);
- fn("x18", regs_[ARM64_REG_R18]);
- fn("x19", regs_[ARM64_REG_R19]);
- fn("x20", regs_[ARM64_REG_R20]);
- fn("x21", regs_[ARM64_REG_R21]);
- fn("x22", regs_[ARM64_REG_R22]);
- fn("x23", regs_[ARM64_REG_R23]);
- fn("x24", regs_[ARM64_REG_R24]);
- fn("x25", regs_[ARM64_REG_R25]);
- fn("x26", regs_[ARM64_REG_R26]);
- fn("x27", regs_[ARM64_REG_R27]);
- fn("x28", regs_[ARM64_REG_R28]);
- fn("x29", regs_[ARM64_REG_R29]);
- fn("sp", regs_[ARM64_REG_SP]);
- fn("lr", regs_[ARM64_REG_LR]);
- fn("pc", regs_[ARM64_REG_PC]);
-}
-
-RegsX86::RegsX86()
- : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
-
-uint32_t RegsX86::MachineType() {
- return EM_386;
-}
-
-uint64_t RegsX86::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
- }
-
- if (rel_pc == 0) {
- return 0;
- }
- return rel_pc - 1;
-}
-
-void RegsX86::SetFromRaw() {
- set_pc(regs_[X86_REG_PC]);
- set_sp(regs_[X86_REG_SP]);
-}
-
-bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
- // Attempt to get the return address from the top of the stack.
- uint32_t new_pc;
- if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
- return false;
- }
-
- set_pc(new_pc);
- return true;
-}
-
-void RegsX86::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("eax", regs_[X86_REG_EAX]);
- fn("ebx", regs_[X86_REG_EBX]);
- fn("ecx", regs_[X86_REG_ECX]);
- fn("edx", regs_[X86_REG_EDX]);
- fn("ebp", regs_[X86_REG_EBP]);
- fn("edi", regs_[X86_REG_EDI]);
- fn("esi", regs_[X86_REG_ESI]);
- fn("esp", regs_[X86_REG_ESP]);
- fn("eip", regs_[X86_REG_EIP]);
-}
-
-RegsX86_64::RegsX86_64()
- : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
-
-uint32_t RegsX86_64::MachineType() {
- return EM_X86_64;
-}
-
-uint64_t RegsX86_64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
- }
-
- if (rel_pc == 0) {
- return 0;
- }
-
- return rel_pc - 1;
-}
-
-void RegsX86_64::SetFromRaw() {
- set_pc(regs_[X86_64_REG_PC]);
- set_sp(regs_[X86_64_REG_SP]);
-}
-
-bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
- // Attempt to get the return address from the top of the stack.
- uint64_t new_pc;
- if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
- return false;
- }
-
- set_pc(new_pc);
- return true;
-}
-
-void RegsX86_64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
- fn("rax", regs_[X86_64_REG_RAX]);
- fn("rbx", regs_[X86_64_REG_RBX]);
- fn("rcx", regs_[X86_64_REG_RCX]);
- fn("rdx", regs_[X86_64_REG_RDX]);
- fn("r8", regs_[X86_64_REG_R8]);
- fn("r9", regs_[X86_64_REG_R9]);
- fn("r10", regs_[X86_64_REG_R10]);
- fn("r11", regs_[X86_64_REG_R11]);
- fn("r12", regs_[X86_64_REG_R12]);
- fn("r13", regs_[X86_64_REG_R13]);
- fn("r14", regs_[X86_64_REG_R14]);
- fn("r15", regs_[X86_64_REG_R15]);
- fn("rdi", regs_[X86_64_REG_RDI]);
- fn("rsi", regs_[X86_64_REG_RSI]);
- fn("rbp", regs_[X86_64_REG_RBP]);
- fn("rsp", regs_[X86_64_REG_RSP]);
- fn("rip", regs_[X86_64_REG_RIP]);
-}
-
-static Regs* ReadArm(void* remote_data) {
- arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
-
- RegsArm* regs = new RegsArm();
- memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
- regs->SetFromRaw();
- return regs;
-}
-
-static Regs* ReadArm64(void* remote_data) {
- arm64_user_regs* user = reinterpret_cast<arm64_user_regs*>(remote_data);
-
- RegsArm64* regs = new RegsArm64();
- memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
- uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
- reg_data[ARM64_REG_PC] = user->pc;
- reg_data[ARM64_REG_SP] = user->sp;
- regs->SetFromRaw();
- return regs;
-}
-
-static Regs* ReadX86(void* remote_data) {
- x86_user_regs* user = reinterpret_cast<x86_user_regs*>(remote_data);
-
- RegsX86* regs = new RegsX86();
- (*regs)[X86_REG_EAX] = user->eax;
- (*regs)[X86_REG_EBX] = user->ebx;
- (*regs)[X86_REG_ECX] = user->ecx;
- (*regs)[X86_REG_EDX] = user->edx;
- (*regs)[X86_REG_EBP] = user->ebp;
- (*regs)[X86_REG_EDI] = user->edi;
- (*regs)[X86_REG_ESI] = user->esi;
- (*regs)[X86_REG_ESP] = user->esp;
- (*regs)[X86_REG_EIP] = user->eip;
-
- regs->SetFromRaw();
- return regs;
-}
-
-static Regs* ReadX86_64(void* remote_data) {
- x86_64_user_regs* user = reinterpret_cast<x86_64_user_regs*>(remote_data);
-
- RegsX86_64* regs = new RegsX86_64();
- (*regs)[X86_64_REG_RAX] = user->rax;
- (*regs)[X86_64_REG_RBX] = user->rbx;
- (*regs)[X86_64_REG_RCX] = user->rcx;
- (*regs)[X86_64_REG_RDX] = user->rdx;
- (*regs)[X86_64_REG_R8] = user->r8;
- (*regs)[X86_64_REG_R9] = user->r9;
- (*regs)[X86_64_REG_R10] = user->r10;
- (*regs)[X86_64_REG_R11] = user->r11;
- (*regs)[X86_64_REG_R12] = user->r12;
- (*regs)[X86_64_REG_R13] = user->r13;
- (*regs)[X86_64_REG_R14] = user->r14;
- (*regs)[X86_64_REG_R15] = user->r15;
- (*regs)[X86_64_REG_RDI] = user->rdi;
- (*regs)[X86_64_REG_RSI] = user->rsi;
- (*regs)[X86_64_REG_RBP] = user->rbp;
- (*regs)[X86_64_REG_RSP] = user->rsp;
- (*regs)[X86_64_REG_RIP] = user->rip;
-
- regs->SetFromRaw();
- return regs;
-}
+// The largest user structure.
+constexpr size_t MAX_USER_REGS_SIZE = sizeof(arm64_user_regs) + 10;
// This function assumes that reg_data is already aligned to a 64 bit value.
// If not this could crash with an unaligned access.
@@ -348,106 +53,42 @@
switch (io.iov_len) {
case sizeof(x86_user_regs):
- return ReadX86(buffer.data());
+ return RegsX86::Read(buffer.data());
case sizeof(x86_64_user_regs):
- return ReadX86_64(buffer.data());
+ return RegsX86_64::Read(buffer.data());
case sizeof(arm_user_regs):
- return ReadArm(buffer.data());
+ return RegsArm::Read(buffer.data());
case sizeof(arm64_user_regs):
- return ReadArm64(buffer.data());
+ return RegsArm64::Read(buffer.data());
}
return nullptr;
}
-static Regs* CreateFromArmUcontext(void* ucontext) {
- arm_ucontext_t* arm_ucontext = reinterpret_cast<arm_ucontext_t*>(ucontext);
-
- RegsArm* regs = new RegsArm();
- memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
- regs->SetFromRaw();
- return regs;
-}
-
-static Regs* CreateFromArm64Ucontext(void* ucontext) {
- arm64_ucontext_t* arm64_ucontext = reinterpret_cast<arm64_ucontext_t*>(ucontext);
-
- RegsArm64* regs = new RegsArm64();
- memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
- regs->SetFromRaw();
- return regs;
-}
-
-void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) {
- // Put the registers in the expected order.
- regs_[X86_REG_EDI] = ucontext->uc_mcontext.edi;
- regs_[X86_REG_ESI] = ucontext->uc_mcontext.esi;
- regs_[X86_REG_EBP] = ucontext->uc_mcontext.ebp;
- regs_[X86_REG_ESP] = ucontext->uc_mcontext.esp;
- regs_[X86_REG_EBX] = ucontext->uc_mcontext.ebx;
- regs_[X86_REG_EDX] = ucontext->uc_mcontext.edx;
- regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx;
- regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax;
- regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip;
- SetFromRaw();
-}
-
-static Regs* CreateFromX86Ucontext(void* ucontext) {
- x86_ucontext_t* x86_ucontext = reinterpret_cast<x86_ucontext_t*>(ucontext);
-
- RegsX86* regs = new RegsX86();
- regs->SetFromUcontext(x86_ucontext);
- return regs;
-}
-
-void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
- // R8-R15
- memcpy(®s_[X86_64_REG_R8], &ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));
-
- // Rest of the registers.
- regs_[X86_64_REG_RDI] = ucontext->uc_mcontext.rdi;
- regs_[X86_64_REG_RSI] = ucontext->uc_mcontext.rsi;
- regs_[X86_64_REG_RBP] = ucontext->uc_mcontext.rbp;
- regs_[X86_64_REG_RBX] = ucontext->uc_mcontext.rbx;
- regs_[X86_64_REG_RDX] = ucontext->uc_mcontext.rdx;
- regs_[X86_64_REG_RAX] = ucontext->uc_mcontext.rax;
- regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
- regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
- regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
-
- SetFromRaw();
-}
-
-static Regs* CreateFromX86_64Ucontext(void* ucontext) {
- x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);
-
- RegsX86_64* regs = new RegsX86_64();
- regs->SetFromUcontext(x86_64_ucontext);
- return regs;
-}
-
-Regs* Regs::CreateFromUcontext(uint32_t machine_type, void* ucontext) {
- switch (machine_type) {
- case EM_386:
- return CreateFromX86Ucontext(ucontext);
- case EM_X86_64:
- return CreateFromX86_64Ucontext(ucontext);
- case EM_ARM:
- return CreateFromArmUcontext(ucontext);
- case EM_AARCH64:
- return CreateFromArm64Ucontext(ucontext);
+Regs* Regs::CreateFromUcontext(ArchEnum arch, void* ucontext) {
+ switch (arch) {
+ case ARCH_X86:
+ return RegsX86::CreateFromUcontext(ucontext);
+ case ARCH_X86_64:
+ return RegsX86_64::CreateFromUcontext(ucontext);
+ case ARCH_ARM:
+ return RegsArm::CreateFromUcontext(ucontext);
+ case ARCH_ARM64:
+ return RegsArm64::CreateFromUcontext(ucontext);
+ case ARCH_UNKNOWN:
+ default:
+ return nullptr;
}
- return nullptr;
}
-uint32_t Regs::CurrentMachineType() {
+ArchEnum Regs::CurrentArch() {
#if defined(__arm__)
- return EM_ARM;
+ return ARCH_ARM;
#elif defined(__aarch64__)
- return EM_AARCH64;
+ return ARCH_ARM64;
#elif defined(__i386__)
- return EM_386;
+ return ARCH_X86;
#elif defined(__x86_64__)
- return EM_X86_64;
+ return ARCH_X86_64;
#else
abort();
#endif
@@ -469,192 +110,4 @@
return regs;
}
-bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
- uint32_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
- return false;
- }
-
- uint64_t offset = 0;
- if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
- // non-RT sigreturn call.
- // __restore:
- //
- // Form 1 (arm):
- // 0x77 0x70 mov r7, #0x77
- // 0xa0 0xe3 svc 0x00000000
- //
- // Form 2 (arm):
- // 0x77 0x00 0x90 0xef svc 0x00900077
- //
- // Form 3 (thumb):
- // 0x77 0x27 movs r7, #77
- // 0x00 0xdf svc 0
- if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
- return false;
- }
- if (data == 0x5ac3c35a) {
- // SP + uc_mcontext offset + r0 offset.
- offset = sp() + 0x14 + 0xc;
- } else {
- // SP + r0 offset
- offset = sp() + 0xc;
- }
- } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
- // RT sigreturn call.
- // __restore_rt:
- //
- // Form 1 (arm):
- // 0xad 0x70 mov r7, #0xad
- // 0xa0 0xe3 svc 0x00000000
- //
- // Form 2 (arm):
- // 0xad 0x00 0x90 0xef svc 0x009000ad
- //
- // Form 3 (thumb):
- // 0xad 0x27 movs r7, #ad
- // 0x00 0xdf svc 0
- if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
- return false;
- }
- if (data == sp() + 8) {
- // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
- offset = sp() + 8 + 0x80 + 0x14 + 0xc;
- } else {
- // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
- offset = sp() + 0x80 + 0x14 + 0xc;
- }
- }
- if (offset == 0) {
- return false;
- }
-
- if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
- return false;
- }
- SetFromRaw();
- return true;
-}
-
-bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
- uint64_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
- return false;
- }
-
- // Look for the kernel sigreturn function.
- // __kernel_rt_sigreturn:
- // 0xd2801168 mov x8, #0x8b
- // 0xd4000001 svc #0x0
- if (data != 0xd4000001d2801168ULL) {
- return false;
- }
-
- // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
- if (!process_memory->ReadFully(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
- sizeof(uint64_t) * ARM64_REG_LAST)) {
- return false;
- }
-
- SetFromRaw();
- return true;
-}
-
-bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
- uint64_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
- return false;
- }
-
- if (data == 0x80cd00000077b858ULL) {
- // Without SA_SIGINFO set, the return sequence is:
- //
- // __restore:
- // 0x58 pop %eax
- // 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
- // 0xcd 0x80 int 0x80
- //
- // SP points at arguments:
- // int signum
- // struct sigcontext (same format as mcontext)
- struct x86_mcontext_t context;
- if (!process_memory->ReadFully(sp() + 4, &context, sizeof(context))) {
- return false;
- }
- regs_[X86_REG_EBP] = context.ebp;
- regs_[X86_REG_ESP] = context.esp;
- regs_[X86_REG_EBX] = context.ebx;
- regs_[X86_REG_EDX] = context.edx;
- regs_[X86_REG_ECX] = context.ecx;
- regs_[X86_REG_EAX] = context.eax;
- regs_[X86_REG_EIP] = context.eip;
- SetFromRaw();
- return true;
- } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) {
- // With SA_SIGINFO set, the return sequence is:
- //
- // __restore_rt:
- // 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
- // 0xcd 0x80 int 0x80
- //
- // SP points at arguments:
- // int signum
- // siginfo*
- // ucontext*
-
- // Get the location of the sigcontext data.
- uint32_t ptr;
- if (!process_memory->ReadFully(sp() + 8, &ptr, sizeof(ptr))) {
- return false;
- }
- // Only read the portion of the data structure we care about.
- x86_ucontext_t x86_ucontext;
- if (!process_memory->ReadFully(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
- return false;
- }
- SetFromUcontext(&x86_ucontext);
- return true;
- }
- return false;
-}
-
-bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
- uint64_t data;
- Memory* elf_memory = elf->memory();
- // Read from elf memory since it is usually more expensive to read from
- // process memory.
- if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
- return false;
- }
-
- uint16_t data2;
- if (!elf_memory->ReadFully(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
- return false;
- }
-
- // __restore_rt:
- // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax
- // 0x0f 0x05 syscall
- // 0x0f nopl 0x0($rax)
-
- // Read the mcontext data from the stack.
- // sp points to the ucontext data structure, read only the mcontext part.
- x86_64_ucontext_t x86_64_ucontext;
- if (!process_memory->ReadFully(sp() + 0x28, &x86_64_ucontext.uc_mcontext,
- sizeof(x86_64_mcontext_t))) {
- return false;
- }
- SetFromUcontext(&x86_64_ucontext);
- return true;
-}
-
} // namespace unwindstack
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
new file mode 100644
index 0000000..34f29bd
--- /dev/null
+++ b/libunwindstack/RegsArm.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/RegsArm.h>
+
+#include "MachineArm.h"
+#include "UcontextArm.h"
+#include "UserArm.h"
+
+namespace unwindstack {
+
+RegsArm::RegsArm()
+ : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
+
+ArchEnum RegsArm::Arch() {
+ return ARCH_ARM;
+}
+
+uint64_t RegsArm::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid()) {
+ return rel_pc;
+ }
+
+ uint64_t load_bias = elf->GetLoadBias();
+ if (rel_pc < load_bias) {
+ return rel_pc;
+ }
+ uint64_t adjusted_rel_pc = rel_pc - load_bias;
+
+ if (adjusted_rel_pc < 5) {
+ return rel_pc;
+ }
+
+ if (adjusted_rel_pc & 1) {
+ // This is a thumb instruction, it could be 2 or 4 bytes.
+ uint32_t value;
+ if (rel_pc < 5 || !elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) ||
+ (value & 0xe000f000) != 0xe000f000) {
+ return rel_pc - 2;
+ }
+ }
+ return rel_pc - 4;
+}
+
+void RegsArm::SetFromRaw() {
+ set_pc(regs_[ARM_REG_PC]);
+ set_sp(regs_[ARM_REG_SP]);
+}
+
+bool RegsArm::SetPcFromReturnAddress(Memory*) {
+ if (pc() == regs_[ARM_REG_LR]) {
+ return false;
+ }
+
+ set_pc(regs_[ARM_REG_LR]);
+ return true;
+}
+
+void RegsArm::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+ fn("r0", regs_[ARM_REG_R0]);
+ fn("r1", regs_[ARM_REG_R1]);
+ fn("r2", regs_[ARM_REG_R2]);
+ fn("r3", regs_[ARM_REG_R3]);
+ fn("r4", regs_[ARM_REG_R4]);
+ fn("r5", regs_[ARM_REG_R5]);
+ fn("r6", regs_[ARM_REG_R6]);
+ fn("r7", regs_[ARM_REG_R7]);
+ fn("r8", regs_[ARM_REG_R8]);
+ fn("r9", regs_[ARM_REG_R9]);
+ fn("r10", regs_[ARM_REG_R10]);
+ fn("r11", regs_[ARM_REG_R11]);
+ fn("ip", regs_[ARM_REG_R12]);
+ fn("sp", regs_[ARM_REG_SP]);
+ fn("lr", regs_[ARM_REG_LR]);
+ fn("pc", regs_[ARM_REG_PC]);
+}
+
+Regs* RegsArm::Read(void* remote_data) {
+ arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
+
+ RegsArm* regs = new RegsArm();
+ memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
+ regs->SetFromRaw();
+ return regs;
+}
+
+Regs* RegsArm::CreateFromUcontext(void* ucontext) {
+ arm_ucontext_t* arm_ucontext = reinterpret_cast<arm_ucontext_t*>(ucontext);
+
+ RegsArm* regs = new RegsArm();
+ memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
+ regs->SetFromRaw();
+ return regs;
+}
+
+bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+ uint32_t data;
+ Memory* elf_memory = elf->memory();
+ // Read from elf memory since it is usually more expensive to read from
+ // process memory.
+ if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
+ return false;
+ }
+
+ uint64_t offset = 0;
+ if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
+ // non-RT sigreturn call.
+ // __restore:
+ //
+ // Form 1 (arm):
+ // 0x77 0x70 mov r7, #0x77
+ // 0xa0 0xe3 svc 0x00000000
+ //
+ // Form 2 (arm):
+ // 0x77 0x00 0x90 0xef svc 0x00900077
+ //
+ // Form 3 (thumb):
+ // 0x77 0x27 movs r7, #77
+ // 0x00 0xdf svc 0
+ if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
+ return false;
+ }
+ if (data == 0x5ac3c35a) {
+ // SP + uc_mcontext offset + r0 offset.
+ offset = sp() + 0x14 + 0xc;
+ } else {
+ // SP + r0 offset
+ offset = sp() + 0xc;
+ }
+ } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
+ // RT sigreturn call.
+ // __restore_rt:
+ //
+ // Form 1 (arm):
+ // 0xad 0x70 mov r7, #0xad
+ // 0xa0 0xe3 svc 0x00000000
+ //
+ // Form 2 (arm):
+ // 0xad 0x00 0x90 0xef svc 0x009000ad
+ //
+ // Form 3 (thumb):
+ // 0xad 0x27 movs r7, #ad
+ // 0x00 0xdf svc 0
+ if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
+ return false;
+ }
+ if (data == sp() + 8) {
+ // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
+ offset = sp() + 8 + 0x80 + 0x14 + 0xc;
+ } else {
+ // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
+ offset = sp() + 0x80 + 0x14 + 0xc;
+ }
+ }
+ if (offset == 0) {
+ return false;
+ }
+
+ if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
+ return false;
+ }
+ SetFromRaw();
+ return true;
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
new file mode 100644
index 0000000..2077bc5
--- /dev/null
+++ b/libunwindstack/RegsArm64.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/RegsArm64.h>
+
+#include "MachineArm64.h"
+#include "UcontextArm64.h"
+#include "UserArm64.h"
+
+namespace unwindstack {
+
+RegsArm64::RegsArm64()
+ : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
+
+ArchEnum RegsArm64::Arch() {
+ return ARCH_ARM64;
+}
+
+uint64_t RegsArm64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid()) {
+ return rel_pc;
+ }
+
+ if (rel_pc < 4) {
+ return rel_pc;
+ }
+ return rel_pc - 4;
+}
+
+void RegsArm64::SetFromRaw() {
+ set_pc(regs_[ARM64_REG_PC]);
+ set_sp(regs_[ARM64_REG_SP]);
+}
+
+bool RegsArm64::SetPcFromReturnAddress(Memory*) {
+ if (pc() == regs_[ARM64_REG_LR]) {
+ return false;
+ }
+
+ set_pc(regs_[ARM64_REG_LR]);
+ return true;
+}
+
+void RegsArm64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+ fn("x0", regs_[ARM64_REG_R0]);
+ fn("x1", regs_[ARM64_REG_R1]);
+ fn("x2", regs_[ARM64_REG_R2]);
+ fn("x3", regs_[ARM64_REG_R3]);
+ fn("x4", regs_[ARM64_REG_R4]);
+ fn("x5", regs_[ARM64_REG_R5]);
+ fn("x6", regs_[ARM64_REG_R6]);
+ fn("x7", regs_[ARM64_REG_R7]);
+ fn("x8", regs_[ARM64_REG_R8]);
+ fn("x9", regs_[ARM64_REG_R9]);
+ fn("x10", regs_[ARM64_REG_R10]);
+ fn("x11", regs_[ARM64_REG_R11]);
+ fn("x12", regs_[ARM64_REG_R12]);
+ fn("x13", regs_[ARM64_REG_R13]);
+ fn("x14", regs_[ARM64_REG_R14]);
+ fn("x15", regs_[ARM64_REG_R15]);
+ fn("x16", regs_[ARM64_REG_R16]);
+ fn("x17", regs_[ARM64_REG_R17]);
+ fn("x18", regs_[ARM64_REG_R18]);
+ fn("x19", regs_[ARM64_REG_R19]);
+ fn("x20", regs_[ARM64_REG_R20]);
+ fn("x21", regs_[ARM64_REG_R21]);
+ fn("x22", regs_[ARM64_REG_R22]);
+ fn("x23", regs_[ARM64_REG_R23]);
+ fn("x24", regs_[ARM64_REG_R24]);
+ fn("x25", regs_[ARM64_REG_R25]);
+ fn("x26", regs_[ARM64_REG_R26]);
+ fn("x27", regs_[ARM64_REG_R27]);
+ fn("x28", regs_[ARM64_REG_R28]);
+ fn("x29", regs_[ARM64_REG_R29]);
+ fn("sp", regs_[ARM64_REG_SP]);
+ fn("lr", regs_[ARM64_REG_LR]);
+ fn("pc", regs_[ARM64_REG_PC]);
+}
+
+Regs* RegsArm64::Read(void* remote_data) {
+ arm64_user_regs* user = reinterpret_cast<arm64_user_regs*>(remote_data);
+
+ RegsArm64* regs = new RegsArm64();
+ memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
+ uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
+ reg_data[ARM64_REG_PC] = user->pc;
+ reg_data[ARM64_REG_SP] = user->sp;
+ regs->SetFromRaw();
+ return regs;
+}
+
+Regs* RegsArm64::CreateFromUcontext(void* ucontext) {
+ arm64_ucontext_t* arm64_ucontext = reinterpret_cast<arm64_ucontext_t*>(ucontext);
+
+ RegsArm64* regs = new RegsArm64();
+ memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
+ regs->SetFromRaw();
+ return regs;
+}
+
+bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+ uint64_t data;
+ Memory* elf_memory = elf->memory();
+ // Read from elf memory since it is usually more expensive to read from
+ // process memory.
+ if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
+ return false;
+ }
+
+ // Look for the kernel sigreturn function.
+ // __kernel_rt_sigreturn:
+ // 0xd2801168 mov x8, #0x8b
+ // 0xd4000001 svc #0x0
+ if (data != 0xd4000001d2801168ULL) {
+ return false;
+ }
+
+ // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
+ if (!process_memory->ReadFully(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
+ sizeof(uint64_t) * ARM64_REG_LAST)) {
+ return false;
+ }
+
+ SetFromRaw();
+ return true;
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
new file mode 100644
index 0000000..ef2f3de
--- /dev/null
+++ b/libunwindstack/RegsX86.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/RegsX86.h>
+
+#include "MachineX86.h"
+#include "UcontextX86.h"
+#include "UserX86.h"
+
+namespace unwindstack {
+
+RegsX86::RegsX86()
+ : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
+
+ArchEnum RegsX86::Arch() {
+ return ARCH_X86;
+}
+
+uint64_t RegsX86::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid()) {
+ return rel_pc;
+ }
+
+ if (rel_pc == 0) {
+ return 0;
+ }
+ return rel_pc - 1;
+}
+
+void RegsX86::SetFromRaw() {
+ set_pc(regs_[X86_REG_PC]);
+ set_sp(regs_[X86_REG_SP]);
+}
+
+bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
+ // Attempt to get the return address from the top of the stack.
+ uint32_t new_pc;
+ if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
+ return false;
+ }
+
+ set_pc(new_pc);
+ return true;
+}
+
+void RegsX86::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+ fn("eax", regs_[X86_REG_EAX]);
+ fn("ebx", regs_[X86_REG_EBX]);
+ fn("ecx", regs_[X86_REG_ECX]);
+ fn("edx", regs_[X86_REG_EDX]);
+ fn("ebp", regs_[X86_REG_EBP]);
+ fn("edi", regs_[X86_REG_EDI]);
+ fn("esi", regs_[X86_REG_ESI]);
+ fn("esp", regs_[X86_REG_ESP]);
+ fn("eip", regs_[X86_REG_EIP]);
+}
+
+Regs* RegsX86::Read(void* user_data) {
+ x86_user_regs* user = reinterpret_cast<x86_user_regs*>(user_data);
+
+ RegsX86* regs = new RegsX86();
+ (*regs)[X86_REG_EAX] = user->eax;
+ (*regs)[X86_REG_EBX] = user->ebx;
+ (*regs)[X86_REG_ECX] = user->ecx;
+ (*regs)[X86_REG_EDX] = user->edx;
+ (*regs)[X86_REG_EBP] = user->ebp;
+ (*regs)[X86_REG_EDI] = user->edi;
+ (*regs)[X86_REG_ESI] = user->esi;
+ (*regs)[X86_REG_ESP] = user->esp;
+ (*regs)[X86_REG_EIP] = user->eip;
+
+ regs->SetFromRaw();
+ return regs;
+}
+
+void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) {
+ // Put the registers in the expected order.
+ regs_[X86_REG_EDI] = ucontext->uc_mcontext.edi;
+ regs_[X86_REG_ESI] = ucontext->uc_mcontext.esi;
+ regs_[X86_REG_EBP] = ucontext->uc_mcontext.ebp;
+ regs_[X86_REG_ESP] = ucontext->uc_mcontext.esp;
+ regs_[X86_REG_EBX] = ucontext->uc_mcontext.ebx;
+ regs_[X86_REG_EDX] = ucontext->uc_mcontext.edx;
+ regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx;
+ regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax;
+ regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip;
+ SetFromRaw();
+}
+
+Regs* RegsX86::CreateFromUcontext(void* ucontext) {
+ x86_ucontext_t* x86_ucontext = reinterpret_cast<x86_ucontext_t*>(ucontext);
+
+ RegsX86* regs = new RegsX86();
+ regs->SetFromUcontext(x86_ucontext);
+ return regs;
+}
+
+bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+ uint64_t data;
+ Memory* elf_memory = elf->memory();
+ // Read from elf memory since it is usually more expensive to read from
+ // process memory.
+ if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
+ return false;
+ }
+
+ if (data == 0x80cd00000077b858ULL) {
+ // Without SA_SIGINFO set, the return sequence is:
+ //
+ // __restore:
+ // 0x58 pop %eax
+ // 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax
+ // 0xcd 0x80 int 0x80
+ //
+ // SP points at arguments:
+ // int signum
+ // struct sigcontext (same format as mcontext)
+ struct x86_mcontext_t context;
+ if (!process_memory->ReadFully(sp() + 4, &context, sizeof(context))) {
+ return false;
+ }
+ regs_[X86_REG_EBP] = context.ebp;
+ regs_[X86_REG_ESP] = context.esp;
+ regs_[X86_REG_EBX] = context.ebx;
+ regs_[X86_REG_EDX] = context.edx;
+ regs_[X86_REG_ECX] = context.ecx;
+ regs_[X86_REG_EAX] = context.eax;
+ regs_[X86_REG_EIP] = context.eip;
+ SetFromRaw();
+ return true;
+ } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) {
+ // With SA_SIGINFO set, the return sequence is:
+ //
+ // __restore_rt:
+ // 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax
+ // 0xcd 0x80 int 0x80
+ //
+ // SP points at arguments:
+ // int signum
+ // siginfo*
+ // ucontext*
+
+ // Get the location of the sigcontext data.
+ uint32_t ptr;
+ if (!process_memory->ReadFully(sp() + 8, &ptr, sizeof(ptr))) {
+ return false;
+ }
+ // Only read the portion of the data structure we care about.
+ x86_ucontext_t x86_ucontext;
+ if (!process_memory->ReadFully(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
+ return false;
+ }
+ SetFromUcontext(&x86_ucontext);
+ return true;
+ }
+ return false;
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
new file mode 100644
index 0000000..70921f8
--- /dev/null
+++ b/libunwindstack/RegsX86_64.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/RegsX86_64.h>
+
+#include "MachineX86_64.h"
+#include "UcontextX86_64.h"
+#include "UserX86_64.h"
+
+namespace unwindstack {
+
+RegsX86_64::RegsX86_64()
+ : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
+
+ArchEnum RegsX86_64::Arch() {
+ return ARCH_X86_64;
+}
+
+uint64_t RegsX86_64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid()) {
+ return rel_pc;
+ }
+
+ if (rel_pc == 0) {
+ return 0;
+ }
+
+ return rel_pc - 1;
+}
+
+void RegsX86_64::SetFromRaw() {
+ set_pc(regs_[X86_64_REG_PC]);
+ set_sp(regs_[X86_64_REG_SP]);
+}
+
+bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
+ // Attempt to get the return address from the top of the stack.
+ uint64_t new_pc;
+ if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
+ return false;
+ }
+
+ set_pc(new_pc);
+ return true;
+}
+
+void RegsX86_64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+ fn("rax", regs_[X86_64_REG_RAX]);
+ fn("rbx", regs_[X86_64_REG_RBX]);
+ fn("rcx", regs_[X86_64_REG_RCX]);
+ fn("rdx", regs_[X86_64_REG_RDX]);
+ fn("r8", regs_[X86_64_REG_R8]);
+ fn("r9", regs_[X86_64_REG_R9]);
+ fn("r10", regs_[X86_64_REG_R10]);
+ fn("r11", regs_[X86_64_REG_R11]);
+ fn("r12", regs_[X86_64_REG_R12]);
+ fn("r13", regs_[X86_64_REG_R13]);
+ fn("r14", regs_[X86_64_REG_R14]);
+ fn("r15", regs_[X86_64_REG_R15]);
+ fn("rdi", regs_[X86_64_REG_RDI]);
+ fn("rsi", regs_[X86_64_REG_RSI]);
+ fn("rbp", regs_[X86_64_REG_RBP]);
+ fn("rsp", regs_[X86_64_REG_RSP]);
+ fn("rip", regs_[X86_64_REG_RIP]);
+}
+
+Regs* RegsX86_64::Read(void* remote_data) {
+ x86_64_user_regs* user = reinterpret_cast<x86_64_user_regs*>(remote_data);
+
+ RegsX86_64* regs = new RegsX86_64();
+ (*regs)[X86_64_REG_RAX] = user->rax;
+ (*regs)[X86_64_REG_RBX] = user->rbx;
+ (*regs)[X86_64_REG_RCX] = user->rcx;
+ (*regs)[X86_64_REG_RDX] = user->rdx;
+ (*regs)[X86_64_REG_R8] = user->r8;
+ (*regs)[X86_64_REG_R9] = user->r9;
+ (*regs)[X86_64_REG_R10] = user->r10;
+ (*regs)[X86_64_REG_R11] = user->r11;
+ (*regs)[X86_64_REG_R12] = user->r12;
+ (*regs)[X86_64_REG_R13] = user->r13;
+ (*regs)[X86_64_REG_R14] = user->r14;
+ (*regs)[X86_64_REG_R15] = user->r15;
+ (*regs)[X86_64_REG_RDI] = user->rdi;
+ (*regs)[X86_64_REG_RSI] = user->rsi;
+ (*regs)[X86_64_REG_RBP] = user->rbp;
+ (*regs)[X86_64_REG_RSP] = user->rsp;
+ (*regs)[X86_64_REG_RIP] = user->rip;
+
+ regs->SetFromRaw();
+ return regs;
+}
+
+void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
+ // R8-R15
+ memcpy(®s_[X86_64_REG_R8], &ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));
+
+ // Rest of the registers.
+ regs_[X86_64_REG_RDI] = ucontext->uc_mcontext.rdi;
+ regs_[X86_64_REG_RSI] = ucontext->uc_mcontext.rsi;
+ regs_[X86_64_REG_RBP] = ucontext->uc_mcontext.rbp;
+ regs_[X86_64_REG_RBX] = ucontext->uc_mcontext.rbx;
+ regs_[X86_64_REG_RDX] = ucontext->uc_mcontext.rdx;
+ regs_[X86_64_REG_RAX] = ucontext->uc_mcontext.rax;
+ regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
+ regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
+ regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
+
+ SetFromRaw();
+}
+
+Regs* RegsX86_64::CreateFromUcontext(void* ucontext) {
+ x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);
+
+ RegsX86_64* regs = new RegsX86_64();
+ regs->SetFromUcontext(x86_64_ucontext);
+ return regs;
+}
+
+bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+ uint64_t data;
+ Memory* elf_memory = elf->memory();
+ // Read from elf memory since it is usually more expensive to read from
+ // process memory.
+ if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
+ return false;
+ }
+
+ uint16_t data2;
+ if (!elf_memory->ReadFully(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
+ return false;
+ }
+
+ // __restore_rt:
+ // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax
+ // 0x0f 0x05 syscall
+ // 0x0f nopl 0x0($rax)
+
+ // Read the mcontext data from the stack.
+ // sp points to the ucontext data structure, read only the mcontext part.
+ x86_64_ucontext_t x86_64_ucontext;
+ if (!process_memory->ReadFully(sp() + 0x28, &x86_64_ucontext.uc_mcontext,
+ sizeof(x86_64_mcontext_t))) {
+ return false;
+ }
+ SetFromUcontext(&x86_64_ucontext);
+ return true;
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/Ucontext.h b/libunwindstack/Ucontext.h
deleted file mode 100644
index 22f6a89..0000000
--- a/libunwindstack/Ucontext.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBUNWINDSTACK_UCONTEXT_H
-#define _LIBUNWINDSTACK_UCONTEXT_H
-
-#include <stdint.h>
-
-namespace unwindstack {
-
-//-------------------------------------------------------------------
-// ARM ucontext structures
-//-------------------------------------------------------------------
-struct arm_stack_t {
- uint32_t ss_sp; // void __user*
- int32_t ss_flags; // int
- uint32_t ss_size; // size_t
-};
-
-struct arm_mcontext_t {
- uint32_t trap_no; // unsigned long
- uint32_t error_code; // unsigned long
- uint32_t oldmask; // unsigned long
- uint32_t regs[ARM_REG_LAST]; // unsigned long
- uint32_t cpsr; // unsigned long
- uint32_t fault_address; // unsigned long
-};
-
-struct arm_ucontext_t {
- uint32_t uc_flags; // unsigned long
- uint32_t uc_link; // struct ucontext*
- arm_stack_t uc_stack;
- arm_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-//-------------------------------------------------------------------
-
-//-------------------------------------------------------------------
-// ARM64 ucontext structures
-//-------------------------------------------------------------------
-struct arm64_stack_t {
- uint64_t ss_sp; // void __user*
- int32_t ss_flags; // int
- uint64_t ss_size; // size_t
-};
-
-struct arm64_sigset_t {
- uint64_t sig; // unsigned long
-};
-
-struct arm64_mcontext_t {
- uint64_t fault_address; // __u64
- uint64_t regs[ARM64_REG_LAST]; // __u64
- uint64_t pstate; // __u64
- // Nothing else is used, so don't define it.
-};
-
-struct arm64_ucontext_t {
- uint64_t uc_flags; // unsigned long
- uint64_t uc_link; // struct ucontext*
- arm64_stack_t uc_stack;
- arm64_sigset_t uc_sigmask;
- // The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM64.
- char __padding[128 - sizeof(arm64_sigset_t)];
- // The full structure requires 16 byte alignment, but our partial structure
- // doesn't, so force the alignment.
- arm64_mcontext_t uc_mcontext __attribute__((aligned(16)));
-};
-//-------------------------------------------------------------------
-
-//-------------------------------------------------------------------
-// X86 ucontext structures
-//-------------------------------------------------------------------
-struct x86_stack_t {
- uint32_t ss_sp; // void __user*
- int32_t ss_flags; // int
- uint32_t ss_size; // size_t
-};
-
-struct x86_mcontext_t {
- uint32_t gs;
- uint32_t fs;
- uint32_t es;
- uint32_t ds;
- uint32_t edi;
- uint32_t esi;
- uint32_t ebp;
- uint32_t esp;
- uint32_t ebx;
- uint32_t edx;
- uint32_t ecx;
- uint32_t eax;
- uint32_t trapno;
- uint32_t err;
- uint32_t eip;
- uint32_t cs;
- uint32_t efl;
- uint32_t uesp;
- uint32_t ss;
- // Only care about the registers, skip everything else.
-};
-
-struct x86_ucontext_t {
- uint32_t uc_flags; // unsigned long
- uint32_t uc_link; // struct ucontext*
- x86_stack_t uc_stack;
- x86_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-//-------------------------------------------------------------------
-
-//-------------------------------------------------------------------
-// X86_64 ucontext structures
-//-------------------------------------------------------------------
-struct x86_64_stack_t {
- uint64_t ss_sp; // void __user*
- int32_t ss_flags; // int
- uint64_t ss_size; // size_t
-};
-
-struct x86_64_mcontext_t {
- uint64_t r8;
- uint64_t r9;
- uint64_t r10;
- uint64_t r11;
- uint64_t r12;
- uint64_t r13;
- uint64_t r14;
- uint64_t r15;
- uint64_t rdi;
- uint64_t rsi;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t rdx;
- uint64_t rax;
- uint64_t rcx;
- uint64_t rsp;
- uint64_t rip;
- uint64_t efl;
- uint64_t csgsfs;
- uint64_t err;
- uint64_t trapno;
- uint64_t oldmask;
- uint64_t cr2;
- // Only care about the registers, skip everything else.
-};
-
-struct x86_64_ucontext_t {
- uint64_t uc_flags; // unsigned long
- uint64_t uc_link; // struct ucontext*
- x86_64_stack_t uc_stack;
- x86_64_mcontext_t uc_mcontext;
- // Nothing else is used, so don't define it.
-};
-//-------------------------------------------------------------------
-
-} // namespace unwindstack
-
-#endif // _LIBUNWINDSTACK_UCONTEXT_H
diff --git a/libunwindstack/UcontextArm.h b/libunwindstack/UcontextArm.h
new file mode 100644
index 0000000..8c94166
--- /dev/null
+++ b/libunwindstack/UcontextArm.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM_H
+#define _LIBUNWINDSTACK_UCONTEXT_ARM_H
+
+#include <stdint.h>
+
+#include "MachineArm.h"
+
+namespace unwindstack {
+
+struct arm_stack_t {
+ uint32_t ss_sp; // void __user*
+ int32_t ss_flags; // int
+ uint32_t ss_size; // size_t
+};
+
+struct arm_mcontext_t {
+ uint32_t trap_no; // unsigned long
+ uint32_t error_code; // unsigned long
+ uint32_t oldmask; // unsigned long
+ uint32_t regs[ARM_REG_LAST]; // unsigned long
+ uint32_t cpsr; // unsigned long
+ uint32_t fault_address; // unsigned long
+};
+
+struct arm_ucontext_t {
+ uint32_t uc_flags; // unsigned long
+ uint32_t uc_link; // struct ucontext*
+ arm_stack_t uc_stack;
+ arm_mcontext_t uc_mcontext;
+ // Nothing else is used, so don't define it.
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_UCONTEXT_ARM_H
diff --git a/libunwindstack/UcontextArm64.h b/libunwindstack/UcontextArm64.h
new file mode 100644
index 0000000..655719f
--- /dev/null
+++ b/libunwindstack/UcontextArm64.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM64_H
+#define _LIBUNWINDSTACK_UCONTEXT_ARM64_H
+
+#include <stdint.h>
+
+#include "MachineArm64.h"
+
+namespace unwindstack {
+
+struct arm64_stack_t {
+ uint64_t ss_sp; // void __user*
+ int32_t ss_flags; // int
+ uint64_t ss_size; // size_t
+};
+
+struct arm64_sigset_t {
+ uint64_t sig; // unsigned long
+};
+
+struct arm64_mcontext_t {
+ uint64_t fault_address; // __u64
+ uint64_t regs[ARM64_REG_LAST]; // __u64
+ uint64_t pstate; // __u64
+ // Nothing else is used, so don't define it.
+};
+
+struct arm64_ucontext_t {
+ uint64_t uc_flags; // unsigned long
+ uint64_t uc_link; // struct ucontext*
+ arm64_stack_t uc_stack;
+ arm64_sigset_t uc_sigmask;
+ // The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM64.
+ char __padding[128 - sizeof(arm64_sigset_t)];
+ // The full structure requires 16 byte alignment, but our partial structure
+ // doesn't, so force the alignment.
+ arm64_mcontext_t uc_mcontext __attribute__((aligned(16)));
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_UCONTEXT_ARM64_H
diff --git a/libunwindstack/User.h b/libunwindstack/UcontextX86.h
similarity index 62%
copy from libunwindstack/User.h
copy to libunwindstack/UcontextX86.h
index 53f7e50..f79d92b 100644
--- a/libunwindstack/User.h
+++ b/libunwindstack/UcontextX86.h
@@ -26,75 +26,52 @@
* SUCH DAMAGE.
*/
-#ifndef _LIBUNWINDSTACK_USER_H
-#define _LIBUNWINDSTACK_USER_H
+#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_H
+#define _LIBUNWINDSTACK_UCONTEXT_X86_H
+
+#include <stdint.h>
+
+#include "MachineX86.h"
namespace unwindstack {
-struct x86_user_regs {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
+struct x86_stack_t {
+ uint32_t ss_sp; // void __user*
+ int32_t ss_flags; // int
+ uint32_t ss_size; // size_t
+};
+
+struct x86_mcontext_t {
+ uint32_t gs;
+ uint32_t fs;
+ uint32_t es;
+ uint32_t ds;
uint32_t edi;
+ uint32_t esi;
uint32_t ebp;
- uint32_t eax;
- uint32_t xds;
- uint32_t xes;
- uint32_t xfs;
- uint32_t xgs;
- uint32_t orig_eax;
- uint32_t eip;
- uint32_t xcs;
- uint32_t eflags;
uint32_t esp;
- uint32_t xss;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+ uint32_t trapno;
+ uint32_t err;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t efl;
+ uint32_t uesp;
+ uint32_t ss;
+ // Only care about the registers, skip everything else.
};
-struct x86_64_user_regs {
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- uint64_t rax;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t orig_rax;
- uint64_t rip;
- uint64_t cs;
- uint64_t eflags;
- uint64_t rsp;
- uint64_t ss;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ds;
- uint64_t es;
- uint64_t fs;
- uint64_t gs;
+struct x86_ucontext_t {
+ uint32_t uc_flags; // unsigned long
+ uint32_t uc_link; // struct ucontext*
+ x86_stack_t uc_stack;
+ x86_mcontext_t uc_mcontext;
+ // Nothing else is used, so don't define it.
};
-struct arm_user_regs {
- uint32_t regs[18];
-};
-
-struct arm64_user_regs {
- uint64_t regs[31];
- uint64_t sp;
- uint64_t pc;
- uint64_t pstate;
-};
-
-// The largest user structure.
-constexpr size_t MAX_USER_REGS_SIZE = sizeof(arm64_user_regs) + 10;
-
} // namespace unwindstack
-#endif // _LIBUNWINDSTACK_USER_H
+#endif // _LIBUNWINDSTACK_UCONTEXT_X86_H
diff --git a/libunwindstack/User.h b/libunwindstack/UcontextX86_64.h
similarity index 67%
copy from libunwindstack/User.h
copy to libunwindstack/UcontextX86_64.h
index 53f7e50..d689796 100644
--- a/libunwindstack/User.h
+++ b/libunwindstack/UcontextX86_64.h
@@ -26,75 +26,56 @@
* SUCH DAMAGE.
*/
-#ifndef _LIBUNWINDSTACK_USER_H
-#define _LIBUNWINDSTACK_USER_H
+#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_64_H
+#define _LIBUNWINDSTACK_UCONTEXT_X86_64_H
+
+#include <stdint.h>
+
+#include "MachineX86_64.h"
namespace unwindstack {
-struct x86_user_regs {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint32_t xds;
- uint32_t xes;
- uint32_t xfs;
- uint32_t xgs;
- uint32_t orig_eax;
- uint32_t eip;
- uint32_t xcs;
- uint32_t eflags;
- uint32_t esp;
- uint32_t xss;
+struct x86_64_stack_t {
+ uint64_t ss_sp; // void __user*
+ int32_t ss_flags; // int
+ uint64_t ss_size; // size_t
};
-struct x86_64_user_regs {
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
+struct x86_64_mcontext_t {
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rdi;
+ uint64_t rsi;
uint64_t rbp;
uint64_t rbx;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
+ uint64_t rdx;
uint64_t rax;
uint64_t rcx;
- uint64_t rdx;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t orig_rax;
- uint64_t rip;
- uint64_t cs;
- uint64_t eflags;
uint64_t rsp;
- uint64_t ss;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ds;
- uint64_t es;
- uint64_t fs;
- uint64_t gs;
+ uint64_t rip;
+ uint64_t efl;
+ uint64_t csgsfs;
+ uint64_t err;
+ uint64_t trapno;
+ uint64_t oldmask;
+ uint64_t cr2;
+ // Only care about the registers, skip everything else.
};
-struct arm_user_regs {
- uint32_t regs[18];
+struct x86_64_ucontext_t {
+ uint64_t uc_flags; // unsigned long
+ uint64_t uc_link; // struct ucontext*
+ x86_64_stack_t uc_stack;
+ x86_64_mcontext_t uc_mcontext;
+ // Nothing else is used, so don't define it.
};
-struct arm64_user_regs {
- uint64_t regs[31];
- uint64_t sp;
- uint64_t pc;
- uint64_t pstate;
-};
-
-// The largest user structure.
-constexpr size_t MAX_USER_REGS_SIZE = sizeof(arm64_user_regs) + 10;
-
} // namespace unwindstack
-#endif // _LIBUNWINDSTACK_USER_H
+#endif // _LIBUNWINDSTACK_UCONTEXT_X86_64_H
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 3092a62..4ae365d 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -174,8 +174,7 @@
if (frame_num >= frames_.size()) {
return "";
}
- return FormatFrame(frames_[frame_num],
- regs_->MachineType() == EM_ARM || regs_->MachineType() == EM_386);
+ return FormatFrame(frames_[frame_num], regs_->Arch() == ARCH_ARM || regs_->Arch() == ARCH_X86);
}
std::string Unwinder::FormatFrame(const FrameData& frame, bool bits32) {
diff --git a/libunwindstack/UserArm.h b/libunwindstack/UserArm.h
new file mode 100644
index 0000000..7388c03
--- /dev/null
+++ b/libunwindstack/UserArm.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LIBUNWINDSTACK_USER_ARM_H
+#define _LIBUNWINDSTACK_USER_ARM_H
+
+namespace unwindstack {
+
+struct arm_user_regs {
+ uint32_t regs[18];
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_USER_ARM_H
diff --git a/libunwindstack/User.h b/libunwindstack/UserArm64.h
similarity index 60%
copy from libunwindstack/User.h
copy to libunwindstack/UserArm64.h
index 53f7e50..d74983f 100644
--- a/libunwindstack/User.h
+++ b/libunwindstack/UserArm64.h
@@ -26,65 +26,11 @@
* SUCH DAMAGE.
*/
-#ifndef _LIBUNWINDSTACK_USER_H
-#define _LIBUNWINDSTACK_USER_H
+#ifndef _LIBUNWINDSTACK_USER_ARM64_H
+#define _LIBUNWINDSTACK_USER_ARM64_H
namespace unwindstack {
-struct x86_user_regs {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint32_t xds;
- uint32_t xes;
- uint32_t xfs;
- uint32_t xgs;
- uint32_t orig_eax;
- uint32_t eip;
- uint32_t xcs;
- uint32_t eflags;
- uint32_t esp;
- uint32_t xss;
-};
-
-struct x86_64_user_regs {
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- uint64_t rax;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t orig_rax;
- uint64_t rip;
- uint64_t cs;
- uint64_t eflags;
- uint64_t rsp;
- uint64_t ss;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ds;
- uint64_t es;
- uint64_t fs;
- uint64_t gs;
-};
-
-struct arm_user_regs {
- uint32_t regs[18];
-};
-
struct arm64_user_regs {
uint64_t regs[31];
uint64_t sp;
@@ -92,9 +38,6 @@
uint64_t pstate;
};
-// The largest user structure.
-constexpr size_t MAX_USER_REGS_SIZE = sizeof(arm64_user_regs) + 10;
-
} // namespace unwindstack
-#endif // _LIBUNWINDSTACK_USER_H
+#endif // _LIBUNWINDSTACK_USER_ARM64_H
diff --git a/libunwindstack/User.h b/libunwindstack/UserX86.h
similarity index 68%
copy from libunwindstack/User.h
copy to libunwindstack/UserX86.h
index 53f7e50..a040560 100644
--- a/libunwindstack/User.h
+++ b/libunwindstack/UserX86.h
@@ -26,8 +26,8 @@
* SUCH DAMAGE.
*/
-#ifndef _LIBUNWINDSTACK_USER_H
-#define _LIBUNWINDSTACK_USER_H
+#ifndef _LIBUNWINDSTACK_USER_X86_H
+#define _LIBUNWINDSTACK_USER_X86_H
namespace unwindstack {
@@ -51,50 +51,6 @@
uint32_t xss;
};
-struct x86_64_user_regs {
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- uint64_t rax;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t orig_rax;
- uint64_t rip;
- uint64_t cs;
- uint64_t eflags;
- uint64_t rsp;
- uint64_t ss;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ds;
- uint64_t es;
- uint64_t fs;
- uint64_t gs;
-};
-
-struct arm_user_regs {
- uint32_t regs[18];
-};
-
-struct arm64_user_regs {
- uint64_t regs[31];
- uint64_t sp;
- uint64_t pc;
- uint64_t pstate;
-};
-
-// The largest user structure.
-constexpr size_t MAX_USER_REGS_SIZE = sizeof(arm64_user_regs) + 10;
-
} // namespace unwindstack
-#endif // _LIBUNWINDSTACK_USER_H
+#endif // _LIBUNWINDSTACK_USER_X86_H
diff --git a/libunwindstack/User.h b/libunwindstack/UserX86_64.h
similarity index 74%
rename from libunwindstack/User.h
rename to libunwindstack/UserX86_64.h
index 53f7e50..b80d201 100644
--- a/libunwindstack/User.h
+++ b/libunwindstack/UserX86_64.h
@@ -26,31 +26,11 @@
* SUCH DAMAGE.
*/
-#ifndef _LIBUNWINDSTACK_USER_H
-#define _LIBUNWINDSTACK_USER_H
+#ifndef _LIBUNWINDSTACK_USER_X86_64_H
+#define _LIBUNWINDSTACK_USER_X86_64_H
namespace unwindstack {
-struct x86_user_regs {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint32_t xds;
- uint32_t xes;
- uint32_t xfs;
- uint32_t xgs;
- uint32_t orig_eax;
- uint32_t eip;
- uint32_t xcs;
- uint32_t eflags;
- uint32_t esp;
- uint32_t xss;
-};
-
struct x86_64_user_regs {
uint64_t r15;
uint64_t r14;
@@ -81,20 +61,6 @@
uint64_t gs;
};
-struct arm_user_regs {
- uint32_t regs[18];
-};
-
-struct arm64_user_regs {
- uint64_t regs[31];
- uint64_t sp;
- uint64_t pc;
- uint64_t pstate;
-};
-
-// The largest user structure.
-constexpr size_t MAX_USER_REGS_SIZE = sizeof(arm64_user_regs) + 10;
-
} // namespace unwindstack
-#endif // _LIBUNWINDSTACK_USER_H
+#endif // _LIBUNWINDSTACK_USER_X86_64_H
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index d9ea9c4..d27727b 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -36,6 +36,14 @@
struct MapInfo;
class Regs;
+enum ArchEnum : uint8_t {
+ ARCH_UNKNOWN = 0,
+ ARCH_ARM,
+ ARCH_ARM64,
+ ARCH_X86,
+ ARCH_X86_64,
+};
+
class Elf {
public:
Elf(Memory* memory) : memory_(memory) {}
@@ -64,6 +72,8 @@
uint8_t class_type() { return class_type_; }
+ ArchEnum arch() { return arch_; }
+
Memory* memory() { return memory_.get(); }
ElfInterface* interface() { return interface_.get(); }
@@ -83,6 +93,7 @@
std::unique_ptr<Memory> memory_;
uint32_t machine_type_;
uint8_t class_type_;
+ ArchEnum arch_;
// Protect calls that can modify internal state of the interface object.
std::mutex lock_;
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 6576e4c..7025fcf 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -27,10 +27,8 @@
// Forward declarations.
class Elf;
-struct MapInfo;
+enum ArchEnum : uint8_t;
class Memory;
-struct x86_ucontext_t;
-struct x86_64_ucontext_t;
class Regs {
public:
@@ -51,7 +49,7 @@
: total_regs_(total_regs), sp_reg_(sp_reg), return_loc_(return_loc) {}
virtual ~Regs() = default;
- virtual uint32_t MachineType() = 0;
+ virtual ArchEnum Arch() = 0;
virtual void* RawData() = 0;
virtual uint64_t pc() = 0;
@@ -70,9 +68,9 @@
uint16_t sp_reg() { return sp_reg_; }
uint16_t total_regs() { return total_regs_; }
- static uint32_t CurrentMachineType();
+ static ArchEnum CurrentArch();
static Regs* RemoteGet(pid_t pid);
- static Regs* CreateFromUcontext(uint32_t machine_type, void* ucontext);
+ static Regs* CreateFromUcontext(ArchEnum arch, void* ucontext);
static Regs* CreateFromLocal();
protected:
@@ -110,82 +108,6 @@
std::vector<AddressType> regs_;
};
-class RegsArm : public RegsImpl<uint32_t> {
- public:
- RegsArm();
- virtual ~RegsArm() = default;
-
- virtual uint32_t MachineType() override final;
-
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
-
- void SetFromRaw() override;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
-
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-};
-
-class RegsArm64 : public RegsImpl<uint64_t> {
- public:
- RegsArm64();
- virtual ~RegsArm64() = default;
-
- virtual uint32_t MachineType() override final;
-
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
-
- void SetFromRaw() override;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
-
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-};
-
-class RegsX86 : public RegsImpl<uint32_t> {
- public:
- RegsX86();
- virtual ~RegsX86() = default;
-
- virtual uint32_t MachineType() override final;
-
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
-
- void SetFromRaw() override;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
-
- void SetFromUcontext(x86_ucontext_t* ucontext);
-
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-};
-
-class RegsX86_64 : public RegsImpl<uint64_t> {
- public:
- RegsX86_64();
- virtual ~RegsX86_64() = default;
-
- virtual uint32_t MachineType() override final;
-
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
-
- void SetFromRaw() override;
-
- bool SetPcFromReturnAddress(Memory* process_memory) override;
-
- bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
-
- void SetFromUcontext(x86_64_ucontext_t* ucontext);
-
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
-};
-
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_REGS_H
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
new file mode 100644
index 0000000..b5d344b
--- /dev/null
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_REGS_ARM_H
+#define _LIBUNWINDSTACK_REGS_ARM_H
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Regs.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Memory;
+
+class RegsArm : public RegsImpl<uint32_t> {
+ public:
+ RegsArm();
+ virtual ~RegsArm() = default;
+
+ virtual ArchEnum Arch() override final;
+
+ uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+ void SetFromRaw() override;
+
+ bool SetPcFromReturnAddress(Memory* process_memory) override;
+
+ bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+
+ virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ static Regs* Read(void* data);
+
+ static Regs* CreateFromUcontext(void* ucontext);
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_REGS_ARM_H
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
new file mode 100644
index 0000000..30e626c
--- /dev/null
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_REGS_ARM64_H
+#define _LIBUNWINDSTACK_REGS_ARM64_H
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Regs.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Memory;
+
+class RegsArm64 : public RegsImpl<uint64_t> {
+ public:
+ RegsArm64();
+ virtual ~RegsArm64() = default;
+
+ virtual ArchEnum Arch() override final;
+
+ uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+ void SetFromRaw() override;
+
+ bool SetPcFromReturnAddress(Memory* process_memory) override;
+
+ bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+
+ virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ static Regs* Read(void* data);
+
+ static Regs* CreateFromUcontext(void* ucontext);
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_REGS_ARM64_H
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
new file mode 100644
index 0000000..a695bbf
--- /dev/null
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_REGS_X86_H
+#define _LIBUNWINDSTACK_REGS_X86_H
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Regs.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Memory;
+struct x86_ucontext_t;
+
+class RegsX86 : public RegsImpl<uint32_t> {
+ public:
+ RegsX86();
+ virtual ~RegsX86() = default;
+
+ virtual ArchEnum Arch() override final;
+
+ uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+ void SetFromRaw() override;
+
+ bool SetPcFromReturnAddress(Memory* process_memory) override;
+
+ bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+
+ void SetFromUcontext(x86_ucontext_t* ucontext);
+
+ virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ static Regs* Read(void* data);
+
+ static Regs* CreateFromUcontext(void* ucontext);
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_REGS_X86_H
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
new file mode 100644
index 0000000..23a3f20
--- /dev/null
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_REGS_X86_64_H
+#define _LIBUNWINDSTACK_REGS_X86_64_H
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Regs.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Memory;
+struct x86_64_ucontext_t;
+
+class RegsX86_64 : public RegsImpl<uint64_t> {
+ public:
+ RegsX86_64();
+ virtual ~RegsX86_64() = default;
+
+ virtual ArchEnum Arch() override final;
+
+ uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+
+ void SetFromRaw() override;
+
+ bool SetPcFromReturnAddress(Memory* process_memory) override;
+
+ bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+
+ void SetFromUcontext(x86_64_ucontext_t* ucontext);
+
+ virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ static Regs* Read(void* data);
+
+ static Regs* CreateFromUcontext(void* ucontext);
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_REGS_X86_64_H
diff --git a/libunwindstack/tests/ArmExidxDecodeTest.cpp b/libunwindstack/tests/ArmExidxDecodeTest.cpp
index 94cb493..8d6d00d 100644
--- a/libunwindstack/tests/ArmExidxDecodeTest.cpp
+++ b/libunwindstack/tests/ArmExidxDecodeTest.cpp
@@ -24,7 +24,7 @@
#include <gtest/gtest.h>
#include <unwindstack/Log.h>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
#include "ArmExidx.h"
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index 4b621c9..5f7cf60 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -20,10 +20,10 @@
#include <vector>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
#include "ElfInterfaceArm.h"
-#include "Machine.h"
+#include "MachineArm.h"
#include "ElfFake.h"
#include "MemoryFake.h"
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index afd113d..00192f1 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -25,6 +25,7 @@
#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
+#include <unwindstack/RegsArm.h>
#include "ElfFake.h"
#include "ElfTestUtils.h"
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index fedaf87..3c5af4a 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include <unwindstack/Elf.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -30,7 +31,7 @@
: Regs(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
virtual ~RegsFake() = default;
- uint32_t MachineType() override { return fake_type_; }
+ ArchEnum Arch() override { return fake_arch_; }
void* RawData() override { return nullptr; }
uint64_t pc() override { return fake_pc_; }
uint64_t sp() override { return fake_sp_; }
@@ -50,14 +51,14 @@
void SetFromRaw() override {}
- void FakeSetMachineType(uint32_t type) { fake_type_ = type; }
+ void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; }
void FakeSetPc(uint64_t pc) { fake_pc_ = pc; }
void FakeSetSp(uint64_t sp) { fake_sp_ = sp; }
void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
private:
- uint32_t fake_type_ = 0;
+ ArchEnum fake_arch_ = ARCH_UNKNOWN;
uint64_t fake_pc_ = 0;
uint64_t fake_sp_ = 0;
bool fake_return_address_valid_ = false;
@@ -71,7 +72,7 @@
: RegsImpl<TypeParam>(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
virtual ~RegsImplFake() = default;
- uint32_t MachineType() override { return 0; }
+ ArchEnum Arch() override { return ARCH_UNKNOWN; }
uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
void SetFromRaw() override {}
diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp
index c8d1d98..0cb70ba 100644
--- a/libunwindstack/tests/RegsIterateTest.cpp
+++ b/libunwindstack/tests/RegsIterateTest.cpp
@@ -25,9 +25,15 @@
#include <unwindstack/Elf.h>
#include <unwindstack/ElfInterface.h>
#include <unwindstack/MapInfo.h>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
-#include "Machine.h"
+#include "MachineArm.h"
+#include "MachineArm64.h"
+#include "MachineX86.h"
+#include "MachineX86_64.h"
namespace unwindstack {
diff --git a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
index 85192d5..ae57caf 100644
--- a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
+++ b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
@@ -19,9 +19,15 @@
#include <gtest/gtest.h>
#include <unwindstack/Elf.h>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
-#include "Machine.h"
+#include "MachineArm.h"
+#include "MachineArm64.h"
+#include "MachineX86.h"
+#include "MachineX86_64.h"
#include "MemoryFake.h"
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 3320f77..a932973 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -21,7 +21,10 @@
#include <unwindstack/Elf.h>
#include <unwindstack/ElfInterface.h>
#include <unwindstack/MapInfo.h>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
#include "ElfFake.h"
#include "MemoryFake.h"
@@ -212,4 +215,18 @@
EXPECT_EQ(0x4900000000U, x86_64.pc());
}
+TEST_F(RegsTest, machine_type) {
+ RegsArm arm_regs;
+ EXPECT_EQ(ARCH_ARM, arm_regs.Arch());
+
+ RegsArm64 arm64_regs;
+ EXPECT_EQ(ARCH_ARM64, arm64_regs.Arch());
+
+ RegsX86 x86_regs;
+ EXPECT_EQ(ARCH_X86, x86_regs.Arch());
+
+ RegsX86_64 x86_64_regs;
+ EXPECT_EQ(ARCH_X86_64, x86_64_regs.Arch());
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index d24abe4..962f744 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -27,10 +27,12 @@
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
#include <unwindstack/Unwinder.h>
-#include "Machine.h"
+#include "MachineArm.h"
+#include "MachineArm64.h"
#include "ElfTestUtils.h"
@@ -73,7 +75,7 @@
BufferMaps maps(buffer.data());
ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(static_cast<uint32_t>(EM_ARM), regs.MachineType());
+ ASSERT_EQ(ARCH_ARM, regs.Arch());
std::shared_ptr<Memory> process_memory(memory);
@@ -125,7 +127,7 @@
BufferMaps maps(buffer.data());
ASSERT_TRUE(maps.Parse());
- ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), regs.MachineType());
+ ASSERT_EQ(ARCH_ARM64, regs.Arch());
std::shared_ptr<Memory> process_memory(memory);
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index b372fd0..242cc6a 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -250,7 +250,7 @@
LocalMaps maps;
ASSERT_TRUE(maps.Parse());
- std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentMachineType(), ucontext));
+ std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext));
VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 098459e..71103b4 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -95,7 +95,7 @@
void SetUp() override {
ElfInterfaceFake::FakeClear();
- regs_.FakeSetMachineType(EM_ARM);
+ regs_.FakeSetArch(ARCH_ARM);
regs_.FakeSetReturnAddressValid(false);
}
@@ -702,14 +702,14 @@
ASSERT_EQ(1U, unwinder.NumFrames());
- regs_.FakeSetMachineType(EM_ARM);
+ regs_.FakeSetArch(ARCH_ARM);
EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
- regs_.FakeSetMachineType(EM_386);
+ regs_.FakeSetArch(ARCH_X86);
EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
- regs_.FakeSetMachineType(EM_AARCH64);
+ regs_.FakeSetArch(ARCH_ARM64);
EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
- regs_.FakeSetMachineType(EM_X86_64);
+ regs_.FakeSetArch(ARCH_X86_64);
EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
EXPECT_EQ("", unwinder.FormatFrame(1));
diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp
index f2530d7..7896279 100644
--- a/libunwindstack/tools/unwind.cpp
+++ b/libunwindstack/tools/unwind.cpp
@@ -63,17 +63,17 @@
}
printf("ABI: ");
- switch (regs->MachineType()) {
- case EM_ARM:
+ switch (regs->Arch()) {
+ case unwindstack::ARCH_ARM:
printf("arm");
break;
- case EM_386:
+ case unwindstack::ARCH_X86:
printf("x86");
break;
- case EM_AARCH64:
+ case unwindstack::ARCH_ARM64:
printf("arm64");
break;
- case EM_X86_64:
+ case unwindstack::ARCH_X86_64:
printf("x86_64");
break;
default: