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
|
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 \
|
completion.c shell.c shell_cmds.c shell_sym.c \
|
||||||
history.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