Skip to content

widberg/msvc8.0_patcher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

msvc8.0_patcher

A conglomeration of magical artifacts that patch MSVC 8.0 binaries to add pseudo-__usercall syntax from IDA Pro in support of the FUELDecompilation project.

Syntax

Example 1

Pass x in edx and y on the stack. Callee cleans up the stack. Only ecx needs to be caller preserved across the call, if it is live; eax and edx do not need to be preserved even though they are traditionally call spoiled registers.

int __usercall __edx __spoils __ecx func(int x, int y)
{
  return x + y;
}

Example 2

Pass this in esi, x in ebx, and y on the stack. Caller cleans up the stack. Default spoils behavior.

int __userpurge __esi __ebx class::func(int x, int y)
{
  return x + y + this->z;
}

Usage

Clone the repository and submodules. Use a modern Visual Studio and Ninja to build the project. Make sure to define -DMSVC_ORIGINAL_BIN=<path to original msvc8.0 bin directory> -DMSVC_PATCHED_BIN=<path to patched msvc8.0 bin directory>. A compatible MSVC 8.0 can be found in the widberg/msvc8.0 repository.

TODO

Ordered by priority.

  • For some reason reg args are treated as "used" aka overwritten even if they aren't
    • Only the regs not in the clobber list
    • This is really annoying because it makes it impossible to match functions using regs other than eax, ecx, and edx for args
    • Actual flex params are not treated as used, try to copy what those do if I can figure that out
  • figure out if we need spoils/preseved regs
    • Probably need preserved
    • The compiler will save off eax before a call to a function that doesn't modify it but in the game it doesn't
    • likely the ltcg optimizer can be more restrictive with the spoils list
    • this might solve the ebp problem too?
  • Figure out if we need a way to force using base pointer as reg
    • Sometimes the compiler uses another reg when it should be using ebp
    • Even with /Oy- it still uses another reg
    • This could be due to not matching instructions elsewhere in the functions due to the previous todo
  • Store the regs data out of band
    • We're stepping on memory used by the compiler putting the pointer where we are
  • force inline/no inline per call
    • Likely unnecessary
    • Not sure if LTCG would cause anything to be inlined that wouldn't be otherwise if available
    • If we do need this then probably just allow forceinline and noinline keywords after a function call and tag the call

Notes

  • Which regs are supported for parameters
    • IDA thinks the compiler passes floats in st regs for user code but I think its confused
    • I don't see any evidence that the compiler is capable of using st regs for flex params. Only the 8 gprs and 8 xmm regs are used
    • The compiler may emit calls to compiler runtime functions such as __ftol2_sse which does pass the argument in st0 but these are a special case an user code will never do this
    • FUEL doesn't use xmm regs for params outside of library code so I won't bother supporting it
    • FUEL also never passes arguments in EBP or ESP

About

A conglomeration of magical artifacts that patch MSVC 8.0 binaries to add pseudo-__usercall syntax

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors