5 ms·
Rewrite your Ruby VM at runtime to hot patch useful features
- teilo 17y agoThis is a perfect example of "because I can". Never ever do this for real.
- tptacek 17y agoIn a dev/test environment, do whatever works best and fastest. If you have the skillset and toolset to jump right to the ABI to solve a problem, it's pretty silly to stay in the confines of MRI just out of orthodoxy.
- futuremint 17y agoI'm probably not thinking this through all the way, but wouldn't a memory profiler be more straight-forward, and less dangerous in Smalltalk? I haven't built one myself, but I know that the Seaside framework comes with a built-in memory profiler. Doing intercession of messages to objects in Smalltalk isn't trivial, but it isn't voodoo either. I whipped up a quick method replacement class that swaps out a database 'save' method's behavior for testing. However, I would imagine that trying to replace VM primitive calls would lead to some not-so-nice side effects (maybe... or would it just make the image slower?). I like Ruby, and I like Smalltalk, but I'm liking Smalltalk much better lately because the "turtles all the way down" aspect which makes things like a memory profiler much less "voodoo-y".
- tptacek 17y agoReplace "memory profiler" with any other piece of runtime manipulation, and the point is just as valid with Smalltalk. It is not, in fact, "turtles all the way down"; eventually you hit the ABI, and that's what this article is talking about.
- tptacek 17y agoI love posts like this, but I think the authors would benefit from a close read of the Microsoft Detours paper, which runtime patchers have been cribbing from for the past 5 years or so. The general Detours approach: * Disassemble the first N bytes of a target location * Scoop N bytes worth of opcodes out of the target, and re-host them somewhere heap-allocated * Replace the N bytes with an absolute jump to a heap-allocated trampoline * Bounce to your code * Execute the scooped-up N bytes worth of opcodes * Jump back to the target This approach (what the post calls "caller-side trampolines") works well when your targets are function prologues, and less well when it's an arbitrary bblock. We have an implementation in pure Ruby, complete with a pure-Ruby ia32 assembler (which is one of the most useful little pieces of code I've written) at Timur's Ragweed repository --- google "Ruby ragweed github".
- bensummers 17y agoSee also: http://rentzsch.com/mach_override http://rentzsch.com/mach_override It used to be used quite comprehensively to add non-Apple-sanctioned functionality to Mac OS X. Hopefully it isn't used much these days.
- KirinDave 17y agoI am surprised this works. I was under the impression that more modern implementations write protected the pages that libraries in the initial link are loaded to. There is really no good reason for them to be writable save for extremely strange uses such as in this article. Is this assumption false?
- tptacek 17y agoUserland code can't usually modify program text. The kernel can. The kernel will modify program text on your program's behalf if you own the process you want to modify. Depending on the OS, that happens via WriteProcessMemory, ptrace, Mach, or procfs.
- KirinDave 17y agoWell in the code Joe posted, he takes the marked pages and calls mprotect on them so they can be modified. I am surprised he's allowed to do this at all. Is there ever a legitimate reason to do this in most modern systems? I mean besides this crazy-like-a-fox twin trampoline system, or for compromising binaries at runtime maliciously. The days of overlays are long gone. :)
- tptacek 17y agoint main(int argc, char **argv) { void *faddr = strxfrm; void *paddr = (void*) ((u_int32_t)faddr & 0xfffff000); if(mprotect(paddr, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) >= 0) { ((u_char *)faddr)[0] = 0xcc; strxfrm("foo", "", 0); } else perror("mprotect"); exit(0); } $ ./mp Trace/BPT trap The simplest answer to your question that jumps into my head is "relocations", but I'm always surprised by the everyday craziness of the C runtime and the Unix ABI, so I'm sure there's a simpler answer.