blob: f1c972f30a8301a9d4197588a060ef159a4ba900 [file] [log] [blame]
// Copyright 2023 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/scs_unwinder.h"
namespace unwinder {
Error ShadowCallStackUnwinder::Step(Memory* scs, const Registers& current, Registers& next) {
if (current.arch() != Registers::Arch::kArm64) {
return Error("Shadow call stack is only supported on arm64");
}
uint64_t x18;
if (auto err = current.Get(RegisterID::kArm64_x18, x18); err.has_err()) {
return err;
}
if (!x18) {
return Error("No shadow call stack");
}
// The shadow call stack is pushed/popped via
//
// str x30, [x18], #8 ; post-indexed
// ...
// ldr x30, [x18, #-8]! ; pre-indexed
//
// So x18 points to the next available slots.
uint64_t ra;
if (auto err = scs->Read(x18 - 8, ra); err.has_err()) {
return err;
}
// A zero ra indicates the beginning of the shadow call stack.
if (ra) {
next.SetPC(ra);
next.Set(RegisterID::kArm64_x18, x18 - 8);
}
return Success();
}
} // namespace unwinder