Compare commits

..

No commits in common. "504d270947a333177d8fa2bad68df35a4736855a" and "ebece52aec3a6226efc6b4395aa8638ad62f955c" have entirely different histories.

17 changed files with 57 additions and 389 deletions

2
nemu/.gitignore vendored
View file

@ -7,8 +7,6 @@ build/
.config .config
.config.old .config.old
.envrc .envrc
.metals/
.vscode/
compile_commands.json compile_commands.json
### C ### ### C ###

View file

@ -48,7 +48,6 @@ CFLAGS_BUILD += $(if $(CONFIG_CC_ASAN),-fsanitize=address,)
CFLAGS_TRACE += -DITRACE_COND=$(if $(CONFIG_ITRACE_COND),$(call remove_quote,$(CONFIG_ITRACE_COND)),true) CFLAGS_TRACE += -DITRACE_COND=$(if $(CONFIG_ITRACE_COND),$(call remove_quote,$(CONFIG_ITRACE_COND)),true)
CFLAGS += $(CFLAGS_BUILD) $(CFLAGS_TRACE) -D__GUEST_ISA__=$(GUEST_ISA) CFLAGS += $(CFLAGS_BUILD) $(CFLAGS_TRACE) -D__GUEST_ISA__=$(GUEST_ISA)
LDFLAGS += $(CFLAGS_BUILD) LDFLAGS += $(CFLAGS_BUILD)
INC_PATH += $(NEMU_HOME)/src/isa/$(GUEST_ISA)/local-include
# Include rules for menuconfig # Include rules for menuconfig
include $(NEMU_HOME)/scripts/config.mk include $(NEMU_HOME)/scripts/config.mk
@ -61,6 +60,8 @@ else
include $(NEMU_HOME)/scripts/native.mk include $(NEMU_HOME)/scripts/native.mk
endif endif
.PHONY: test
include $(NEMU_HOME)/tests/Makefile include $(NEMU_HOME)/tests/Makefile
all-tests: TEST_OBJS = $(filter-out $(OBJ_DIR)/src/nemu-main.o, $(OBJS)) all-tests: TEST_OBJS = $(filter-out $(OBJ_DIR)/src/nemu-main.o, $(OBJS))
all-tests: CFLAGS += $(shell pkg-config --cflags check) all-tests: CFLAGS += $(shell pkg-config --cflags check)
@ -69,5 +70,3 @@ all-tests: $(TEST_SRCS:%.c=$(OBJ_DIR)/%)
test: all-tests test: all-tests
@$(OBJ_DIR)/tests/expr_test @$(OBJ_DIR)/tests/expr_test
.PHONY: test

View file

@ -1,74 +0,0 @@
#
# Automatically generated file; DO NOT EDIT.
# NEMU Configuration Menu
#
# CONFIG_ISA_x86 is not set
# CONFIG_ISA_mips32 is not set
CONFIG_ISA_riscv=y
# CONFIG_ISA_loongarch32r is not set
CONFIG_ISA="riscv32"
#
# ISA-dependent Options for riscv
#
# CONFIG_RV64 is not set
# CONFIG_RVE is not set
# end of ISA-dependent Options for riscv
CONFIG_ENGINE_INTERPRETER=y
CONFIG_ENGINE="interpreter"
CONFIG_MODE_SYSTEM=y
CONFIG_TARGET_NATIVE_ELF=y
# CONFIG_TARGET_SHARE is not set
# CONFIG_TARGET_AM is not set
#
# Build Options
#
CONFIG_CC_GCC=y
# CONFIG_CC_GPP is not set
# CONFIG_CC_CLANG is not set
CONFIG_CC="gcc"
# CONFIG_CC_O0 is not set
# CONFIG_CC_O1 is not set
CONFIG_CC_O2=y
# CONFIG_CC_O3 is not set
CONFIG_CC_OPT="-O2"
# CONFIG_CC_LTO is not set
# CONFIG_CC_DEBUG is not set
CONFIG_CC_ASAN=y
# end of Build Options
#
# Testing and Debugging
#
CONFIG_TRACE=y
CONFIG_TRACE_START=0
CONFIG_TRACE_END=10000
CONFIG_ITRACE=y
CONFIG_ITRACE_COND="true"
# CONFIG_DIFFTEST is not set
CONFIG_DIFFTEST_REF_PATH="none"
CONFIG_DIFFTEST_REF_NAME="none"
# end of Testing and Debugging
#
# Memory Configuration
#
CONFIG_MBASE=0x80000000
CONFIG_MSIZE=0x8000000
CONFIG_PC_RESET_OFFSET=0
# CONFIG_PMEM_MALLOC is not set
CONFIG_PMEM_GARRAY=y
CONFIG_MEM_RANDOM=y
# end of Memory Configuration
# CONFIG_DEVICE is not set
#
# Miscellaneous
#
CONFIG_TIMER_GETTIMEOFDAY=y
# CONFIG_TIMER_CLOCK_GETTIME is not set
CONFIG_RT_CHECK=y
# end of Miscellaneous

View file

@ -50,21 +50,6 @@
libllvm libllvm
]; ];
configurePhase = ''
echo NEMU_HOME=$NEMU_HOME
echo pwd=$(pwd)
mkdir -p $(pwd)/kconfig
WORK_DIR=$(pwd) obj=$(pwd)/kconfig make --trace -e -f scripts/config.mk WORK_DIR=$(pwd) obj=$(pwd)/kconfig rv32_defconfig
'';
installPhase = ''
BUILD_DIR=$out make install
'';
checkPhase = ''
BUILD_DIR=$out make test
'';
NEMU_HOME = src; NEMU_HOME = src;
meta = with lib; { meta = with lib; {

View file

@ -21,15 +21,7 @@
#include <utils.h> #include <utils.h>
#define Log(format, ...) \ #define Log(format, ...) \
_Log(ANSI_FMT("[INFO] %s:%d %s() ", ANSI_FG_BLUE) format "\n", \ _Log(ANSI_FMT("[%s:%d %s] " format, ANSI_FG_BLUE) "\n", \
__FILE__, __LINE__, __func__, ## __VA_ARGS__)
#define Warning(format, ...) \
_Log(ANSI_FMT("[WARNING] %s:%d %s() ", ANSI_FG_YELLOW) format "\n", \
__FILE__, __LINE__, __func__, ## __VA_ARGS__)
#define Error(format, ...) \
_Log(ANSI_FMT("[ERROR] %s:%d %s() ", ANSI_FG_RED) format "\n", \
__FILE__, __LINE__, __func__, ## __VA_ARGS__) __FILE__, __LINE__, __func__, ## __VA_ARGS__)
#define Assert(cond, format, ...) \ #define Assert(cond, format, ...) \

View file

@ -10,7 +10,7 @@ endif
WORK_DIR = $(shell pwd) WORK_DIR = $(shell pwd)
BUILD_DIR = $(WORK_DIR)/build BUILD_DIR = $(WORK_DIR)/build
INC_PATH := $(WORK_DIR)/include $(BUILD_DIR)/include $(INC_PATH) INC_PATH := $(WORK_DIR)/include $(INC_PATH)
OBJ_DIR = $(BUILD_DIR)/obj-$(NAME)$(SO) OBJ_DIR = $(BUILD_DIR)/obj-$(NAME)$(SO)
BINARY = $(BUILD_DIR)/$(NAME)$(SO) BINARY = $(BUILD_DIR)/$(NAME)$(SO)
@ -42,13 +42,13 @@ $(OBJ_DIR)/%.o: %.cc
$(OBJ_DIR)/%.tag.c: %.y $(OBJ_DIR)/%.tag.c: %.y
@echo + YACC $< @echo + YACC $<
@mkdir -p $(dir $@) $(BUILD_DIR)/include @mkdir -p $(dir $@)
@$(YACC) $(YFLAGS) --header=$(BUILD_DIR)/include/$(notdir $(<:.y=.h)) -o $@ $< @$(YACC) $(YFLAGS) --header=$(<:.y=.h) -o $@ $<
$(OBJ_DIR)/%.yy.c: %.l $(OBJ_DIR)/%.tag.c $(OBJ_DIR)/%.yy.c: %.l $(OBJ_DIR)/%.tag.c
@echo + LEX $< @echo + LEX $<
@mkdir -p $(dir $@) $(BUILD_DIR)/include @mkdir -p $(dir $@)
@$(LEX) $(LFLAGS) --header=$(BUILD_DIR)/include/$(notdir $(<:.l=_lex.h)) -o $@ $< @$(LEX) $(LFLAGS) --header=$(<:.l=_lex.h) -o $@ $<
$(OBJ_DIR)/%.tag.o: $(OBJ_DIR)/%.tag.c $(OBJ_DIR)/%.tag.o: $(OBJ_DIR)/%.tag.c
@echo + CC $< @echo + CC $<
@ -67,7 +67,7 @@ $(OBJ_DIR)/%.yy.o: $(OBJ_DIR)/%.yy.c
# Some convenient rules # Some convenient rules
.PHONY: app install clean .PHONY: app clean
app: $(BINARY) app: $(BINARY)
@ -75,9 +75,5 @@ $(BINARY):: $(OBJS) $(ARCHIVES)
@echo + LD $@ @echo + LD $@
@$(LD) -o $@ $(OBJS) $(LDFLAGS) $(ARCHIVES) $(LIBS) @$(LD) -o $@ $(OBJS) $(LDFLAGS) $(ARCHIVES) $(LIBS)
install: $(BINARY)
@mkdir -p $(PREFIX)/bin
@cp $(BINARY) $(PREFIX)/bin/
clean: clean:
-rm -rf $(BUILD_DIR) -rm -rf $(BUILD_DIR)

View file

@ -31,7 +31,6 @@ static uint64_t g_timer = 0; // unit: us
static bool g_print_step = false; static bool g_print_step = false;
void device_update(); void device_update();
bool wp_eval_all();
static void trace_and_difftest(Decode *_this, vaddr_t dnpc) { static void trace_and_difftest(Decode *_this, vaddr_t dnpc) {
#ifdef CONFIG_ITRACE_COND #ifdef CONFIG_ITRACE_COND
@ -78,10 +77,6 @@ static void execute(uint64_t n) {
exec_once(&s, cpu.pc); exec_once(&s, cpu.pc);
g_nr_guest_inst ++; g_nr_guest_inst ++;
trace_and_difftest(&s, cpu.pc); trace_and_difftest(&s, cpu.pc);
if (wp_eval_all()) {
puts(s.logbuf);
break;
}
if (nemu_state.state != NEMU_RUNNING) break; if (nemu_state.state != NEMU_RUNNING) break;
IFDEF(CONFIG_DEVICE, device_update()); IFDEF(CONFIG_DEVICE, device_update());
} }

View file

@ -36,16 +36,5 @@ void isa_reg_display() {
} }
word_t isa_reg_str2val(const char *s, bool *success) { word_t isa_reg_str2val(const char *s, bool *success) {
assert(s);
int i;
for (i = 0; i < 32 && strcmp(s, regs[i]) != 0; i++)
;
if (i == 32) {
*success = false;
return 0; return 0;
} }
*success = true;
return gpr(i);
}

2
nemu/src/monitor/sdb/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
addrexp_lex.h
addrexp.h

View file

@ -1,8 +1,5 @@
%{ %{
#include <isa.h>
#include <addrexp.h> #include <addrexp.h>
static bool success = false;
void yyerror(word_t *result, const char *err);
%} %}
%option noyywrap %option noyywrap
@ -10,15 +7,7 @@
0[xX][0-9a-fA-F]+ { yylval = strtoul(yytext, NULL, 16); return HEX_NUMBER; } 0[xX][0-9a-fA-F]+ { yylval = strtoul(yytext, NULL, 16); return HEX_NUMBER; }
[0-9]+ { yylval = strtoul(yytext, NULL, 10); return NUMBER; } [0-9]+ { yylval = strtoul(yytext, NULL, 10); return NUMBER; }
$[asgprt$][0-9pa][0-9]? { [+\-*/()] { return *yytext; }
yylval = isa_reg_str2val(yytext + 1, &success);
if(!success) {
yyerror(NULL, "Failed to convert reg to value");
return YYerror;
}
return REGISTER;
}
[+\-*/<=()] { return *yytext; }
[ \t] { } [ \t] { }
. { printf("Unexpected character: %s\n", yytext); return YYerror; } . { printf("Unexpected character: %s\n", yytext); }
%% %%

View file

@ -1,25 +1,16 @@
%code requires {
#include <common.h>
#include <memory/vaddr.h>
#include <stdio.h>
#include <stdlib.h>
extern int yylex(void);
}
%{ %{
#include <common.h>
#include <isa.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
void yyerror(word_t *result, const char *err) { #include <stdint.h>
Error("%s", err); extern int yylex(void);
void yyerror(uint32_t *result, const char *err) {
fprintf(stderr, "Error: %s\n", err);
} }
%} %}
%token NUMBER HEX_NUMBER %token NUMBER HEX_NUMBER
%token REGISTER
%locations
%start input %start input
%define api.value.type { word_t } %define api.value.type { uint32_t }
%parse-param { uint32_t *result } %parse-param { uint32_t *result }
%left '-' '+' %left '-' '+'
%left '*' '/' %left '*' '/'
@ -31,12 +22,6 @@ input
expression expression
: number { $$ = $1; } : number { $$ = $1; }
| expression '>' '=' expression { $$ = ($1 >= $4); }
| expression '<' '=' expression { $$ = ($1 <= $4); }
| expression '=' '=' expression { $$ = ($1 == $4); }
| expression '!' '=' expression { $$ = ($1 == $4); }
| expression '>' expression { $$ = ($1 > $3); }
| expression '<' expression { $$ = ($1 < $3); }
| expression '+' expression { $$ = $1 + $3; } | expression '+' expression { $$ = $1 + $3; }
| expression '-' expression { $$ = $1 - $3; } | expression '-' expression { $$ = $1 - $3; }
| expression '*' expression { $$ = $1 * $3; } | expression '*' expression { $$ = $1 * $3; }
@ -48,12 +33,10 @@ expression
$$ = $1 / $3; $$ = $1 / $3;
} }
| '-' number { $$ = -$2; } | '-' number { $$ = -$2; }
| '*' expression { $$ = vaddr_read($2, WORD_BYTES); }
| '(' expression ')' { $$ = $2; } | '(' expression ')' { $$ = $2; }
number number
: REGISTER : NUMBER
| NUMBER
| HEX_NUMBER | HEX_NUMBER
%% %%

View file

@ -1,2 +1,3 @@
SRCS-y += src/monitor/sdb/addrexp.tag.c src/monitor/sdb/addrexp.yy.c SRCS-y += src/monitor/sdb/addrexp.tag.c src/monitor/sdb/addrexp.yy.c
INC_PATH += src/monitor/sdb
LFLAGS += -DYY_NO_UNPUT -DYY_NO_INPUT LFLAGS += -DYY_NO_UNPUT -DYY_NO_INPUT

View file

@ -16,24 +16,22 @@
#include "sdb.h" #include "sdb.h"
#include "common.h" #include "common.h"
#include "sys/types.h" #include "sys/types.h"
#include <addrexp.h>
#include <addrexp_lex.h>
#include <cpu/cpu.h> #include <cpu/cpu.h>
#include <errno.h> #include <errno.h>
#include <isa.h> #include <isa.h>
#include <memory/vaddr.h> #include <memory/paddr.h>
#include <readline/history.h> #include <readline/history.h>
#include <readline/readline.h> #include <readline/readline.h>
#include <stdint.h> #include <stdint.h>
#include <addrexp.h>
#include <addrexp_lex.h>
static int is_batch_mode = false; static int is_batch_mode = false;
// command handlers // command handlers
static int cmd_help(char *args); static int cmd_help(char *args);
static int cmd_c(char *args); static int cmd_c(char *args);
static int cmd_p(char *args);
static int cmd_q(char *args); static int cmd_q(char *args);
static int cmd_w(char *args);
static int cmd_x(char *args); static int cmd_x(char *args);
static int cmd_si(char *args); static int cmd_si(char *args);
static int cmd_info(char *args); static int cmd_info(char *args);
@ -55,10 +53,8 @@ static struct CommandTable {
{"help", "Display information about all supported commands", cmd_help, {"help", "Display information about all supported commands", cmd_help,
NULL, 0}, NULL, 0},
{"c", "Continue the execution of the program", cmd_c, NULL, 0}, {"c", "Continue the execution of the program", cmd_c, NULL, 0},
{"p", "Print expression result", cmd_p, NULL, 0},
{"q", "Exit NEMU", cmd_q, NULL, 0}, {"q", "Exit NEMU", cmd_q, NULL, 0},
{"x", "Examine content of physical memory address", cmd_x, NULL, 0}, {"x", "Examine content of physical memory address", cmd_x, NULL, 0},
{"w", "Break when expression is changed", cmd_w, NULL, 0},
{"si", "Execute next [n] program line", cmd_si, NULL, 0}, {"si", "Execute next [n] program line", cmd_si, NULL, 0},
{"info", "Print information of registers or watchpoints", cmd_info, {"info", "Print information of registers or watchpoints", cmd_info,
cmd_info_table, ARRLEN(cmd_info_table)}, cmd_info_table, ARRLEN(cmd_info_table)},
@ -129,17 +125,21 @@ static word_t parse_uint(const char *arg, bool *success) {
} }
} }
word_t parse_expr(const char *arg, bool *success) { static paddr_t parse_expr(const char *arg, bool *success) {
if (arg == NULL) { if (arg == NULL) {
puts("Invalid expr argument."); puts("Invalid expr argument.");
*success = false; *success = false;
return 0; return 0;
} else { } else {
word_t res; // bool res = false;
// FIXME: We cannot use `parse_uint` here, it accept `-1234` as input
// paddr_t addr = parse_uint(arg, &res);
// *success = res;
paddr_t addr;
yy_scan_string(arg); yy_scan_string(arg);
*success = !yyparse(&res); *success = !yyparse(&addr);
yylex_destroy(); yylex_destroy();
return res; return addr;
} }
} }
@ -148,22 +148,6 @@ static int cmd_c(char *args) {
return 0; return 0;
} }
static int cmd_p(char *args) {
char *arg = strtok(NULL, "");
bool res = false;
word_t result = parse_expr(arg, &res);
if (!res)
goto wrong_usage;
printf("%s: %u\n", arg, result);
return 0;
wrong_usage:
printf("Invalid argument for command p: %s\n", arg);
printf("Usage: p [EXPR: <expr>]\n");
return 0;
}
static int cmd_q(char *args) { static int cmd_q(char *args) {
nemu_state.state = NEMU_QUIT; nemu_state.state = NEMU_QUIT;
return -1; return -1;
@ -201,12 +185,6 @@ static int cmd_info_w(char *args) {
return 0; return 0;
} }
static int cmd_w(char *args) {
char *expr = strtok(NULL, "");
wp_add(expr);
return 0;
}
static int cmd_x(char *args) { static int cmd_x(char *args) {
char *arg = strtok(NULL, " "); char *arg = strtok(NULL, " ");
bool res = false; bool res = false;
@ -215,15 +193,15 @@ static int cmd_x(char *args) {
goto wrong_usage; goto wrong_usage;
// No deliminter here, just pass all the remain argument to `parse_expr()` // No deliminter here, just pass all the remain argument to `parse_expr()`
arg = strtok(NULL, ""); arg = strtok(NULL, "");
word_t start_addr = parse_expr(arg, &res); word_t addr = parse_expr(arg, &res);
if (!res) if (!res)
goto wrong_usage; goto wrong_usage;
start_addr = start_addr & ~(WORD_BYTES - 1); addr = addr & ~(WORD_BYTES - 1);
for (vaddr_t vaddr = start_addr; vaddr < start_addr + n; vaddr += WORD_BYTES) { for (paddr_t paddr = addr; paddr < addr + n; paddr += WORD_BYTES) {
word_t value = vaddr_read(vaddr, WORD_BYTES); word_t value = paddr_read(addr, WORD_BYTES);
printf("\e[1;34m" FMT_PADDR "\e[0m" printf("\e[1;34m" FMT_PADDR "\e[0m"
" " FMT_WORD "\n", " " FMT_WORD "\n",
vaddr, value); paddr, value);
} }
return 0; return 0;

View file

@ -18,8 +18,4 @@
#include <common.h> #include <common.h>
word_t parse_expr(const char *arg, bool *success);
int wp_add(char * expr);
int wp_remove_by_number(int number);
#endif #endif

View file

@ -2,33 +2,31 @@
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University * Copyright (c) 2014-2022 Zihao Yu, Nanjing University
* *
* NEMU is licensed under Mulan PSL v2. * NEMU is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan * You can use this software according to the terms and conditions of the Mulan PSL v2.
*PSL v2. You may obtain a copy of Mulan PSL v2 at: * You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2 * http://license.coscl.org.cn/MulanPSL2
* *
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
*KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
*NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* *
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
***************************************************************************************/ ***************************************************************************************/
#include "sdb.h" #include "sdb.h"
#include <common.h>
#include <stdio.h>
#define NR_WP 32 #define NR_WP 32
typedef struct watchpoint { typedef struct watchpoint {
int NO; int NO;
struct watchpoint *next; struct watchpoint *next;
word_t val;
char *expr; /* TODO: Add more members if necessary */
} WP; } WP;
static WP wp_pool[NR_WP] = {}; static WP wp_pool[NR_WP] = {};
static WP *head = NULL, *tail = NULL, *free_ = NULL; static WP *head = NULL, *free_ = NULL;
static int wp_count = 0;
void init_wp_pool() { void init_wp_pool() {
int i; int i;
@ -41,110 +39,5 @@ void init_wp_pool() {
free_ = wp_pool; free_ = wp_pool;
} }
static WP *wp_new() { /* TODO: Implement the functionality of watchpoint */
if (free_ == NULL) {
Error("wp_pool: Watchpoint pool not initialized or is full.");
return NULL;
}
WP *ret = free_;
free_ = free_->next;
ret->NO = 0;
ret->next = NULL;
return ret;
}
static void wp_delete(WP *wp) {
Assert(wp, "Failed to delete watchpoint from pool.");
wp->next = free_;
free_ = wp;
}
int wp_add(char * expr) {
WP *wp = wp_new();
if (wp == NULL) {
Error("watchpoint: Failed to add watchpoint, pool is full.");
goto failed_create;
}
wp->NO = wp_count++;
if (tail == NULL) {
head = wp;
tail = wp;
} else {
tail->next = wp;
tail = wp;
}
bool success = false;
wp->val = parse_expr(expr, &success);
if (!success) {
Error("Failed to parse given expression `%s`", expr);
goto failed_create;
}
int len = strlen(expr);
wp->expr = malloc((len + 1) * sizeof(char));
if (wp->expr == NULL) {
Error("Failed to allocate memory for expression");
goto failed_create;
}
strncpy(wp->expr, expr, len + 1);
wp->expr[len] = '\0';
return 0;
failed_create:
wp_delete(wp);
return 1;
}
int wp_remove_by_number(int number) {
WP *target_prev;
// Find previous node of target number
for (target_prev = head; target_prev != NULL && target_prev->next->NO != number; target_prev = target_prev->next) ;
if (target_prev == NULL) {
Error("Watchpoint not found, you can check current watchpoints with `info w`");
return 1;
}
WP *target = target_prev->next;
target_prev->next = target->next;
if (target == head) {
head = target->next;
} else if (target == tail) {
tail = target_prev;
}
wp_delete(target);
return 0;
}
static bool wp_check_change(WP* wp) {
bool success = false;
word_t result;
result = parse_expr(wp->expr, &success);
if (!success) {
panic("Failed to evaluate expression `%s`", wp->expr);
}
if (result != wp->val) {
wp->val = result;
return true;
}
return false;
}
/*
Check if watchpoint value changed after execution
*/
bool wp_eval_all() {
WP *wp;
bool value_change = false;
for (wp = head; wp != NULL; wp = wp->next) {
int prev_val = wp->val;
if (wp_check_change(wp)) {
printf("Watchpoint %d: %s\n %u -> %u\n", wp->NO, wp->expr, prev_val, wp->val);
value_change = true;
}
}
return value_change;
}

View file

@ -1,5 +1,4 @@
TEST_SRCS += tests/expr_test.c TEST_SRCS += tests/expr_test.c
YACC = bison
$(OBJ_DIR)/%: %.c $(TEST_OBJS) app $(OBJ_DIR)/%: %.c $(TEST_OBJS) app
@mkdir -p $(dir $@) @mkdir -p $(dir $@)

View file

@ -1,6 +1,5 @@
#include "macro.h"
#include "sys/types.h" #include "sys/types.h"
#include <unistd.h> #include "unistd.h"
#include <assert.h> #include <assert.h>
#include <check.h> #include <check.h>
#include <math.h> #include <math.h>
@ -10,8 +9,6 @@
#include <time.h> #include <time.h>
#include <addrexp.h> #include <addrexp.h>
#include <addrexp_lex.h> #include <addrexp_lex.h>
#include <isa.h>
#include <reg.h>
char buf[65536] = {}, ref_buf[65536] = {}; char buf[65536] = {}, ref_buf[65536] = {};
static char code_buf[65536 + 128] = {}; // a little larger than `buf` static char code_buf[65536 + 128] = {}; // a little larger than `buf`
@ -150,12 +147,6 @@ struct {
{"-0x1", 0xFFFFFFFFU}, {"-0x1", 0xFFFFFFFFU},
{"0--1", 0x1}, {"0--1", 0x1},
{"0--0x1", 0x1}, {"0--0x1", 0x1},
}, reg_exprs[] = {
{"$ra", 0x1},
{"0x2 + 4*-$a7", 0xFFFFFFBEU},
{"0x1831/$gp + 13", 2077U},
{"$$0 == 123", 0},
{"$$0 == 0", 1},
}; };
START_TEST(test_expr_negative_operand) { START_TEST(test_expr_negative_operand) {
yy_scan_string(exprs[_i].expr); yy_scan_string(exprs[_i].expr);
@ -169,47 +160,6 @@ START_TEST(test_expr_negative_operand) {
} }
END_TEST END_TEST
extern const char *regs[];
START_TEST(test_expr_plain_register) {
int i, j, result;
char buf[30] = {};
uint32_t value;
// NOTE: need to fix this if want to support more arch
buf[0] = '$';
for (i = 0; i < 32; i++) {
ck_assert(strncpy(buf + 1, regs[i], 10) != NULL);
gpr(i) = i;
yy_scan_string(buf);
result = yyparse(&value);
yylex_destroy();
ck_assert_msg(result == 0, "expr = %s\n", buf);
ck_assert(value == i);
for (j = 1; j < 10; j++) {
buf[j] = '\0';
}
}
}
END_TEST
START_TEST(test_expr_register) {
int i;
uint32_t value;
for (i = 0; i < 32; i++) {
gpr(i) = i;
}
yy_scan_string(reg_exprs[_i].expr);
ck_assert(!yyparse(&value));
yylex_destroy();
ck_assert_msg(value == reg_exprs[_i].reference,
"\n\texpr = %s\n\t(addr = %u) != (reference = %u)\n", reg_exprs[_i].expr,
value, reg_exprs[_i].reference);
}
END_TEST
Suite *expr_suite(void) { Suite *expr_suite(void) {
Suite *s; Suite *s;
TCase *tc_core; TCase *tc_core;
@ -220,9 +170,6 @@ Suite *expr_suite(void) {
tcase_add_loop_test(tc_core, test_expr_random_100, 0, 20); tcase_add_loop_test(tc_core, test_expr_random_100, 0, 20);
tcase_add_loop_test(tc_core, test_expr_negative_operand, 0, tcase_add_loop_test(tc_core, test_expr_negative_operand, 0,
sizeof(exprs) / sizeof(exprs[0])); sizeof(exprs) / sizeof(exprs[0]));
tcase_add_loop_test(tc_core, test_expr_register, 0,
sizeof(reg_exprs) / sizeof(reg_exprs[0]));
tcase_add_test(tc_core, test_expr_plain_register);
suite_add_tcase(s, tc_core); suite_add_tcase(s, tc_core);
return s; return s;