wip: generic MT DTI dumper w/ AOB-based vftable identification #1
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Complete refactor of the project into a (more) universal MTFramework DTI dumper + related tooling.
In order to combat the crashing/instability issues of the current
master
branch, this refactoring opts for a new multi-tiered approach to dumping.Associate DTI <-> vftables without class instantiation
In order to get the vftable for a given class without calling the constructor directly, we utilize the
::GetDTI
virtual function to associate a DTI object with the vftable:lea rax, <DTI OBJECT>; RET
pattern used in all::GetDTI
methods.::GetDTI
methodsNOTE: This still isn't perfect, as there are some methods that return DTI objects with this same pattern that are not the ::GetDTI method. Additionally, there are some classes that have inherited from a DTI class, but have not registered themselves in the DTI table / overriden the relevant virtual member functions.
Dumping property lists (safely)
To populate the property list for a given class, we must have a "valid" instance in memory to pass to the populate member function (as it tries to deference the pointer). To work around this without calling the constructor (for stability) we create a fake object (empty byte buffer the size of the class, as defined by the DTI) and set the first element the vftable.
When calling the
::CreateProperty
function we sometimes run into certain cases where the vftable we found was incorrect (see note in section above), or has code that would othewise crash the process or hang the current thread (lock/mutex, loop, etc). The crashes can be prevented with a SEH handler, but the hanging calls pose issues.If order to work around this, when attempting to dump the property list create a new thread with it's own SEH exception handler. If the thread does not signal completion within a certain period of time, we assume that the population has failed (either due to crash of hanging), kill the job thread, then continue.
TODO: We currently don't track which have failed for further evaluation. Create a ticket for this.
Separation of property dumping and processing
Rather than needing to run this dumper for every small formatting/output generator change, I've decided to split out dumping from the processing as much as possible. This was done by making the dumper only aware of the binary layout of each games structures (MtProperty, MtPropertyList, etc), and dumping the raw data to a JSON file.
This dump while large, convoluted, and unwieldy can be used more easily from external tooling (e.g. the process_dump.py script).
Example DTI dump and processing of MHW
src/MT/game/MHW.h
:MtProperty
class definitionMT_DTI_HASH_TABLE_OFFSET
MT_TYPE_TABLE_RVA_OFFSET
MT_TYPE_TABLE_COUNT
scripts/profiles/MHW.json
is correct:Build the project & inject into MHW
Process the raw dump with the script
flat_dump.h
will be generated with a format similar to the original MHW-ClassPropDump project.