[lldb-dev] Redefining functions

Filipe Cabecinhas filcab+lldb-dev at gmail.com
Mon Aug 8 17:08:44 PDT 2011


Hi!

On Mon, Jul 18, 2011 at 18:13, Greg Clayton <gclayton at apple.com> wrote:

>
> On Jul 18, 2011, at 1:32 PM, Filipe Cabecinhas wrote:
>
> > Hi,
> >
> > I'm trying to create an LLDB command that sets an internal breakpoint for
> a function, and then executes some code, but I'm having come difficulties...
> >
> > I've seen the expression command, which does something close to what I
> want to do after the breakpoint, but I have some doubts. I want the code to
> be able to return from the function where it's called, but the
> "target->EvaluateExpression" doesn't let the code return from it (while I
> would like to execute code with something like "if (condition) return NULL;
> more code…"). Is there a way to compile arbitrary code (with return
> statements) and execute it?
>
> Not currently.
>
> >
> > Is there a way to create something like an anonymous function (with
> certain parameters), and have it compiled and linked, while looking up
> global variables?
>
> Current expressions can do the lookups, but as you already know they don't
> live beyong the first invocation.
>
> > ClangUtilityFunction doesn't look up any variables, and I can't seem to
> find a way to look up global variables without a Frame object.
>
> For globals you shouldn't need the frame. If the globals are in your symbol
> table and are external you might be able to use dlsym().
>
> > Is there a way to know a function (or method)'s address from its
> prototype?
>
> A normal fuction that was compiled into your code or an expression
> function?
>

For my first try (a command like "expr" but that would re-define functions)
I wantes to find out the location of some function/method, given the
prototype (e.g: "ProcessGDBRemote::StartDebugserverProcess(char const*)"). I
would suppose we could mangle the name and try to find the symbol. I haven't
seen any way to do that in lldb, but I suppose it's possible to do. Maybe
I'm looking at it wrong.



> > My final purpose is to be able to redefine functions on-the-fly (with
> caveats for inlined functions, etc). The only way I saw that could work was
> creating a (similar) function and making the other function a trampoline
> (either using breakpoints, or writing a jmp expression at its address)… Did
> I miss another easier way?
>
> We do want the ability to just compile up something in an LLDB command but
> we don't have that yet. You currently can do this via python if you really
> want to by making a source file, invoking the compiler on it, and then
> making a dylib. You can then use the "process load" command to load the
> shared library:
>
> (lldb) process load foo.so
>
> So if you have your python code do the global variable lookups and create
> the source code, you could hack something together.
>
> When/if you are ready to try and take over the function, you can look for
> any "Trampoline" symbols. For a simple a.out program on darwin we see:
>
> (lldb) file ~/Documents/src/args/a.out
> Current executable set to '~/Documents/src/args/a.out' (i386).
> (lldb) image dump symtab a.out
> Symtab, file = /Volumes/work/gclayton/Documents/src/args/a.out, num_symbols
> = 18:
>               Debug symbol
>               |Synthetic symbol
>               ||Externally Visible
>               |||
> Index   UserID DSX Type         File Address/Value Load Address       Size
>               Flags      Name
> ------- ------ --- ------------ ------------------ ------------------
> ------------------ ---------- ----------------------------------
> ....
> [   10]     16     Trampoline   0x0000000000001e76
>  0x0000000000000006 0x00010100 __stack_chk_fail
> ...
> [   12]     18     Trampoline   0x0000000000001e7c
>  0x0000000000000006 0x00010100 exit
> [   13]     19     Trampoline   0x0000000000001e82
>  0x0000000000000006 0x00010100 getcwd
> [   14]     20     Trampoline   0x0000000000001e88
>  0x0000000000000006 0x00010100 perror
> [   15]     21     Trampoline   0x0000000000001e8e
>  0x0000000000000006 0x00010100 printf
> [   16]     22     Trampoline   0x0000000000001e94
>  0x0000000000000006 0x00010100 puts
>
> On MacOSX, you could then easily patch the trampoline code to call your own
> function for say "printf" by modifying the function address in the PLT
> entry.
>
>
That would be a good solution, at least to substitute functions that are
accessed with the PLT. But are the trampolines reified (I don't think so)?
Or should I just write to the process' PLT directly, after loading the
function?

What about replacing other functions? Let's say that I want to replace a
random function (that I can't replace by changing the PLT). If I have
information about which functions call it, I can replace the definition of
the function by a jump and, if necessary, get the new versions of the
functions that call the replaced function (doing the same to them, for a
maximum of X iterations, for example). Though I would suppose clang won't
give us that information (at least for now).

Thanks for the help,

  Filipe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20110808/8b97c876/attachment.html>


More information about the lldb-dev mailing list