Implements a small breakpoint lib
Allows to store & efficient lookup
This commit is contained in:
parent
77beccae4f
commit
e3d0baa414
4 changed files with 354 additions and 1 deletions
|
|
@ -1,6 +1,6 @@
|
|||
bin_PROGRAMS = asmsh child
|
||||
|
||||
libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c compile.c logger.c \
|
||||
libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c breakpoints.c compile.c logger.c \
|
||||
completion.c shell.c shell_cmds.c shell_sym.c \
|
||||
history.c
|
||||
|
||||
|
|
|
|||
175
breakpoints.c
Normal file
175
breakpoints.c
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/* Copyright Yann Weber <asmsh@yannweb.net>
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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;
|
||||
|
||||
}
|
||||
|
||||
70
breakpoints.h
Normal file
70
breakpoints.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* Copyright Yann Weber <asmsh@yannweb.net>
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef ASMSH_BREAKPOINTS_H
|
||||
#define ASMSH_BREAKPOINTS_H
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
typedef struct asmsh_brk_s asmsh_brk_t;
|
||||
|
||||
|
||||
/** Stores breakpoints informations */
|
||||
struct asmsh_brk_s
|
||||
{
|
||||
/** Breakpoint addresses sorted ascending */
|
||||
unsigned long *addrs;
|
||||
/** Number of breakpoints */
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
/** Initialize the breakpoint list
|
||||
* @param brks Pointer on the list to initialize
|
||||
* @return 0 if no error else -1
|
||||
*/
|
||||
int asmsh_brk_init(asmsh_brk_t *brks);
|
||||
|
||||
/** Cleanup a breakpoint list struct
|
||||
* @param brks Pointer on the list to clean
|
||||
*/
|
||||
void asmsh_brk_free(asmsh_brk_t *brks);
|
||||
|
||||
/** Add a breakpoint
|
||||
* @param brks Pointer on the list
|
||||
* @param addr The breakpoint's address
|
||||
* @return 0 if no error 1 if allready present else -1 and set errno
|
||||
*/
|
||||
int asmsh_brk_add(asmsh_brk_t *brks, unsigned long addr);
|
||||
|
||||
/** Del a breakpoint
|
||||
* @param brks Pointer on the list
|
||||
* @param addr The breakpoint's address
|
||||
* @return 0 if no error 1 if not present else -1 and set errno
|
||||
*/
|
||||
int asmsh_brk_del(asmsh_brk_t *brks, unsigned long addr);
|
||||
|
||||
/** Check if a breakpoint exists
|
||||
* @param brks Pointer on the list
|
||||
* @param addr The address to check
|
||||
* @return 0 if no breakpoint at given address
|
||||
*/
|
||||
int asmsh_brk_isset(asmsh_brk_t *brks, unsigned long addr);
|
||||
|
||||
#endif
|
||||
|
||||
108
tests/tests_breakpoints.c
Normal file
108
tests/tests_breakpoints.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <check.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asmsh_check.h"
|
||||
#include "breakpoints.h"
|
||||
|
||||
START_TEST(brk_add)
|
||||
{
|
||||
asmsh_brk_t brks;
|
||||
asmsh_brk_init(&brks);
|
||||
ck_assert_int_eq(brks.sz, 0);
|
||||
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, 0x42), 0);
|
||||
ck_assert_int_eq(brks.sz, 1);
|
||||
ck_assert_int_eq(brks.addrs[0], 0x42);
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, 0x42), 1);
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, 0x1312), 0);
|
||||
ck_assert_int_eq(brks.sz, 2);
|
||||
ck_assert_int_eq(brks.addrs[0], 0x42);
|
||||
ck_assert_int_eq(brks.addrs[1], 0x1312);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(brk_add_order)
|
||||
{
|
||||
asmsh_brk_t brks;
|
||||
asmsh_brk_init(&brks);
|
||||
|
||||
for(int s=0;s<2;s++)
|
||||
{
|
||||
for(int i=s;i<10; i+=2)
|
||||
{
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, i), 0);
|
||||
}
|
||||
}
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
ck_assert_int_eq(brks.addrs[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(brk_isset)
|
||||
{
|
||||
asmsh_brk_t brks;
|
||||
asmsh_brk_init(&brks);
|
||||
ck_assert_int_eq(brks.sz, 0);
|
||||
|
||||
ck_assert_int_eq(asmsh_brk_isset(&brks, 0x42), 0);
|
||||
ck_assert_int_eq(asmsh_brk_isset(&brks, 0x1312), 0);
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, 0x42), 0);
|
||||
ck_assert_int_ne(asmsh_brk_isset(&brks, 0x42), 0);
|
||||
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, 0x1312), 0);
|
||||
dprintf(2,"test isset\n");
|
||||
ck_assert_int_ne(asmsh_brk_isset(&brks, 0x1312), 0);
|
||||
dprintf(2,"test isset2\n");
|
||||
ck_assert_int_ne(asmsh_brk_isset(&brks, 0x42), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(brk_del)
|
||||
{
|
||||
asmsh_brk_t brks;
|
||||
asmsh_brk_init(&brks);
|
||||
ck_assert_int_eq(brks.sz, 0);
|
||||
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, 0x42), 0);
|
||||
ck_assert_int_eq(asmsh_brk_add(&brks, 0x1312), 0);
|
||||
ck_assert_int_ne(asmsh_brk_isset(&brks, 0x42), 0);
|
||||
ck_assert_int_ne(asmsh_brk_isset(&brks, 0x1312), 0);
|
||||
|
||||
ck_assert_int_eq(asmsh_brk_del(&brks, 0x42), 0);
|
||||
ck_assert_int_eq(asmsh_brk_isset(&brks, 0x42), 0);
|
||||
ck_assert_int_ne(asmsh_brk_isset(&brks, 0x1312), 0);
|
||||
|
||||
ck_assert_int_eq(asmsh_brk_del(&brks, 0x42), 1);
|
||||
ck_assert_int_eq(asmsh_brk_isset(&brks, 0x42), 0);
|
||||
ck_assert_int_ne(asmsh_brk_isset(&brks, 0x1312), 0);
|
||||
|
||||
ck_assert_int_eq(asmsh_brk_del(&brks, 0x1312), 0);
|
||||
ck_assert_int_eq(asmsh_brk_isset(&brks, 0x42), 0);
|
||||
ck_assert_int_eq(asmsh_brk_isset(&brks, 0x1312), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
|
||||
/*
|
||||
START_TEST(brk_)
|
||||
{
|
||||
asmsh_brk_t brks;
|
||||
asmsh_brk_init(&brks);
|
||||
}
|
||||
END_TEST
|
||||
*/
|
||||
|
||||
ASMSH_CHECK_START("Testing breakpoints lib", "Testing breakpoints manipulation")
|
||||
ASMSH_ADD_TEST(brk_add);
|
||||
ASMSH_ADD_TEST(brk_add_order);
|
||||
ASMSH_ADD_TEST(brk_isset);
|
||||
ASMSH_ADD_TEST(brk_del);
|
||||
ASMSH_CHECK_END
|
||||
Loading…
Add table
Add a link
Reference in a new issue