Skip to content

PAL_VirtualUnwind - is there need to add special case for NetBSD? #5637

@krytarowski

Description

@krytarowski

File: src/pal/src/exception/seh-unwind.cpp

BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers)
{
    int st;
    unw_context_t unwContext;
    unw_cursor_t cursor;

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_ARM64_) || defined(_ARM_)
    DWORD64 curPc;
#endif

    if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0)
    {
        // The current frame is a source of hardware exception. Due to the fact that
        // we use the low level unwinder to unwind just one frame a time, the
        // unwinder doesn't have the signal_frame flag set. So it doesn't
        // know that it should not decrement the PC before looking up the unwind info.
        // So we compensate it by incrementing the PC before passing it to the unwinder.
        // Without it, the unwinder would not find unwind info if the hardware exception
        // happened in the first instruction of a function.
        CONTEXTSetPC(context, CONTEXTGetPC(context) + 1);
    }

#if UNWIND_CONTEXT_IS_UCONTEXT_T
    WinContextToUnwindContext(context, &unwContext);
#else
    st = unw_getcontext(&unwContext);
    if (st < 0)
    {
        return FALSE;
    }
#endif
    st = unw_init_local(&cursor, &unwContext);
    if (st < 0)
    {
        return FALSE;
    }

#if !UNWIND_CONTEXT_IS_UCONTEXT_T
    // Set the unwind context to the specified windows context
    WinContextToUnwindCursor(context, &cursor);
#endif

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_ARM64_) || defined(_ARM_)
    // OSX and FreeBSD appear to do two different things when unwinding
    // 1: If it reaches where it cannot unwind anymore, say a 
    // managed frame.  It wil return 0, but also update the $pc
    // 2: If it unwinds all the way to _start it will return
    // 0 from the step, but $pc will stay the same.
    // The behaviour of libunwind from nongnu.org is to null the PC
    // So we bank the original PC here, so we can compare it after
    // the step
    curPc = CONTEXTGetPC(context);
#endif

    st = unw_step(&cursor);
    if (st < 0)
    {
        return FALSE;
    }

    // Check if the frame we have unwound to is a frame that caused
    // synchronous signal, like a hardware exception and record it
    // in the context flags.
    if (unw_is_signal_frame(&cursor) > 0)
    {
        context->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
    }
    else
    {
        context->ContextFlags &= ~CONTEXT_EXCEPTION_ACTIVE;
    }

    // Update the passed in windows context to reflect the unwind
    //
    UnwindContextToWinContext(&cursor, context);
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_ARM64_) || defined(_ARM_)
    if (st == 0 && CONTEXTGetPC(context) == curPc)
    {
        CONTEXTSetPC(context, 0);
    }
#endif

    if (contextPointers != NULL)
    {
        GetContextPointers(&cursor, &unwContext, contextPointers);
    }
    return TRUE;
}

How to check if I need the extra code path enabled also for NetBSD?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions