Indirect branch emulation

317 views
Skip to first unread message

Gabriel Ferreira Teles Gomes

unread,
Jan 22, 2013, 9:25:28 PM1/22/13
to dynamor...@googlegroups.com
Hello everyone,

I need your help.

I need to implement and test various techniques for indirect branch
emulation (apart from the hashtable lookup already provided by
DynamoRIO). To accomplish this goal, I have already started two
approaches (no success so far):

1) Write a client (using DynamoRIO's API) to modify every basic block
that ends in an indirect branch and add my own address lookup
code/routines.

2) By modifying DynamoRIO's core code, create several versions of it,
each one with a different technique for address lookup.

At this point I am already uncertain whether I should use the first or
the second approach.

Which one is better?
Can I actually do this using a client?
If so, what is the best way to determine if a basic block ends in an
indirect branch?


---

I am not sure if I should give a whole lot of details in this first
email, but if I should, here it goes:

I will explain what I did and what I learned.


First, I wrote a simple application with a single indirect jump over %rax
(attachment loadandjump.s, just in case). Also, right before the
lea/jump instruction pair, I wrote a sequence of 8 useless compare
instructions, which point me where I should look when debugging.

code snippet

.L2:
movl $0, -48(%rbp)
movl $1, -44(%rbp)
cmpl $0, -4(%rbp)
cmpl $0, -4(%rbp)
cmpl $0, -4(%rbp)
cmpl $0, -4(%rbp)
cmpl $0, -4(%rbp)
cmpl $0, -4(%rbp)
cmpl $0, -4(%rbp)
cmpl $0, -4(%rbp)
leaq .L6, %rax
jmp *%rax

Then I verified that I can run it flawlessly with DynamoRIO, whether
using clients or not.

Finally, I tried my first approach:

1)

In the first approach, I wrote a very small client (attachment
dumpbb.c) that prints the instructions in a basic block (at the moment
of its creation). For that, I use the disassembly routines of the API.

code snippet:

dr_printf("*** client dumpbb start\n");
for (instr = instrlist_first(bb);
instr != instrlist_last(bb);
instr = next) {
next = instr_get_next(instr);
disas_size = instr_disassemble_to_buffer(dr_context, instr,
disas_str, 1024);
disas_str[disas_size] = '\0';
dr_printf("%s\n", disas_str);
}
dr_printf("*** client dumpbb stop\n");

It first surprised me, because I had not found any indirect branches.
This is the interesting part of the output:

output snippet:

*** client dumpbb start
push %rbp %rsp -> %rsp 0xfffffff8(%rsp)
mov %rsp -> %rbp
mov $0x00000001 -> 0xfffffffc(%rbp)
mov $0x00000000 -> 0xffffffd0(%rbp)
mov $0x00000001 -> 0xffffffd4(%rbp)
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
lea 0x00400545 -> %rax
*** client dumpbb stop

But then I thought that it should be normal for the client not to
receive the control transfer instruction and that I probably should
not use clients, but modify the core itself (maybe rushing was my
first mistake, here =[). Then I said: "OK, let's dig into DR", and
that brought me to the second approach.

2)

In the second approach, the first thing that I did was to look for the
routines that create the instruction lists and to find where my
indirect jump got removed.

The removal happened in the function mangle_bb_ilist, that is called
by build_bb_ilist, that, in turn, is called by
build_basic_block_fragment (I hope this is right).

To verify that my suppositions were correct, I modified the code with
a copy of the disassembly loop that I had used in my client
(attachment interp.c.patch).

I was happy to see that my indirect jump was there:

output snippet

*** dumping pre-mangle bb start
push %rbp %rsp -> %rsp 0xfffffff8(%rsp)
mov %rsp -> %rbp
mov $0x00000001 -> 0xfffffffc(%rbp)
mov $0x00000000 -> 0xffffffd0(%rbp)
mov $0x00000001 -> 0xffffffd4(%rbp)
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
cmp 0xfffffffc(%rbp) $0x00000000
lea 0x00400545 -> %rax
jmp %rax
Multi-way branch found.
exit type: 12
exit target: 40552900
*** dumping pre-mangle bb stop

I decided to go on and dig deeper into the code with the goal of
modifying the address lookup routines. I did this for a long time and
that improved my insight into the code, as well as it increased my
doubts. Now, I decided to ask for your help, because I am afraid I
might be going the wrong way.

What do you think?
Should I keep trying to modify the core of DynamoRIO?
If so, could you point me in the right direction? (I saw some code
being written to the code cache by insert_exit_stub, and I was
expecting functions insert_inlined_ibl or insert_jump_to_ibl to be
called, but which weren't).


Kind regards,
Gabriel
loadandjump.s
dumpbb.c
inter.c.patch

Reid Kleckner

unread,
Jan 22, 2013, 10:43:33 PM1/22/13
to dynamor...@googlegroups.com
On Tue, Jan 22, 2013 at 9:25 PM, Gabriel Ferreira Teles Gomes <gabriel....@gmail.com> wrote:
Hello everyone,

I need your help.

I need to implement and test various techniques for indirect branch
emulation (apart from the hashtable lookup already provided by
DynamoRIO). To accomplish this goal, I have already started two
approaches (no success so far):

1) Write a client (using DynamoRIO's API) to modify every basic block
that ends in an indirect branch and add my own address lookup
code/routines.

2) By modifying DynamoRIO's core code, create several versions of it,
each one with a different technique for address lookup.

I would use this approach.  The current indirect branch handling is pretty core to the way DR works, and trying to beat it performance wise would mean replacing the existing implementation.  Although a quick cache might help.  Derek might know more from past experience optimizing ibl stuff at Determina.
 
code snippet:

    dr_printf("*** client dumpbb start\n");
    for (instr = instrlist_first(bb);
         instr != instrlist_last(bb);
         instr = next) {

The termination condition should be instr != NULL.  instrlist_last(bb) points to the real instruction at the end of the list.  It's not a C++ STL container.  :)
 
The removal happened in the function mangle_bb_ilist, that is called
by build_bb_ilist, that, in turn, is called by
build_basic_block_fragment (I hope this is right).

Yes, it should replace the indirect jmp with a jump to the right ibl routine after the client has seen the original jmp.
 
What do you think?
Should I keep trying to modify the core of DynamoRIO?
If so, could you point me in the right direction? (I saw some code
being written to the code cache by insert_exit_stub, and I was
expecting functions insert_inlined_ibl or insert_jump_to_ibl to be
called, but which weren't).

There is a limitation in DR that each bb (bb, not trace) have a single terminating app control flow instr.  Whatever you try, you probably want to have multiple exits for multiple targets, so you will probably need to do it inside DR.  I actually wanted to experiment with a few N-element ibl caches for large apps like chrome.  Usually, DR's traces help eliminate most common indirect branches with a spill+lea+jexcz pattern, but for short testing runs, trace building can dominate execution time, so I usually disable them.

Reid

Gabriel Ferreira Teles Gomes

unread,
Feb 20, 2013, 1:02:05 PM2/20/13
to dynamor...@googlegroups.com
Hi Reid,

Thank you for the feedback. I followed your advice and kept trying to
understand the core of DR.
Now, I know a lot more, but I still have some doubts that I could not
answer myself.
Perhaps, you could help me again with one of them.

This one is about DR options.

In function emit_indirect_branch_lookup (core/x86/emit_utils.c:5228 at
rev. 1815) there is one small section of code that is not reached due
to my runtime configuration (inline_ibl_head == false). Here it is:

code snippet (core/x86/emit_utils.c:5395)

if (inline_ibl_head) {
compare_tag = INSTR_CREATE_cmp(dcontext,
OPND_CREATE_MEMPTR(REG_XCX,
HASHLOOKUP_TAG_OFFS),
opnd_create_reg(REG_XBX));
APP(&ilist, compare_tag);

/* TODO: check whether the static predictor can help here */
/* P4OG:2-18 "Use prefix 3E (DS) for taken and 2E (CS) for
not taken cbr" (DS == PREFIX_DATA) */
APP(&ilist,
INSTR_CREATE_jcc(dcontext, OP_jne_short,
opnd_create_instr(next_fragment_nochasing)));

append_ibl_found(dcontext, &ilist, ibl_code, patch,
HASHLOOKUP_START_PC_OFFS, true,
only_spill_state_in_tls,
target_trace_table ?
DYNAMO_OPTION(trace_single_restore_prefix) :
DYNAMO_OPTION(bb_single_restore_prefix),
NULL);
} else ...

I believe that this code is some sort of implementation of what people
usually refer to as inline caching (or software indirect branch
prediction), and I would like to use it. Is my understanding correct?

I tracked the uses and definitions of the variable inline_ibl_head and
it can be set by some of DR runtime options. If, for instance, I use
the following options, the variable inline_ibl_head becomes true:

-indirect_stubs -thread_private -no_coarse_units

But if I use these options, DR crashes while emitting the lookup routine, in

<Application /home/gabriel/msc/dynamorio/trunk/test/loadandjump
(18569) DynamoRIO usage error : encode_cti error: target beyond 8-bit
reach>
<Usage error: encode_cti error: target beyond 8-bit reach
(/home/gabriel/msc/dynamorio/trunk/core/x86/encode.c, line 2175)
version 4.0.0, custom build
-no_shared_bbs -no_shared_traces -thread_private -indirect_stubs
-no_atomic_inlined_linking -inline_trace_ibl
-no_shared_trace_ibl_routine -no_finite_bb_cache
-no_finite_trace_cache


Am I choosing the wrong options?
How could I use DR options to enable inline_ibl_head to be true, and
the emission of the code?
I mean, if that is even possible.

Kind regards,
Gabriel


----------

Call stack:

#0 encode_with_patch_list (dcontext=0xffffffffffffffff,
patch=0x40029070, ilist=0x7fffffffdb00,
start_pc=0x4002aec0)
at /home/gabriel/msc/dynamorio/trunk/core/x86/emit_utils.c:2320
#1 0x000000007123845f in emit_indirect_branch_lookup
(dcontext=0xffffffffffffffff, code=0x40029000,
pc=0x4002aec0 ,
fcache_return_pc=0x4002ad80 "eH\211<%\030",
target_trace_table=true, inline_ibl_head=true, ibl_code=0x40029010)
at /home/gabriel/msc/dynamorio/trunk/core/x86/emit_utils.c:5980
#2 0x00000000712053f0 in emit_ibl_routine_and_template
(dcontext=0xffffffffffffffff, code=0x40029000,
pc=0x4002aec0 ,
fcache_return_pc=0x4002ad80 "eH\211<%\030",
target_trace_table=true, inline_ibl_head=true, thread_shared=true,
branch_type=IBL_RETURN, source_type=IBL_TRACE_PRIVATE,
ibl_code=0x40029010) at
/home/gabriel/msc/dynamorio/trunk/core/x86/arch.c:780
#3 0x00000000712057ed in emit_ibl_routines
(dcontext=0xffffffffffffffff, code=0x40029000,
pc=0x4002ae92 ,
fcache_return_pc=0x4002ad80 "eH\211<%\030",
source_fragment_type=IBL_TRACE_PRIVATE, thread_shared=true,
target_trace_table=true, ibl_code_routines=0x40029010)
at /home/gabriel/msc/dynamorio/trunk/core/x86/arch.c:853
#4 0x0000000071204d31 in shared_gencode_init
(gencode_mode=GENCODE_X64) at
/home/gabriel/msc/dynamorio/trunk/core/x86/arch.c:377
#5 0x000000007120518c in arch_init () at
/home/gabriel/msc/dynamorio/trunk/core/x86/arch.c:599
#6 0x0000000071088501 in dynamorio_app_init () at
/home/gabriel/msc/dynamorio/trunk/core/dynamo.c:508
#7 0x00007ffff7bd3b01 in _init (argc=1, argv=0x7fffffffe978,
envp=0x7fffffffe988) at
/home/gabriel/msc/dynamorio/trunk/core/linux/preload.c:189
#8 0x00007ffff7debd25 in ?? () from /lib64/ld-linux-x86-64.so.2
#9 0x00007ffff7dddb2a in ?? () from /lib64/ld-linux-x86-64.so.2
#10 0x0000000000000001 in ?? ()
#11 0x00007fffffffeba6 in ?? ()
#12 0x0000000000000000 in ?? ()
> --
> You received this message because you are subscribed to the Google Groups
> "DynamoRIO Users" group.
> To post to this group, send email to dynamor...@googlegroups.com.
> To unsubscribe from this group, send email to
> dynamorio-use...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/dynamorio-users?hl=en.

Reid Kleckner

unread,
Feb 28, 2013, 2:36:07 PM2/28/13
to dynamor...@googlegroups.com
I think most of what you're finding is correct.  inline_ibl_head looks like an implementation of inline caching to me.

Some of the options haven't been exercised in a long time and aren't tested or compatible with each other, because they create a testing matrix with a very high complexity.

I see this FIXME in the code:
    /* FIXME: je_short ends up not reaching target for shared inline! */

Probably we shouldn't use OP_je_short for inline_ibl_head and shared gencode.

Sorry for the delayed response.


To unsubscribe from this group and stop receiving emails from it, send an email to dynamorio-use...@googlegroups.com.

To post to this group, send email to dynamor...@googlegroups.com.

Reid Kleckner

unread,
Feb 28, 2013, 2:36:42 PM2/28/13
to dynamor...@googlegroups.com
I meant to mention that this code predates my contributions to the project.  I don't know much about it or what alternatives were considered, but Derek might.

Gabriel Ferreira Teles Gomes

unread,
Apr 11, 2013, 3:36:05 PM4/11/13
to dynamor...@googlegroups.com
Hi Reid,

Thanks for your answers. I did not work much on it since our last emails. As a matter of fact, I think that "inline caching" is already there and that I just haven't seen it with my previous experiments. I will try to make sure that it is so, and if that is the case, I can do the opposite and disable "inline caching" for my future experiments.

I have another question though. I recently tried to activate the use of the "return stack" in DynamoRIO. I couldn't make it work (or even compile properly) and maybe that's because this option has not been exercised in a long time.

So,

Do you know if the "return stack" implementation has been tested lately?
Am I trying to activate it correctly?
Should I have any hope that I can fix it?

I will show you what I did to "active" the return stack, and then the various patches that I "blindly" applied to the code, in order to be able to, at least, compile it. But please feel free to not read the patches at all, as my own understanding of them is very poor. ;)

1) Return Stack activation:

In make/configure.cmake.h:212, I added the following statement (attachment:configure.cmake.h.patch):

#define RETURN_STACK

And that cause the compilation to fail

Should it be done somewhere else?


Kind regards,
Gabriel

--

2) The blind patches:

I incrementally patched the code with silly fixes, just to understand how much of it would fail to compile, and maybe estimate how much effort I would have to spend to properly fix the return stack, altogether.

2.1) in struct generated_code_t, some fields do not exist [anymore?]:

core/x86/arch.c: In function ‘arch_thread_init’:
core/x86/arch.c:1089:33: error: ‘generated_code_t’ has no member named ‘indirect_branch_lookup’
core/x86/arch.c:1090:33: error: ‘generated_code_t’ has no member named ‘unlinked_ib_lookup’

"fixed" with attachment arch.c.patch

2.2) then, in function emit_return_lookup, the [global?] variable shared_dcontext does not exist [anymore?]:

core/x86/emit_utils.c: In function ‘emit_return_lookup’:
core/x86/emit_utils.c:6283:52: error: ‘shared_dcontext’ undeclared (first use in this function)
core/x86/emit_utils.c:6283:52: note: each undeclared identifier is reported only once for each function it appears in

"fixed" with attachment emit_utils.c.1.patch

2.3) Then, in function mangle_indirect_branch_in_trace:

core/x86/interp.c: In function ‘mangle_indirect_branch_in_trace’:
core/x86/interp.c:5441:9: error: the address of ‘instr_is_return’ will always evaluate as ‘true’ [-Werror=address]

"fixed" with attachment interp.c.patch

2.4) Then, the parameters to the function opnd_create_pc might have changed:

core/x86/mangle.c: In function ‘return_stack_mangle_direct_call’:
core/x86/mangle.c:1722:9: error: passing argument 1 of ‘opnd_create_pc’ makes pointer from integer without a cast [-Werror]
core/x86/instr_inline.h:181:1: note: expected ‘app_pc’ but argument is of type ‘uint’
core/x86/mangle.c: In function ‘mangle_indirect_call’:
core/x86/mangle.c:2388:10: error: passing argument 1 of ‘opnd_create_pc’ makes pointer from integer without a cast [-Werror]
core/x86/instr_inline.h:181:1: note: expected ‘app_pc’ but argument is of type ‘ptr_uint_t’

"fixed" with attachment mangle.c.patch

2.5) Then, the comments in core/x86/x86.asm tell me that the return stack routines should be generated (not to be found in the form of C code, I guess).

/home/gabriel/msc/dynamorio/trunk/core/x86/x86.asm: Assembler messages:
/home/gabriel/msc/dynamorio/trunk/core/x86/x86.asm:1505: Error: .error argument must be a string

It is an intentional error, so I just remove the line

2.6) Finally, linking fails due to the generated return stack routine:

Linking C executable ../drsyms_bench
../../lib32/debug/libdynamorio.so.4.0: undefined reference to `return_lookup'
../../lib32/debug/libdynamorio.so.4.0: undefined reference to `unlinked_return'
../../lib32/debug/libdynamorio.so.4.0: undefined reference to `end_return_lookup'

"fixed" with attachment emit_utils.c.2.patch, and that's it.
DynamoRIO does not work. Well, I didn't expect that, anyway.

configure.cmake.h.patch
arch.c.patch
emit_utils.c.1.patch
interp.c.patch
mangle.c.patch
emit_utils.c.2.patch

Derek Bruening

unread,
Apr 11, 2013, 9:35:01 PM4/11/13
to dynamor...@googlegroups.com
On Thu, Apr 11, 2013 at 3:36 PM, Gabriel Ferreira Teles Gomes <gabriel....@gmail.com> wrote:
Do you know if the "return stack" implementation has been tested lately?

RETURN_STACK was an experimental option that has not been touched since 2003.  As you can see, there's no CMake option to turn it on, as it's not supported.  It's on a list of things that should probably be pruned from the code base.  It likely contains a lot of bit rot.  It certainly does not support 64-bit.

- Derek

Gabriel Ferreira Teles Gomes

unread,
Apr 11, 2013, 9:41:33 PM4/11/13
to dynamor...@googlegroups.com
Then I am 10 years too late. :P
Thanks anyway, Derek.

Gabriel Ferreira Teles Gomes

unread,
May 10, 2013, 7:09:53 PM5/10/13
to dynamor...@googlegroups.com
Hi,

I have two new questions.

1) I am trying to insert a clean call in the middle of the basic block
instrumentation but I get an error (curiously, if I insert the clean
call at the end of the BB, it works).

The attachments clientmiddle.c and clientend.c show the differences.
The attachment clientmiddle.log show a bit of the gdb output.

The line that causes the error is

core/x86/encode.c:2492 *field_ptr = (byte)((info->opcode &
0x00ff0000) >> 16);

field_ptr is set to 0 and I guess that it has been initialized by this line:

byte *field_ptr = cache_pc;


2) If I want to allocate memory for every fragment, how should I do it?
I did it already... it kind of works, but only if I never try to free.

My approach was:

In build_basic_block_fragment, I use nonpersistent_heap_alloc

ibspace = (ibspace_t *) nonpersistent_heap_alloc(dcontext,
sizeof(ibspace_t) HEAPACCT(ACCT_OTHER));

then I pass this structure to both build_bb_ilist, which uses some
fields in it, and to emit_fragment_ex, which saves the pointer to a
field in fragment_t.

For the freeing part I tried this:

nonpersistent_heap_free(dcontext, f->ibspace, sizeof(ibspace_t)
HEAPACCT(ACCT_OTHER));

But it didn't work. I mean, calls to nonpersistent_heap_free do work,
but at some point later in the execution, some call to the allocation
function fails.

Is there something obviously wrong?

The attachment free.log has some gdb output from when execution fails.
internalinstrumentation.patch is a diff from trunk revision 1815 (same
as release 4.0.1)

Still couldn't understand why variable p is set to 0x10 <Address 0x10
out of bounds>



On Thu, Apr 11, 2013 at 10:41 PM, Gabriel Ferreira Teles Gomes
clientmiddle.c
clientmiddle.log
clientend.c
free.log
internalinstrumentation.patch

Derek Bruening

unread,
May 12, 2013, 12:04:48 PM5/12/13
to dynamor...@googlegroups.com
On Fri, May 10, 2013 at 7:09 PM, Gabriel Ferreira Teles Gomes <gabriel....@gmail.com> wrote:
1) I am trying to insert a clean call in the middle of the basic block
instrumentation but I get an error (curiously, if I insert the clean
call at the end of the BB, it works).

The attachments clientmiddle.c and clientend.c show the differences.

I don't see a direct clean call: I see a call to dr_insert_mbr_instrumentation(), which requires that its instr_t parameter is an indirect branch (as the documentation says).  It looks like you pass it a label.  Did you run debug build?  It should assert on this incorrect usage of the routine.

Gabriel Ferreira Teles Gomes

unread,
Sep 4, 2013, 2:02:12 PM9/4/13
to dynamor...@googlegroups.com
The function append_ibl_found in file core/x86/emit_utils.c emits the instructions that transfer control to the target fragment, after an indirect branch lookup. The following line emits the jump itself:

        APP(ilist, INSTR_CREATE_jmp_ind(dcontext,
                                        OPND_CREATE_MEMPTR(REG_XCX, start_pc_offset)));

Could I also add code that print the target address to stderr, right before the jump instruction?
How would you do it?

Regards,
Gabriel

Gabriel Ferreira Teles Gomes

unread,
Sep 4, 2013, 2:50:51 PM9/4/13
to dynamor...@googlegroups.com
By the way,

Do the emitted lookup routines (shared_bb_ibl_ret,
shared_bb_ibl_indjmp, etc.) search in the same tables as the function
fragment_lookup in file core/fragment.c?

Or do they use separate mapping tables?

I mean, if I modify a basic block to use fragment_lookup and jump to
the returned fragment, will it jump to the same fragment as if I
haven't changed anything? Or could I end up jumping to a different
fragment?

On Wed, Sep 4, 2013 at 3:02 PM, Gabriel Ferreira Teles Gomes
<gabriel....@gmail.com> wrote:
> The function append_ibl_found in file core/x86/emit_utils.c emits the
> instructions that transfer control to the target fragment, after an indirect
> branch lookup. The following line emits the jump itself:
>
> APP(ilist, INSTR_CREATE_jmp_ind(dcontext,
> OPND_CREATE_MEMPTR(REG_XCX,
> start_pc_offset)));
>
> Could I also add code that print the target address to stderr, right before
> the jump instruction?
> How would you do it?
>
> Regards,
> Gabriel
>
> On Sunday, May 12, 2013 1:04:48 PM UTC-3, Derek Bruening wrote:
>>
>> On Fri, May 10, 2013 at 7:09 PM, Gabriel Ferreira Teles Gomes
>> <gabriel....@gmail.com> wrote:
>>>
>>> 1) I am trying to insert a clean call in the middle of the basic block
>>> instrumentation but I get an error (curiously, if I insert the clean
>>> call at the end of the BB, it works).
>>>
>>> The attachments clientmiddle.c and clientend.c show the differences.
>>
>>
>> I don't see a direct clean call: I see a call to
>> dr_insert_mbr_instrumentation(), which requires that its instr_t parameter
>> is an indirect branch (as the documentation says). It looks like you pass
>> it a label. Did you run debug build? It should assert on this incorrect
>> usage of the routine.
>
> --
> You received this message because you are subscribed to the Google Groups
> "DynamoRIO Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to dynamorio-use...@googlegroups.com.
> To post to this group, send email to dynamor...@googlegroups.com.
> Visit this group at http://groups.google.com/group/dynamorio-users.

Qin Zhao

unread,
Sep 4, 2013, 6:01:07 PM9/4/13
to dynamor...@googlegroups.com
On Wed, Sep 4, 2013 at 2:02 PM, Gabriel Ferreira Teles Gomes <gabriel....@gmail.com> wrote:
The function append_ibl_found in file core/x86/emit_utils.c emits the instructions that transfer control to the target fragment, after an indirect branch lookup. The following line emits the jump itself:

        APP(ilist, INSTR_CREATE_jmp_ind(dcontext,
                                        OPND_CREATE_MEMPTR(REG_XCX, start_pc_offset)));

Could I also add code that print the target address to stderr, right before the jump instruction?
 
print to stderr need lot of instructions, I do not think you can do that by inserting instructions right before that jump
 
How would you do it?

as I suggested before: dr_insert_mbr_instrumentation();
 

Regards,
Gabriel

On Sunday, May 12, 2013 1:04:48 PM UTC-3, Derek Bruening wrote:
On Fri, May 10, 2013 at 7:09 PM, Gabriel Ferreira Teles Gomes <gabriel....@gmail.com> wrote:
1) I am trying to insert a clean call in the middle of the basic block
instrumentation but I get an error (curiously, if I insert the clean
call at the end of the BB, it works).

The attachments clientmiddle.c and clientend.c show the differences.

I don't see a direct clean call: I see a call to dr_insert_mbr_instrumentation(), which requires that its instr_t parameter is an indirect branch (as the documentation says).  It looks like you pass it a label.  Did you run debug build?  It should assert on this incorrect usage of the routine.

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dynamorio-use...@googlegroups.com.
To post to this group, send email to dynamor...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.



--
Interested in Yoga? Be careful of The Yoga Cult or The Scary Yoga Obsession.
More information from  Lorie Anderson and Rick Ross.

Derek Bruening

unread,
Sep 4, 2013, 7:12:03 PM9/4/13
to dynamor...@googlegroups.com
On Wed, Sep 4, 2013 at 2:50 PM, Gabriel Ferreira Teles Gomes <gabriel....@gmail.com> wrote:
Do the emitted lookup routines (shared_bb_ibl_ret,
shared_bb_ibl_indjmp, etc.) search in the same tables as the function
fragment_lookup in file core/fragment.c?

No, indirect branch tables only contain targets of indirect branches.

Gabriel Ferreira Teles Gomes

unread,
Sep 5, 2013, 10:16:17 AM9/5/13
to dynamor...@googlegroups.com
> as I suggested before: dr_insert_mbr_instrumentation();

Ok, but could I add this right before the emission of the jump instruction in the emitted lookup routines? I want to print the host address.

When I try to do it, I get the following error:

<Starting application /local/gabriel/spec/benchspec/CPU2006/429.mcf/run/run_base_test_x32-pc-linux-gnu-4.6.3-basepeak.0001/mcf_base.x32-pc-linux-gnu-4.6.3-basepeak (11509)>
jmp    0x04(%ecx) <Application /local/gabriel/spec/benchspec/CPU2006/429.mcf/run/run_base_test_x32-pc-linux-gnu-4.6.3-basepeak.0001/mcf_base.x32-pc-linux-gnu-4.6.3-basepeak (11509) DynamoRIO usage error : dr_insert_mbr_instrumentation not supported with -opt_speed>
<Usage error: dr_insert_mbr_instrumentation not supported with -opt_speed (/local/gabriel/msc/dynamorio/trunk/core/x86/instrument.c, line 4889)

And I used the following sequence to insert the mbr_instrumentation (maybe the patch file is more useful, so I attached it):

    instr_t *last_instr = instrlist_last(ilist);
    instr_disassemble(dcontext, last_instr, 2);
    dr_insert_mbr_instrumentation(dcontext, ilist, last_instr, (app_pc)emit_check, SPILL_SLOT_1);

Maybe there is another way of printing this host address.



mbr.patch

Gabriel Ferreira Teles Gomes

unread,
Sep 5, 2013, 10:37:14 AM9/5/13
to dynamor...@googlegroups.com
No, indirect branch tables only contain targets of indirect branches.

Is there a function (preferably in C) that looks up in the indirect branch tables?

Derek Bruening

unread,
Sep 5, 2013, 1:46:18 PM9/5/13
to dynamor...@googlegroups.com
See the instrcalls client, which prints the source and target of each call and ret.


Gabriel Ferreira Teles Gomes

unread,
Sep 5, 2013, 3:17:30 PM9/5/13
to dynamor...@googlegroups.com
On Thu, Sep 5, 2013 at 2:46 PM, Derek Bruening <brue...@google.com> wrote:
See the instrcalls client, which prints the source and target of each call and ret.

Isn't it going to print addresses that pertain to the application? (what I refer to as guest addresses. In DynamoRIO, I guess you refer to it as app_pc).
For instance, this is one output from instrcalls:

CALL @  0x0804929d mcf_base.x32-pc-linux-gnu-4.6.3-basepeak!read_min+0x21d ??:0
to  0x08048664 ? ??:0

I believe that both addresses are in the guest application (mcf_..)

I would like to print the host address (cache_pc) of the fragment, i.e. the address of the translated fragment in the code cache. That's why I am trying to insert code inside the lookup routines.

Qin Zhao's suggestion of using dr_insert_mbr_instrumentation would work fine, if I could do it inside the lookup routines. Unfortunately, I get this error, when trying to do so:

DynamoRIO usage error : dr_insert_mbr_instrumentation not supported with -opt_speed

I want to know where the lookup routine is taking me to.

Derek Bruening

unread,
Sep 5, 2013, 5:08:22 PM9/5/13
to dynamor...@googlegroups.com
If you want to see the history of indirect branch transfers with internal info like code cache addresses, why not just run debug build with -no_link_ibl and -loglevel 4.


--
Reply all
Reply to author
Forward
0 new messages