Skip to content

Commit

Permalink
unicorn_tracer: do not use instruction count limit in setup code
Browse files Browse the repository at this point in the history
If uc_emu_start is called with no instruction count limit after being called with an instruction count limit, this will force a flush of the translation buffer. Flushing the translation buffer can be quite expensive, particularly with newer version of Unicorn.

PiperOrigin-RevId: 561784368
  • Loading branch information
ncbray authored and copybara-github committed Aug 31, 2023
1 parent a4ce6a9 commit f300598
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 6 deletions.
10 changes: 7 additions & 3 deletions tracing/unicorn_tracer_aarch64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,15 @@ void SetupCPUState(uc_engine *uc) {

// The entry sequence needs to ERET to somewhere mapped, choose just after the
// entry sequence.
uint64_t exit_address = kEntrySequenceAddress + sizeof(kEntrySequence);
const uint64_t exit_address = kEntrySequenceAddress + sizeof(kEntrySequence);
UNICORN_CHECK(uc_reg_write(uc, UC_ARM64_REG_X30, &exit_address));

// Execute the entry seqeunce
UNICORN_CHECK(uc_emu_start(uc, kEntrySequenceAddress, exit_address, 0, 100));
// Execute the entry sequence.
// For performance reasons, all calls to uc_emu_start should either limit the
// number of instructions executed or not limit the number of instructions
// executed. Switching between these modes will flush the code translation
// buffer in Unicorn v2.
UNICORN_CHECK(uc_emu_start(uc, kEntrySequenceAddress, exit_address, 0, 0));

// Unmap the entry sequence
UNICORN_CHECK(uc_mem_unmap(uc, kEntrySequenceAddress, 0x1000));
Expand Down
11 changes: 8 additions & 3 deletions tracing/unicorn_tracer_x86_64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,15 @@ void UnicornTracer<X86_64>::SetInitialRegisters(
UNICORN_CHECK(uc_mem_write(uc_, addr, &fpregs, kFPRegsSize));
// fxrstor64 [rdi]
const std::string fxRstorRdiByteCode = {0x48, 0x0F, 0xAE, 0x0F};
UNICORN_CHECK(uc_mem_write(uc_, addr + kFPRegsSize, fxRstorRdiByteCode.data(),
const uint64_t code_begin = addr + kFPRegsSize;
const uint64_t code_end = code_begin + fxRstorRdiByteCode.length();
UNICORN_CHECK(uc_mem_write(uc_, code_begin, fxRstorRdiByteCode.data(),
fxRstorRdiByteCode.length()));
// Execute exactly one instruction (count=1).
UNICORN_CHECK(uc_emu_start(uc_, addr + kFPRegsSize, 0, 0, /* count = */ 1));
// For performance reasons, all calls to uc_emu_start should either limit the
// number of instructions executed or not limit the number of instructions
// executed. Switching between these modes will flush the code translation
// buffer in Unicorn v2.
UNICORN_CHECK(uc_emu_start(uc_, code_begin, code_end, 0, 0));
UNICORN_CHECK(uc_mem_unmap(uc_, addr, kPageSize));

// This will redundantly set some of the floating point registers, but that
Expand Down

0 comments on commit f300598

Please sign in to comment.