#ifndef MRT_STACKINFO_H
#define MRT_STACKINFO_H
#include <vector>
#include "Common/BaseObject.h"
#include "Common/StackType.h"
#include "Interpreter/Options.h"
namespace MapleRuntime {
#ifdef INTERPRETER_ENABLED
constexpr int INTERPRETED_FRAME_FDESC = 0;
#endif
class Mutator;
class StackInfo {
public:
explicit StackInfo(const UnwindContext* context = nullptr)
: n2cCount(0), lastFrameType(FrameType::UNKNOWN), topContext(context), isReliableN2CStub(false)
{
if (context == nullptr) {
anchorFA = GetAnchorFAFromMutatorContext();
} else {
anchorFA = context->anchorFA;
}
constexpr int presetStackLength = 32;
stack.reserve(presetStackLength);
}
virtual ~StackInfo()
{
topContext = nullptr;
anchorFA = nullptr;
}
void CheckTopUnwindContextAndInit(UnwindContext& uwContext);
bool IsN2CContext(const UnwindContext& uwContext) const;
void AnalyseAndSetFrameType(UnwindContext& uwContext);
std::vector<FrameInfo>& GetStack() { return stack; }
void ExtractLiteFrameInfoFromStack(std::vector<uint64_t>& liteFrameInfos,
size_t steps = STACK_UNWIND_STEP_MAX) const;
static void GetStackTraceByLiteFrameInfos(const std::vector<uint64_t>& liteFrameInfos,
std::vector<StackTraceElement>& stackTrace);
static void GetStackTraceByLiteFrameInfo(const uint64_t ip, const uint64_t pc, const uint64_t fa,
StackTraceElement& ste);
virtual void FillInStackTrace() = 0;
static const int NEED_FILTED_FLAG;
protected:
std::vector<FrameInfo> stack;
uint32_t n2cCount;
uint32_t* anchorFA = nullptr;
FrameType lastFrameType;
#ifdef _WIN64
UnwindContextStatus uwCtxStatus;
#endif
private:
uint32_t* GetAnchorFAFromMutatorContext() const;
const UnwindContext* topContext;
bool isReliableN2CStub;
};
#define MRT_UNW_GETCALLERFRAME(frame) \
do { \
void* ip = __builtin_return_address(0); \
void* fa = __builtin_frame_address(0); \
FrameAddress* thisFrame = reinterpret_cast<FrameAddress*>(fa); \
(frame).mFrame.SetIP(reinterpret_cast<uint32_t*>(ip)); \
(frame).mFrame.SetFA(thisFrame->callerFrameAddress); \
} while (0)
}
#endif