gimli icon indicating copy to clipboard operation
gimli copied to clipboard

Read, modify, write?

Open Fee0 opened this issue 1 year ago • 6 comments

Can I use gimli to patch some stuff in the eh_frame section of an executable? I saw there are two different structs for e.g. CIE's for read and write. So I assume reading, modifying and writing again is not really a use case? Probably because changing the size of anything would corrupt the whole binary? Is patching inline, without changing the size, out of scope as well?

Fee0 avatar May 09 '23 07:05 Fee0

This isn't really supported currently. There is write::FrameTable::from to allow reading an entire table and then writing it again, but so far it's only been used for testing purposes that I know of, and support for modification is missing.

For patching individual entries, we could expose some of the internals of that if it helps, such as FrameDescriptionEntry::from and FrameDescriptionEntry::write, but I suspect you might be better of using only the read portion of gimli and doing the patching code yourself.

philipc avatar May 09 '23 09:05 philipc

Does something prevent me in general from writing a converter from the read data structures to the write data structures?

Are there some information missing/not accessible where I would need to do more reading/writing myself?

E.g. I noticed that the CallFrameInstruction enums do not contain the same amount of instructions for read and write.

Fee0 avatar May 10 '23 08:05 Fee0

FWIW, there are some half-baked ideas about similar transformations over DWARF in https://github.com/bytecodealliance/wasmtime/issues/5537

Note that patching an executable is a bit harder of a constraint because the size of the encoded DWARF can change depending on what you're doing (even just changing an index can change size because of LEB128 encoding).

fitzgen avatar May 11 '23 18:05 fitzgen

Does something prevent me in general from writing a converter from the read data structures to the write data structures?

These should already exist. I linked to some before.

Are there some information missing/not accessible where I would need to do more reading/writing myself?

The read API should provide all the information. The write API is aimed at producing DWARF, not patching it, so it may not support everything you need for patching.

E.g. I noticed that the CallFrameInstruction enums do not contain the same amount of instructions for read and write.

See write::CallFrameInstruction::from to see which read instructions we support for writing; I think SetLoc and Nop are the only ones missing. For the others, there isn't a one to one correspondence because write chooses between instructions as needed, so this isn't ideal for the patching scenario.

philipc avatar May 11 '23 21:05 philipc

I know that patching will very likely result in having to extend the section in the binary and shift all following sections accordingly which is hard. So, I consider the patching use case to be rather niche.

In general, would you like gimli to have a patching ability anyway?

To be clear, by patching I mean to not just change existing CIE / FDE, but also adding new records of these including byte code instructions etc.

Fee0 avatar May 12 '23 09:05 Fee0

I know that patching will very likely result in having to extend the section in the binary and shift all following sections accordingly which is hard.

That part of the problem is outside the scope of gimli. You'll need to implement it in whatever is processing the ELF/Mach-O/COFF.

In general, would you like gimli to have a patching ability anyway?

It depends on how you are proposing to implement the patching ability. Options that might fit in gimli are adding mutation of the existing write data structures, or adding a visitor for the transformation as mentioned in https://github.com/bytecodealliance/wasmtime/issues/5537.

It might be best to implement a prototype first to see what meets your needs.

philipc avatar May 12 '23 11:05 philipc