instr_get_app_pc returns wrong pc

44 views
Skip to first unread message

Burak ŞAHİN

unread,
Nov 24, 2021, 2:43:36 PM11/24/21
to DynamoRIO Users
instr_get_app_pc sometimes return 0x0 or sometimes return even something totally different. I did some debugging but either in clean call or in registered even app instruction, some app pc values are wrong. 

The trace below is a sequence of BB trace without any call between them. Most of BB addresses are correct, but I found are some BB addresses either 0x0 or 0x66xxxxxxx in my logs for many binaries. Why would instr_get_app_pc would return incorrect pc values for some instructions?


BB | 0x402313
CBR:0x402313 | TAKEN:0x402318 | NOTTAKEN:0x402326
BB | 0x662dca61 (This should be 402318)
CBR:0x402318 | TAKEN:0x40231d | NOTTAKEN:0x402326
BB | 0x0 (This should be 40231d)
CBR:0x40231d | TAKEN:0x4028e2 | NOTTAKEN:0x402326
BB | 0x4028e2
BB | 0x662dca61 (This should be 0x4022dc)
CBR:0x4022dc | TAKEN:0x4022f0 | NOTTAKEN:0x4022e8

sharma...@google.com

unread,
Nov 24, 2021, 3:50:20 PM11/24/21
to DynamoRIO Users
Hi,
For non-app instructions (e.g. the ones that are added by a client),  the `translation` field in instr_t is by default not set. This would cause instr_get_app_pc to return zero. If needed, you can set it using instr_set_translation; see https://github.com/DynamoRIO/dynamorio/blob/5c817aebdfc0b8ca3316dcd325f4e0b95101ebbf/core/ir/instr_api.h#L926.

Note that instr_get_app_pc returns the app pc for a given instr_t. To find these "BB addresses", which instr_t did you use? Is it an app instr (what does instr_is_app say)? For the cases where you get the wrong address, can you share the BB and the instr? You can print these using instrlist_disassemble and instr_disassemble.

Abhinav



Burak ŞAHİN

unread,
Nov 25, 2021, 12:11:45 AM11/25/21
to DynamoRIO Users
I am using the *instr passed to the drmgr_register_bb_instrumentation_event(NULL, event_app_instruction, NULL);
I am passing the instr to a clean call for each first instr in bb. 

The same basic blocks are recorded correctly in a thread log, but the same blocks again can have weird addresses in another thread log.
I checked the instr_is_app and you can see a new trace below. 1 means it is instr is app. The confusing part here is I got same instructions correct in some places, and incorrect in other threads. Also, as you can see, I log the last instruction if it is CBR and in CBR logs the takens are correct. This happens in both version 7 and version 8. And also, if I run the same binary multiple (enough) times, sometimes I got all addresses correct. 

4K BB log is correct then a sequence
.......
BB | 0x40224e | 1
CBR | 0x40224e | TAKEN:0x402255 | NOTTAKEN:0x402257
BB | 0x15 | 1  (This should be 0x402255)
BB | 0x0   | 1  (This should be 0x402265)
CBR:0x402265 | TAKEN:0x402275 | NOTTAKEN:0x40226e
BB | 0x2a | 1 (This should be 0x402275)



24 Kasım 2021 Çarşamba tarihinde saat 15:50:20 UTC-5 itibarıyla sharma...@google.com şunları yazdı:

sharma...@google.com

unread,
Nov 25, 2021, 12:43:45 PM11/25/21
to DynamoRIO Users
> I am using the *instr passed to the drmgr_register_bb_instrumentation_event(NULL, event_app_instruction, NULL);
> I am passing the instr to a clean call for each first instr in bb. 

Oh, I see. I don't think instr_get_app_pc will work as expected with this instr_t*, because the instr_t object will have been de-allocated by the time the fragment starts executing. The instrlist_t and instr_t objects you see in event_app_instruction are valid only at instrumentation time. After all clients are done adding their instrumentation and the basic block fragment is ready, DR encodes the instructions to raw bytes (this is what is stored and executed) and de-allocates the instrlist_t and all instr_t in it.

If your clean call needs to examine the actual app pc of the instruction, then you'll need to get it at instrumentation time (in event_app_instruction) and pass it as an argument to the clean call. Some part of instr_t can be recreated in the clean call using the pc using `decode` (https://github.com/DynamoRIO/dynamorio/blob/bfc4b8280ca70631eb5eaab715bc1c03a8d3ab79/core/ir/decode_api.h#L77). But note that this recreates only what is documented in the previous link.

Hope this helps.

Abhinav

Burak ŞAHİN

unread,
Nov 25, 2021, 3:28:11 PM11/25/21
to DynamoRIO Users
I am already using a clean call and passing instr to a clean call. 

dr_insert_clean_call(drcontext, bb, instr, clean_call_bb, false, 1, OPND_CREATE_INTPTR(instr_clone(drcontext, instr)));

To avoid de-allocation, I am cloning instr into a new instr_t and using it inside the clean call.
I understand you suggest I should also suggest to pass app pc along with instr.  I will try to pass a second argument (app pc) and try to decode. However, since I am cloning the instr, why am I still getting this issue?

25 Kasım 2021 Perşembe tarihinde saat 12:43:45 UTC-5 itibarıyla sharma...@google.com şunları yazdı:

sharma...@google.com

unread,
Nov 25, 2021, 11:02:56 PM11/25/21
to DynamoRIO Users
Hi,
Some replies inline.

> To avoid de-allocation, I am cloning instr into a new instr_t and using it inside the clean call.

So, you clone the instr_t in event_app_instruction. When do you free it? If you free the cloned instr_t in the clean call, it may cause issues if the same fragment is executed again. Note that event_app_instruction will probably not be invoked every time the basic block is executed, as the instrumented block is cached in the code cache.

>  I will try to pass a second argument (app pc) and try to decode

If the decoded instr_t has all the information you need in your clean call, then this should help you avoid having to clone it.

> However, since I am cloning the instr, why am I still getting this issue?

I'm not sure yet. Can you check what instr_get_app_pc returns when it is used in event_app_instruction, for the original instr_t* and the cloned instr_t*?

Abhinav
Reply all
Reply to author
Forward
0 new messages