/* Copyright Yann Weber This file is part of asmsh. asmsh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. asmsh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with asmsh. If not, see . */ #include "breakpoints.h" /** Efficient search of a breakpoint address * * @param brks pointer on the breakpoint list * @param addr the address to search * @param idx a pointer on the breakpoint index * @return -1 if not found else 0 * * @note idx is set to a value suitable for insertion if value is not found */ static int asmsh_brk_index(asmsh_brk_t *brks, unsigned long addr, size_t *idx); int asmsh_brk_init(asmsh_brk_t *brks) { brks->addrs = NULL; brks->sz = 0; return 0; } void asmsh_brk_free(asmsh_brk_t *brks) { free(brks->addrs); } int asmsh_brk_add(asmsh_brk_t *brks, unsigned long addr) { size_t idx; int ret; void *tmp; ret = asmsh_brk_index(brks, addr, &idx); if(ret == 0) { return 1; } if(brks->sz > 0) { tmp = realloc(brks->addrs, sizeof(*brks->addrs)*(brks->sz + 1)); if(tmp == NULL) { int err = errno; asmsh_log_perror("Unable to reallocate breakpoint list"); errno = err; return -1; } brks->addrs=tmp; } else { if(!(brks->addrs = malloc(sizeof(*brks->addrs)))) { int err = errno; asmsh_log_perror("Unable to allocate breakpoint list"); errno = err; return -1; } } if(idx == brks->sz) { brks->addrs[brks->sz] = addr; } else { memmove(&(brks->addrs[idx+1]),&(brks->addrs[idx]), (brks->sz - idx)*sizeof(*brks->addrs)); brks->addrs[idx] = addr; } brks->sz++; return 0; } int asmsh_brk_del(asmsh_brk_t *brks, unsigned long addr) { size_t idx; int ret; void *tmp; ret = asmsh_brk_index(brks, addr, &idx); if(ret < 0) { return 1; } brks->sz--; if(idx < brks->sz) { memmove(&(brks->addrs[idx]), &(brks->addrs[idx+1]), sizeof(*brks->addrs)*brks->sz); } if(brks->sz) { tmp = realloc(brks->addrs, brks->sz); if(tmp == NULL) { int err = errno; asmsh_log_perror("Unable to reallocate breakpoint list when removing"); errno = err; return -1; } brks->addrs=tmp; } else { free(brks->addrs); brks->addrs = NULL; } return 0; } int asmsh_brk_isset(asmsh_brk_t *brks, unsigned long addr) { size_t idx; return asmsh_brk_index(brks, addr, &idx) == 0; } static int asmsh_brk_index(asmsh_brk_t *brks, unsigned long addr, size_t *idx) { size_t beg, end, mid; if(brks->sz == 0) { *idx = 0; return -1; } beg = 0; end = brks->sz; while(end >= beg) { mid = (beg + end) / 2; if(brks->addrs[mid] == addr) { *idx = mid; return 0; } else if(brks->addrs[mid] > addr) { if(mid == 0) { break; } end = mid - 1; } else { beg = mid + 1; if(beg >= brks->sz) { break; } } } *idx = beg; return -1; }