How do you implement relocations for a native (C/C++) architecture plugin? #1620
-
In binaryninjacore.h there is a struct clearly intended for this, but its members are undocumented: struct BNCustomRelocationHandler
{
void* context;
void (*freeObject)(void* ctxt);
bool (*getRelocationInfo)(void* ctxt, BNBinaryView* view, BNArchitecture* arch, BNRelocationInfo* result,
size_t resultCount);
bool (*applyRelocation)(void* ctxt, BNBinaryView* view, BNArchitecture* arch, BNRelocation* reloc, uint8_t* dest,
size_t len);
size_t (*getOperandForExternalRelocation)(void* ctxt, const uint8_t* data, uint64_t addr, size_t length,
BNLowLevelILFunction* il, BNRelocation* relocation);
};
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Maybe the best answer is... just show me the code.
While the above ELF x86 relocation handler is one of the most simple ones the MIPS relocation handler is rather complicated:
Generally speaking, relocations are used for modifying bytes at a given address to point to some symbol. These symbols usually don't exist in the binary and rather exist in some other module, which Binary Ninja doesn't know about. To solve this issue we first record all the symbols referenced by this binary and at the point of BinaryView finalization we assign these symbols addresses in a fake segment which we create at the end of the binary. The relocation information is used for three distinct purposes: In ELFBinaryView::Parse
BinaryView::Read()
Function::GenerateLiftedIL()
Of the 3 methods a relocation handler specifies only GetRelocationInfo The BinaryView needs to query the architecture for how different relocation types should be handled. For ELF files in particular is really important to know which relocations are: JumpSlot, Global, and Copy. This mainly involves filling out the list of structures passed in from the BinaryView. The list of structures is an in/out parameter. The structure is initially filled out with the information from the BinaryView for ELF files this the following information is valid:
The important fields for defining symbols: The if the following conditions evaluate to true we will create a pointer data variable
If the implementer doesn't specify a relocation handler the DefaultRelocation handler will be used:
If implementing your own ApplyRelocation method most of the fields can just be used for whatever purposes are desired. Honestly I should have just add some slack space to the end of the structure for user-defined structures. ApplyRelocation This part is done lazily for speed reasons. Instead of applying all relocations at once, relocations are applied on-demand as each page of memory is read using BinaryView::Read. The purpose of the method is to actually do the relocation. The implementer writes to the dest pointer the data that it wants the BinaryView to actually read. |
Beta Was this translation helpful? Give feedback.
Maybe the best answer is... just show me the code.