DynamoRIO API
dr_ir_instrlist.h File Reference

Functions to create and manipulate lists of instructions. More...

Functions

instrlist_t * instrlist_create (void *drcontext)
 
void instrlist_init (instrlist_t *ilist)
 
void instrlist_destroy (void *drcontext, instrlist_t *ilist)
 
void instrlist_clear (void *drcontext, instrlist_t *ilist)
 
void instrlist_clear_and_destroy (void *drcontext, instrlist_t *ilist)
 
void instrlist_set_translation_target (instrlist_t *ilist, app_pc pc)
 
app_pc instrlist_get_translation_target (instrlist_t *ilist)
 
void instrlist_set_auto_predicate (instrlist_t *ilist, dr_pred_type_t pred)
 
dr_pred_type_t instrlist_get_auto_predicate (instrlist_t *ilist)
 
instr_tinstrlist_first (instrlist_t *ilist)
 
instr_tinstrlist_first_app (instrlist_t *ilist)
 
instr_tinstrlist_last (instrlist_t *ilist)
 
instr_tinstrlist_last_app (instrlist_t *ilist)
 
void instrlist_append (instrlist_t *ilist, instr_t *instr)
 
void instrlist_prepend (instrlist_t *ilist, instr_t *instr)
 
instrlist_t * instrlist_clone (void *drcontext, instrlist_t *old)
 
void instrlist_preinsert (instrlist_t *ilist, instr_t *where, instr_t *instr)
 
void instrlist_postinsert (instrlist_t *ilist, instr_t *where, instr_t *instr)
 
instr_tinstrlist_replace (instrlist_t *ilist, instr_t *oldinst, instr_t *newinst)
 
void instrlist_remove (instrlist_t *ilist, instr_t *instr)
 
bool instrlist_set_fall_through_target (instrlist_t *bb, app_pc tgt)
 
bool instrlist_set_return_target (instrlist_t *bb, app_pc tgt)
 
byte * instrlist_encode (void *drcontext, instrlist_t *ilist, byte *pc, bool has_instr_jmp_targets)
 
byte * instrlist_encode_to_copy (void *drcontext, instrlist_t *ilist, byte *copy_pc, byte *final_pc, byte *max_pc, bool has_instr_jmp_targets)
 
void instrlist_disassemble (void *drcontext, app_pc tag, instrlist_t *ilist, file_t outfile)
 

Detailed Description

Functions to create and manipulate lists of instructions.

Function Documentation

◆ instrlist_append()

void instrlist_append ( instrlist_t *  ilist,
instr_t instr 
)

Adds instr to the end of ilist.

◆ instrlist_clear()

void instrlist_clear ( void *  drcontext,
instrlist_t *  ilist 
)

Frees the instructions in ilist.

◆ instrlist_clear_and_destroy()

void instrlist_clear_and_destroy ( void *  drcontext,
instrlist_t *  ilist 
)

Destroys the instructions in ilist and destroys the instrlist_t object itself.

◆ instrlist_clone()

instrlist_t* instrlist_clone ( void *  drcontext,
instrlist_t *  old 
)

Allocates a new instrlist_t and for each instr_t in old allocates a new instr_t using instr_clone to produce a complete copy of old. Each operand that is opnd_is_instr() has its target updated to point to the corresponding instr_t in the new instrlist_t (this routine assumes that all such targets are contained within old, and may fault otherwise).

◆ instrlist_create()

instrlist_t* instrlist_create ( void *  drcontext)

Returns an initialized instrlist_t allocated on the thread-local heap.

◆ instrlist_destroy()

void instrlist_destroy ( void *  drcontext,
instrlist_t *  ilist 
)

Deallocates the thread-local heap storage for ilist.

◆ instrlist_disassemble()

void instrlist_disassemble ( void *  drcontext,
app_pc  tag,
instrlist_t *  ilist,
file_t  outfile 
)

Prints each instruction in ilist in sequence to outfile. The default is to use DR's custom syntax (see disassemble_set_syntax()) with additional information. The first column contains the offset in bytes from the start of the list. Next, each instruction is labeled according to its type, which will typically either be L3 for an unchanged application instruction or m4 for a tool instruction (the names come from "Level 3" and "meta Level 4", IR details which are no longer exposed to tools). Tool instructions have their IR heap addresses included (indicated with a leading @ character) to make instruction jump targets easier to identify. The final two columns contain the raw bytes and the actual instruction disassembly.

Below is an example where many tool instructions have been inserted around 3 application instructions, which can be identified by the L3 in the 2nd column. The label instructions are referred to by branch and store instructions, as can be seen by searching for the addresses of the labels.

TAG 0xf77576e6
+0 m4 @0xe7856eb4 64 89 0d 60 00 00 00 mov %ecx -> %fs:0x00000060[4byte]
+7 m4 @0xe78574a8 64 8a 0d 52 00 00 00 mov %fs:0x00000052[1byte] -> %cl
+14 m4 @0xe7855ad4 64 88 0d 54 00 00 00 mov %cl -> %fs:0x00000054[1byte]
+21 L3 83 ee 06 sub $0x00000006 %esi -> %esi
+24 m4 @0xe77c3acc 64 80 3d 52 00 00 00 cmp %fs:0x00000052[1byte] $0x00
00
+32 m4 @0xe7855c54 75 fe jnz @0xe7856054[4byte]
+34 m4 @0xe7856e28 64 c6 05 54 00 00 00 mov $0x00 -> %fs:0x00000054[1byte]
00
+42 m4 @0xe7856754 eb fe jmp @0xe7857350[4byte]
+44 m4 @0xe7856054 <label>
+44 m4 @0xe7857428 b9 e9 76 75 f7 mov $0xf77576e9 -> %ecx
+49 m4 @0xe7855b54 64 c7 05 64 00 00 00 mov @0xe7856514[4byte] ->
%fs:0x00000064[4byte]
98 e6 7b e7
+60 m4 @0xe7857a30 e9 0a 35 07 00 jmp $0xe7831ba7
+65 m4 @0xe7856514 <label>
+65 m4 @0xe7857350 <label>
+65 L3 83 fe 23 cmp %esi $0x00000023
+68 m4 @0xe7856da8 64 8b 0d 60 00 00 00 mov %fs:0x00000060[4byte] -> %ecx
+75 L3 0f 87 16 01 00 00 jnbe $0xf7757808
END 0xf77576e6

◆ instrlist_encode()

byte* instrlist_encode ( void *  drcontext,
instrlist_t *  ilist,
byte *  pc,
bool  has_instr_jmp_targets 
)

Encodes each instruction in ilist in turn in contiguous memory starting at pc. Returns the pc after all of the encodings, or NULL if any one of the encodings failed. Uses the x86/x64 mode stored in each instr, not the mode of the current thread. In order for instr_t operands to be encoded properly, has_instr_jmp_targets must be true. If has_instr_jmp_targets is true, the note field of each instr_t in ilist will be overwritten, and if any instr_t targets are not in ilist, they must have their note fields set with their offsets relative to pc. x86 instructions can occupy up to 17 bytes each, so the caller should ensure the target location has enough room to avoid overflow.

◆ instrlist_encode_to_copy()

byte* instrlist_encode_to_copy ( void *  drcontext,
instrlist_t *  ilist,
byte *  copy_pc,
byte *  final_pc,
byte *  max_pc,
bool  has_instr_jmp_targets 
)

Encodes each instruction in ilist in turn in contiguous memory starting copy_pc in preparation for copying to final_pc. Any pc-relative instruction is encoded as though the instruction list were located at final_pc. This allows for direct copying of the encoded bytes to final_pc without re-relativization.

Returns the pc after all of the encodings, or NULL if any one of the encodings failed.

Uses the x86/x64 mode stored in each instr, not the mode of the current thread.

In order for instr_t operands to be encoded properly, has_instr_jmp_targets must be true. If has_instr_jmp_targets is true, the note field of each instr_t in ilist will be overwritten, and if any instr_t targets are not in ilist, they must have their note fields set with their offsets relative to pc.

If max_pc is non-NULL, computes the total size required to encode the instruction list before performing any encoding. If the whole list will not fit starting at copy_pc without exceeding max_pc, returns NULL without encoding anything. Otherwise encodes as normal. Note that x86 instructions can occupy up to 17 bytes each, so if max_pc is NULL, the caller should ensure the target location has enough room to avoid overflow.

◆ instrlist_first()

instr_t* instrlist_first ( instrlist_t *  ilist)

Returns the first instr_t in ilist.

◆ instrlist_first_app()

instr_t* instrlist_first_app ( instrlist_t *  ilist)

Returns the first application (non-meta) instruction in the instruction list ilist.

Note
All preceding meta instructions will be skipped.
We recommend using this routine during the phase of application code analysis, as any non-app instructions present are guaranteed to be ok to skip. However, caution should be exercised if using this routine after any instrumentation insertion has already happened, as instrumentation might affect register usage or other factors being analyzed.

◆ instrlist_get_auto_predicate()

dr_pred_type_t instrlist_get_auto_predicate ( instrlist_t *  ilist)

Returns the predicate for ilist.

◆ instrlist_get_translation_target()

app_pc instrlist_get_translation_target ( instrlist_t *  ilist)

Returns the translation target, or NULL if none is set.

◆ instrlist_init()

void instrlist_init ( instrlist_t *  ilist)

Initializes ilist.

◆ instrlist_last()

instr_t* instrlist_last ( instrlist_t *  ilist)

Returns the last instr_t in ilist.

◆ instrlist_last_app()

instr_t* instrlist_last_app ( instrlist_t *  ilist)

Returns the last application (non-meta) instruction in the instruction list ilist.

Note
All preceding meta instructions will be skipped.
We recommend using this routine during the phase of application code analysis, as any non-app instructions present are guaranteed to be ok to skip. However, caution should be exercised if using this routine after any instrumentation insertion has already happened, as instrumentation might affect register usage or other factors being analyzed.

◆ instrlist_postinsert()

void instrlist_postinsert ( instrlist_t *  ilist,
instr_t where,
instr_t instr 
)

Inserts instr into ilist after where.

◆ instrlist_preinsert()

void instrlist_preinsert ( instrlist_t *  ilist,
instr_t where,
instr_t instr 
)

Inserts instr into ilist prior to where.

◆ instrlist_prepend()

void instrlist_prepend ( instrlist_t *  ilist,
instr_t instr 
)

Adds instr to the front of ilist.

◆ instrlist_remove()

void instrlist_remove ( instrlist_t *  ilist,
instr_t instr 
)

Removes (does not destroy) instr from ilist.

◆ instrlist_replace()

instr_t* instrlist_replace ( instrlist_t *  ilist,
instr_t oldinst,
instr_t newinst 
)

Replaces oldinst with newinst in ilist (does not destroy oldinst).

◆ instrlist_set_auto_predicate()

void instrlist_set_auto_predicate ( instrlist_t *  ilist,
dr_pred_type_t  pred 
)

All future instructions inserted into ilist will be predicated with pred. This is a convenience routine to make it easy to have emitted code from internal DR components predicated.

Note
only has an effect on ARM
clients may not emit instrumentation that writes to flags, nor may clients insert cti's. Internal DR components such as dr_insert_clean_call() handle auto predication gracefully and are thus safe for use with auto predication.

◆ instrlist_set_fall_through_target()

bool instrlist_set_fall_through_target ( instrlist_t *  bb,
app_pc  tgt 
)

Specifies the fall-through target of a basic block if its last instruction is a conditional branch instruction. It can only be called in basic block building event callbacks when the for_trace parameter is false, and has NO EFFECT in other cases.

◆ instrlist_set_return_target()

bool instrlist_set_return_target ( instrlist_t *  bb,
app_pc  tgt 
)

Specifies the return target of a basic block if its last instruction is a call instruction. It can only be called in basic block building event callbacks when the for_trace parameter is false, and has NO EFFECT in other cases.

◆ instrlist_set_translation_target()

void instrlist_set_translation_target ( instrlist_t *  ilist,
app_pc  pc 
)

All future instructions inserted into ilist that do not have raw bits will have instr_set_translation() called with pc as the target. This is a convenience routine to make it easy to have the same code generate non-translation and translation instructions, and it does not try to enforce that all instructions have translations (e.g., some could be inserted via instr_set_next()).