blob: 7d2185e28a5d03e219847ddfa6dbf0dbaebb6535 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/lib/unwinder/fuchsia.h"
#include <zircon/syscalls.h>
namespace unwinder {
Error FuchsiaMemory::ReadBytes(uint64_t addr, uint64_t size, void* dst) {
size_t actual = 0;
zx_status_t status = zx_process_read_memory(process_, addr, dst, size, &actual);
if (status != ZX_OK) {
return Error("zx_process_read_memory: %d", status);
}
if (actual != size) {
return Error("zx_process_read_memory short read: expect %zu, got %zu", size, actual);
}
return Success();
}
unwinder::Registers FromFuchsiaRegisters(const zx_thread_state_general_regs_t& regs) {
#if defined(__x86_64__)
unwinder::Registers res(unwinder::Registers::Arch::kX64);
// The first 4 registers are out-of-order.
res.Set(unwinder::RegisterID::kX64_rax, regs.rax);
res.Set(unwinder::RegisterID::kX64_rbx, regs.rbx);
res.Set(unwinder::RegisterID::kX64_rcx, regs.rcx);
res.Set(unwinder::RegisterID::kX64_rdx, regs.rdx);
for (int i = 4; i < static_cast<int>(unwinder::RegisterID::kX64_last); i++) {
res.Set(static_cast<unwinder::RegisterID>(i), reinterpret_cast<const uint64_t*>(&regs)[i]);
}
#elif defined(__aarch64__)
unwinder::Registers res(unwinder::Registers::Arch::kArm64);
for (int i = 0; i < static_cast<int>(unwinder::RegisterID::kArm64_last); i++) {
res.Set(static_cast<unwinder::RegisterID>(i), reinterpret_cast<const uint64_t*>(&regs)[i]);
}
#elif defined(__riscv)
unwinder::Registers res(unwinder::Registers::Arch::kRiscv64);
// RegisterID::kRiscv64_pc is not 0.
res.SetPC(regs.pc);
for (int i = 1; i < static_cast<int>(unwinder::RegisterID::kRiscv64_last); i++) {
res.Set(static_cast<unwinder::RegisterID>(i), reinterpret_cast<const uint64_t*>(&regs)[i]);
}
#else
#error What platform?
#endif
return res;
}
} // namespace unwinder