Re: [DynInst_API:] Basic Blocks and Register Access


Date: Tue, 29 Apr 2014 10:56:10 -0500
From: Bill Williams <bill@xxxxxxxxxxx>
Subject: Re: [DynInst_API:] Basic Blocks and Register Access
On 04/28/2014 05:37 PM, Sergej Proskurin wrote:
Dear Bill,

When you say this crashes with a segfault at the point of insertion,
do you mean the mutator crashes when inserting the code, or the
mutatee crashes when executing it? In either case, a stack trace will
be helpful; in the latter case if you're running the mutatee under
Dyninst (rather than as a rewritten binary) setting
DYNINST_DEBUG_CRASH=core and enabling core files will get you a
mutatee stack trace and core dump.

Also, all of the safety operations that Dyninst performs (register
saving, stack alignment, etc) will be absent if you're inserting these
calls with PatchAPI directly. Unless that's explicitly desirable, or
you're replacing our code generation with something that produces more
optimized snippets, there's not a lot of benefit to working at the
PatchAPI level. sta

At the point of the crash, the mutator crashes - not the mutatee, making
the environment variable DYNINST_DEBUG_CRASH obsolete at this point.
Dmesg, however, reports the following error:
---
[93133.621503] BinEditor[3863]: segfault at 109 ip b72c0ef3 sp bf811390
error 4 in libdyninstAPI.so.8.1.2[b7139000+27d000]
---

The provided stack trace is:
---
...
Program received signal SIGSEGV, Segmentation fault.
0xb7b88ef3 in func_instance::obj() const () from
/usr/lib/libdyninstAPI.so.8.1
(gdb) bt
#0  0xb7b88ef3 in func_instance::obj() const () from
/usr/lib/libdyninstAPI.so.8.1
#1  0xb7b88f2b in func_instance::proc() const () from
/usr/lib/libdyninstAPI.so.8.1
#2  0xb7b8a4aa in func_instance::blockEntryPoint(block_instance*, bool) ()
    from /usr/lib/libdyninstAPI.so.8.1
#3  0xb7b4203b in instPoint::blockEntry(func_instance*, block_instance*) ()
    from /usr/lib/libdyninstAPI.so.8.1
#4  0xb7b08f94 in BPatch_basicBlock::findEntryPoint() () from
/usr/lib/libdyninstAPI.so.8.1
#5  0x0805285b in binedit::instrument_epilog (this=0x808c028,
addr=0x804850a,
     bytes=0xbfffee63 "\213E\004[9\330\017\204\005", new_nbytes=17,
nbytes=1, block=0x87c56c8)
     at ../src/binedit.cpp:1036
#6  0x0804f3a9 in binedit::stack_protect_func (this=0x808c028,
func=0x87c4138)
     at ../src/binedit.cpp:398
#7  0x0804ef3e in binedit::stack_protect (this=0x808c028) at
../src/binedit.cpp:273
#8  0x08057b23 in perform_operation (editor=0x808c028, operation=2,
func1=..., func2=...)
     at ../src/main.cpp:63
#9  0x080583f8 in main (argc=13, argv=0xbffff074) at ../src/main.cpp:277
---

The problem here is that the PatchAPI is surprisingly not able to find a
PatchAPI::Point*. And since PatchModifier::insert function cannot access
a valid point the process crashes:
---
/* this does not find a valid point within the block of any type (entry,
exit, during) */
Point* point = mgr->findPoint(Location::Block(block), Point::BlockTypes,
true);
---

This seems unusual, and suggests that there's some memory corruption going on somewhere. Any chance you can run this under valgrind and send me the results?


Dyninst allows access to original register values (through the BPatch
interface). It allows instruction replacement through the PatchAPI
interface, which would allow bit-twiddling of this sort. The higher a
level of abstraction you can express the change at, the more likely it
is that we can do the right thing (or a close approximation
thereof)--are you trying to replace one variable with another? Change
how a variable is referenced? Compensate for changes elsewhere in the
code?
Exaclty: I am trying to compensate changes of already inserted code: My
implementation increases the stack frame, which is the reason why I have
to adjust all addresses referenced through the %esp register.

There's code in Dyninst that transforms IP-relative memory accesses to account for code relocation; you might be able to borrow/modify/extend that to transform stack references.

If you want a working example of instruction replacement through
PatchAPI, I'd take a look at Mike Lam's CRAFT tool, available on
SourceForge here: http://sourceforge.net/projects/crafthpc/

It's replacing every double-precision instruction in a program with
code to shadow the calculation in single-precision and evaluate the
error introduced by that replacement; if you strip out the evaluation
portion of that, the shadow machinery should give you a pretty good
idea of where to start with register manipulation. But, as per above,
there may be an easier way to do whatever it is you're aiming for.

Thanks for the hint. I have already had a closer look into Mike Lam's
CRAFT tool - but unfortunately did not find a solution to my issue, yet.

Best regards,
Sergej



--
--bw

Bill Williams
Paradyn Project
bill@xxxxxxxxxxx
[← Prev in Thread] Current Thread [Next in Thread→]