Skip to content

Commit

Permalink
set buffer size for instruction cache in cs_disasm() to @count if @count
Browse files Browse the repository at this point in the history
 > 0. this avoids realloc() in cases where @count is pre-determined. thanks Dang Hoang Vu for the idea
  • Loading branch information
aquynh committed Sep 30, 2014
1 parent 39eb84a commit ac98ca0
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si
uint64_t offset_org;
size_t size_org;
const uint8_t *buffer_org;
unsigned int cache_size = INSN_CACHE_SIZE;

if (!handle) {
// FIXME: how to handle this case:
Expand All @@ -435,11 +436,14 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si

handle->errnum = CS_ERR_OK;

if (count > 0)
cache_size = count;

// save the original offset for SKIPDATA
buffer_org = buffer;
offset_org = offset;
size_org = size;
total_size = (sizeof(cs_insn) * INSN_CACHE_SIZE);
total_size = (sizeof(cs_insn) * cache_size);
total = cs_mem_malloc(total_size);
insn_cache = total;

Expand Down Expand Up @@ -475,10 +479,15 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si
handle->printer(&mci, &ss, handle->printer_info);
fill_insn(handle, insn_cache, ss.buffer, &mci, handle->post_printer, buffer);

c++;
if (count > 0 && c == count)
// disasm requested number of instructions
break;

f++;
if (f == INSN_CACHE_SIZE) {
if (f == cache_size) {
// resize total to contain newly disasm insns
total_size += (sizeof(cs_insn) * INSN_CACHE_SIZE);
total_size += (sizeof(cs_insn) * cache_size);
tmp = cs_mem_realloc(total, total_size);
if (tmp == NULL) { // insufficient memory
if (handle->detail) {
Expand All @@ -494,17 +503,13 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si
}

total = tmp;
insn_cache = (cs_insn *)((char *)total + total_size - (sizeof(cs_insn) * INSN_CACHE_SIZE));
insn_cache = (cs_insn *)((char *)total + total_size - (sizeof(cs_insn) * cache_size));

// reset f back to 0
f = 0;
} else
insn_cache++;

c++;
if (count > 0 && c == count)
break;

buffer += insn_size;
size -= insn_size;
offset += insn_size;
Expand Down Expand Up @@ -544,10 +549,10 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si
insn_cache->detail = NULL;

f++;
if (f == INSN_CACHE_SIZE) {
if (f == cache_size) {
// resize total to contain newly disasm insns

total_size += (sizeof(cs_insn) * INSN_CACHE_SIZE);
total_size += (sizeof(cs_insn) * cache_size);
tmp = cs_mem_realloc(total, total_size);
if (tmp == NULL) { // insufficient memory
if (handle->detail) {
Expand All @@ -563,7 +568,7 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si
}

total = tmp;
insn_cache = (cs_insn *)((char *)total + total_size - (sizeof(cs_insn) * INSN_CACHE_SIZE));
insn_cache = (cs_insn *)((char *)total + total_size - (sizeof(cs_insn) * cache_size));

// reset f back to 0
f = 0;
Expand All @@ -579,7 +584,7 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si

if (f) {
// resize total to contain newly disasm insns
void *tmp = cs_mem_realloc(total, total_size - (INSN_CACHE_SIZE - f) * sizeof(*insn_cache));
void *tmp = cs_mem_realloc(total, total_size - (cache_size - f) * sizeof(*insn_cache));
if (tmp == NULL) { // insufficient memory
// free all detail pointers
if (handle->detail) {
Expand Down

0 comments on commit ac98ca0

Please sign in to comment.