CasualX / pelite

Lightweight, memory-safe, zero-allocation library for reading and navigating PE binaries.
MIT License
280 stars 42 forks source link

UNWIND_INFO and unwind_info() is broken #252

Closed namazso closed 2 years ago

namazso commented 2 years ago

code:

    let unwind = fun.unwind_info().unwrap();
    let codes = unwind.unwind_codes();
    println!("RVA {:02x} has {} unwind codes:", fun.image().BeginAddress, codes.len());
    for code in codes {
        println!("CodeOffset {:02x} UnwindOpInfo {:02x} FrameOffset {:04x}", code.CodeOffset, code.UnwindOpInfo, code.FrameOffset);
    }

output:

RVA 00200010 has 4 unwind codes:
CodeOffset 02 UnwindOpInfo 06 FrameOffset 0603
CodeOffset 06 UnwindOpInfo 32 FrameOffset 3002
CodeOffset 02 UnwindOpInfo 04 FrameOffset 0003
CodeOffset 01 UnwindOpInfo 06 FrameOffset 0602

real data:

RUNTIME_FUNCTION(00200010h, 00200040h)
  UNWIND_INFO: 00041B70h
    version: 2
    flags: (none)
    prolog: 6h
    count: 4
    frame register: (none)
    frame register offset: 0h
    unwind codes:
      02h UWOP_EPILOG(at_end: false, size: 02h)
      03h UWOP_EPILOG(offset: 0003h)
      06h UWOP_ALLOC_SMALL(32)
      02h UWOP_PUSH_NONVOL(RBX)

likely caused by mismatch of type. here:

#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
#[repr(C)]
pub struct UNWIND_CODE {
    pub CodeOffset: u8,
    pub UnwindOpInfo: u8,
    pub FrameOffset: u16,
}

real (in C):

struct UNWIND_CODE
{
    BYTE offset;
    BYTE code : 4;
    BYTE info : 4;
};

docs: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-160

CasualX commented 2 years ago

Thanks for the report, I'm not sure how I messed this up in the first place.