capstone-engine / capstone

Capstone disassembly/disassembler framework for ARM, ARM64 (ARMv8), Alpha, BPF, Ethereum VM, HPPA, LoongArch, M68K, M680X, Mips, MOS65XX, PPC, RISC-V(rv32G/rv64G), SH, Sparc, SystemZ, TMS320C64X, TriCore, Webassembly, XCore and X86.
http://www.capstone-engine.org
7.18k stars 1.52k forks source link

Add cs_buffer. Breaking API change. #2367

Closed numas13 closed 1 month ago

numas13 commented 1 month ago

Remove cs_malloc() and cs_free().

cs_disasm_iter() is a tiny wrapper around cs_disasm(count=1).

Your checklist for this pull request

Detailed description

API change unifies disassembly process. Before, there were two separate functions to disassemble one instruction at a time in a loop and many instructions into a dynamic buffer. Commit will introduce user allocatable buffer that can be used in both situations with one function.

Updating the use of cs_disasm_iter() is a little more complicated than cs_disasm():

// old api
cs_insn *insn = cs_malloc(handle);
while (cs_disasm_iter(handle, &code, &code_size, &ip, insn)) {
    disassembled_instructions += 1;
}
cs_free(insn);

Must be changed to:

// new api
cs_buffer *buffer = cs_buffer_new(1); // create buffer with 1 element
while (cs_disasm_iter(handle, &code, &code_size, &ip, buffer)) {
    cs_insn *insn = &buffer->insn[0]; // get first insn in a buffer
    disassembled_instructions += 1;
}
cs_buffer_free(buffer); // free buffer

Updating the use of cs_disasm() is straightforward, just use cs_buffer_new(0) to create a buffer and pass it to cs_disasm().

Benchmarks

❯ hyperfine -N ./orig/test_iter_benchmark ./test_iter_benchmark
Benchmark 1: ./orig/test_iter_benchmark
  Time (mean ± σ):     10.632 s ±  0.227 s    [User: 10.622 s, System: 0.004 s]
  Range (min … max):   10.327 s … 11.007 s    10 runs

Benchmark 2: ./test_iter_benchmark
  Time (mean ± σ):     10.815 s ±  0.082 s    [User: 10.812 s, System: 0.001 s]
  Range (min … max):   10.695 s … 10.986 s    10 runs

Summary
  './orig/test_iter_benchmark' ran
    1.02 ± 0.02 times faster than './test_iter_benchmark'
❯ ARGS="10 0x028800 0x1517dd libc.so"; hyperfine -N "./orig/test_file_benchmark $ARGS" "./test_file_benchmark $ARGS"
Benchmark 1: ./orig/test_file_benchmark 10 0x028800 0x1517dd libc.so
  Time (mean ± σ):      2.352 s ±  0.035 s    [User: 2.349 s, System: 0.002 s]
  Range (min … max):    2.299 s …  2.388 s    10 runs

Benchmark 2: ./test_file_benchmark 10 0x028800 0x1517dd libc.so
  Time (mean ± σ):      2.392 s ±  0.053 s    [User: 2.387 s, System: 0.003 s]
  Range (min … max):    2.329 s …  2.497 s    10 runs

Summary
  './orig/test_file_benchmark 10 0x028800 0x1517dd libc.so' ran
    1.02 ± 0.03 times faster than './test_file_benchmark 10 0x028800 0x1517dd libc.so'

Test plan

Update bindings and user software.

Closing issues

...

numas13 commented 1 month ago

Please rebase this on onto the ASAN PR from me or wait until it is merged: #2313 Just so we get extra test coverage.

There is one problem in test_arm_regression. Is it expected?

numas13 commented 1 month ago

I've updated python bindings and review is appreciated.

aquynh commented 1 month ago

please avoid breaking API

numas13 commented 1 month ago

I'm closing PRs. We'll think about what can be done.