commit 1c750154f5fa3f8521850512c911827e36bdb6df
parent e0b397f6b5f9021563e6309cbccda402d9afbd22
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Mon, 5 Nov 2018 11:26:50 +0000
[debuglang] Integrate debuglang in the build system
Debuglang (previously hosted) was a totally independent
executable. This patch integrates it with the current
build system and with the code.
Change-Id: Ic74e25990ffb3bb81413d2229ee8ca3fab559546
Co-authored-by: Joel Hutton
Diffstat:
12 files changed, 370 insertions(+), 329 deletions(-)
diff --git a/arch/amd64/Makefile b/arch/amd64/Makefile
@@ -1,8 +1,8 @@
PROJECTDIR = ../..
include $(PROJECTDIR)/scripts/rules.mk
-ROMOBJS = crt-$(SYS).o arch.o rom.o $(SRCDIR)/romfw/builtin.o
-RAMOBJS = crt-$(SYS).o arch.o rom.o $(SRCDIR)/ramfw/builtin.o
+ROMOBJS = crt-$(SYS).o arch.o rom.o $(DEBUGLANG) $(SRCDIR)/romfw/builtin.o
+RAMOBJS = crt-$(SYS).o arch.o rom.o $(DEBUGLANG) $(SRCDIR)/ramfw/builtin.o
TARGET = $(BINDIR)/romfw.elf $(BINDIR)/ramfw.elf
LIBS = -lhdl -lrmu -lc
diff --git a/arch/amd64/arch.c b/arch/amd64/arch.c
@@ -1,8 +1,13 @@
+#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <rcode.h>
+
+jmp_buf recover;
+
+
void
halt(void)
{
@@ -12,7 +17,7 @@ halt(void)
void
swtch(struct trapframe *fp)
{
- panic("swtch() not implemented");
+ longjmp(recover, 1);
}
void
diff --git a/arch/amd64/hosted.c b/arch/amd64/hosted.c
@@ -1,324 +0,0 @@
-#include <errno.h>
-#include <rcode.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <hosted.h>
-
-void
-print_tf(struct trapframe *tfp)
-{
- printf("x0=0x%llx\tx1=0x%llx\tx2=0x%llx\tx3=0x%llx\n"
- "x4=0x%llx\tx5=0x%llx\tx6=0x%llx\tx7=0x%llx\n"
- "x8=0x%llx\tx9=0x%llx\tx10=0x%llx\tx11=0x%llx\n"
- "x12=0x%llx\tx13=0x%llx\tx14=0x%llx\tx15=0x%llx\n"
- "x16=0x%llx\tx17=0x%llx\tx18=0x%llx\tx19=0x%llx\n"
- "x20=0x%llx\tx21=0x%llx\tx22=0x%llx\tx23=0x%llx\n"
- "x24=0x%llx\tx25=0x%llx\tx26=0x%llx\tx27=0x%llx\n"
- "x28=0x%llx\tx29=0x%llx\tx30=0x%llx\telr=%p\n"
- "spsr=0x%llx\tesr=0x%llx\tfar=0x%llx\n"
- "sp=0x%p\n",
- tfp->x0, tfp->x1, tfp->x2, tfp->x3,
- tfp->x4, tfp->x5, tfp->x6, tfp->x7,
- tfp->x8, tfp->x9, tfp->x10, tfp->x11,
- tfp->x12, tfp->x13, tfp->x14, tfp->x15,
- tfp->x16, tfp->x17, tfp->x18, tfp->x19,
- tfp->x20, tfp->x21, tfp->x22, tfp->x23,
- tfp->x24, tfp->x25, tfp->x26, tfp->x27,
- tfp->x28, tfp->x29, tfp->x30, tfp->elr,
- tfp->spsr, tfp->esr, tfp->far, tfp->sp);
-}
-
-/* Read a value in a given base between 2 and 16 0 means default base;
- * 10, unless the string begins with "0x" or "0b"
- */
-unsigned long long
-base_read(char* str, int base, int *err)
-{
- unsigned long long val;
- char *endptr;
-
- endptr = NULL;
- errno = 0;
- val = strtoull(str, &endptr, base);
- if (str == endptr || errno != 0){
- ERROR("strtoull error with '%s' in base %d\n", str, base);
- if(err != NULL)
- *err = 1;
- }
- return val;
-}
-
-/* Get reg struct for named reg */
-unsigned long long*
-get_named_reg(char* name, struct trapframe* tfp)
-{
- size_t i;
- char *regptr;
-
- regptr=NULL;
- for(i=0;i<NUM_NAMED_REGS;i++){
- if(strcmp(name,named_regs[i].name)==0){
- regptr = (char*) tfp;
- regptr += named_regs[i].offset;
- }
- }
- return (unsigned long long*) regptr;
-}
-
-/* Get rmc_command struct for named rmc command */
-const struct rmc_command*
-get_rmc_cmd(char* name)
-{
- size_t i;
-
- for(i=0;i<NUM_RMC_COMMANDS;i++){
- if(strcmp(name,rmc_commands[i].name)==0){
- return &rmc_commands[i];
- }
- }
- return NULL;
-}
-
-/* Get command struct for named command */
-const struct command*
-get_command(char* name)
-{
- size_t i;
-
- for(i=0;i<NUM_COMMANDS;i++){
- if(strcmp(name,commands[i].name)==0){
- return &commands[i];
- }
- }
- return NULL;
-}
-
-int
-do_set(char** argv,int argc, struct trapframe* tfp)
-{
- unsigned long long *reg=NULL;
- unsigned long long setval=0;
- unsigned int base;
- int err;
-
- err = 0;
-
- reg = get_named_reg(argv[1],tfp);
- if( reg == NULL){
- ERROR("Register '%s' not found\n",argv[1]);
- return 1;
- }
-
- base = 0;
-
- switch(argc){
- case 4:
- base = base_read(argv[3], 10, &err);
- if(err)
- return 1;
- /* fallthrough */
- case 3:
- setval = base_read(argv[2], base, &err);
- if(err)
- return 1;
- break;
- default:
- ERROR("Invalid number of parameters for set\n");
- return 1;
- }
- INFO("set:0x%llx\n",setval);
- *reg=setval;
- return 0;
-}
-
-int
-do_read(char** argv,int argc, struct trapframe* tfp)
-{
- unsigned long long* reg=NULL;
- char* format_string;
-
- reg = get_named_reg(argv[1],tfp);
- if(reg == NULL){
- ERROR("Register '%s' not found\n",argv[1]);
- return 1;
- }
-
- switch(argc){
- case 3:
- switch(atoi(argv[2])){
- case 10:
- format_string="%llu\n";
- break;
- case 16:
- format_string="%llx\n";
- break;
- default:
- ERROR("Unsupported base for read:%s\nsupported: 10,16\n",
- argv[2]);
- return 1;
- }
- break;
- case 2:
- format_string="%llu\n";
- break;
- default:
- ERROR("Invalid number of arguments for read\n");
- return 1;
- }
- printf(format_string,*reg);
- return 0;
-}
-
-int
-do_dump(char** argv,int argc, struct trapframe* tfp)
-{
- print_tf(tfp);
- return 0;
-}
-
-int
-do_trap(char** argv,int argc, struct trapframe* tfp)
-{
- trap(tfp);
- return 0;
-}
-
-int
-do_rmc(char** argv,int argc, struct trapframe* tfp)
-{
- unsigned char class;
- unsigned char func;
- unsigned int base;
- const struct rmc_command *rmc_cmd;
- int err;
-
- err = 0;
-
- base = 0;
- switch(argc){
- case 4:
- base = base_read(argv[3], 10, &err);
- if(err)
- return 1;
- /* fallthrough */
- case 3:
- class = base_read(argv[1], base, &err);
- func = base_read(argv[2], base, &err);
- if(err)
- return 1;
- break;
- case 2:
- rmc_cmd = get_rmc_cmd(argv[1]);
- if (rmc_cmd == NULL){
- ERROR("rmc '%s' not found\n",argv[1]);
- return 1;
- }
- class = rmc_cmd->class;
- func = rmc_cmd->func;
- break;
- default:
- ERROR("Invalid number of parameters for rmc\n");
- return 1;
- }
- INFO("class:%d,func:%d\n",class,func);
- tfp->esr=(unsigned long long) RMC<<26;
- tfp->esr |= class;
- tfp->esr |= (func<<8);
- trap(tfp);
- return 0;
-}
-
-/* Separate buffer whitespace */
-void
-tokenise(char* buff, char** argv, unsigned int* argc, char* sep)
-{
- char* token;
-
- *argc=0;
- token=strtok(buff,sep);
- while(token!=NULL){
- argv[*argc]=token;
- (*argc)++;
- token=strtok(NULL,sep);
- }
- return;
-}
-
-char*
-trim(char* buff)
-{
- int bufflen,i;
- char* newbuff;
-
- newbuff = buff;
- bufflen=strlen(buff);
-
- /* Trailing whitespace */
- for(i = bufflen-1; i>0; i--){
- if(buff[i]==' ' || buff[i]=='\t' || buff[i] == '\n'){
- buff[i]='\0';;
- }
- else{
- break;
- }
- }
- /* Leading whitespace */
- for(i = 0; i<bufflen; i++){
- if(buff[i]==' ' || buff[i]=='\t' || buff[i] == '\n'){
- newbuff+=1;
- }
- else{
- break;
- }
- }
- return newbuff;
-}
-
-int
-parse_cmd(char * cmd, struct trapframe* tfp)
-{
- char* argv[MAX_PARTS];
- unsigned int argc;
- const struct command* com;
-
- cmd = trim(cmd);
-
- /* Get array of strings by separating on whitespace */
- tokenise(cmd,argv,&argc," ");
-
- if(argc != 0){
- com = get_command(argv[0]);
- }
-
- if(com == NULL){
- ERROR("Command '%s' not found\n",argv[0]);
- return 1;
- }
-
- /* Call eval function for specific command */
- com->eval(argv,argc, tfp);
- return 0;
-}
-
-int
-main(int argc, char *argv[])
-{
- char buffer[BUFFER_SIZE];
- struct trapframe tf;
- char* end;
-
- memset(&tf, 0, sizeof(struct trapframe));
- end=0;
- do{
- printf("$ ");
- fflush(stdout);
- end = fgets(buffer,BUFFER_SIZE,stdin);
- if(strlen(buffer)>1){
- parse_cmd(buffer,&tf);
- }
- fflush(stdout);
- }
- while(end != NULL);
- return 0;
-}
diff --git a/arch/amd64/ram.c b/arch/amd64/ram.c
@@ -3,5 +3,6 @@
int
main(int argc, char *argv[])
{
+ debug();
return 0;
}
diff --git a/arch/amd64/rom.c b/arch/amd64/rom.c
@@ -3,5 +3,6 @@
int
main(int argc, char *argv[])
{
+ debug();
return 0;
}
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
@@ -8,12 +8,14 @@ MORECFLAGS = -DUARTBASE=0x1c0c0000 \
ROMOBJS = rom-crt-$(SYS).o \
rom-$(SYS).o \
arch.o \
+ $(DEBUGLANG) \
$(DRVDIR)/uart.o \
$(SRCDIR)/romfw/builtin.o \
RAMOBJS = ram-crt-$(SYS).o \
ram-$(SYS).o \
arch.o \
+ $(DEBUGLANG) \
$(DRVDIR)/uart.o \
$(SRCDIR)/ramfw/builtin.o \
diff --git a/config/amd64-linux.mk b/config/amd64-linux.mk
@@ -6,3 +6,4 @@ ASM = as
LINKER = ld
SYS = linux
CROSS_COMPILE =
+DEBUGLANG = $(SRCDIR)/debuglang/builtin.o
diff --git a/include/rcode.h b/include/rcode.h
@@ -149,6 +149,7 @@ extern void panic(const char *msg);
extern void printk(const char * restrict fmt, ...) PRINTKFMT;
extern void rmc(Rmucmd *cmd);
extern void swtch(struct trapframe *fp);
+extern void debug(void);
/* architectural functions */
extern void halt(void);
diff --git a/scripts/genhosted.sh b/scripts/gendebuglang.sh
diff --git a/src/Makefile b/src/Makefile
@@ -3,7 +3,7 @@ include $(PROJECTDIR)/scripts/rules.mk
LIBS = libc librmu libtypes libhdl
IMGS = ramfw romfw
-DIRS = $(LIBS) $(IMGS)
+DIRS = $(LIBS) $(IMGS) debuglang
OBJS = rmc.o ecstr.o
all: $(IMGS)
@@ -14,7 +14,7 @@ gen: FORCE
ecstr.c: $(INCDIR)/rcode.h
$(SCRIPTDIR)/genecstr.sh $(INCDIR)/rcode.h
-$(IMGS): $(LIBS) $(OBJS)
+$(IMGS): $(LIBS) $(OBJS) debuglang
$(DIRS): FORCE
+@cd $@ && $(MAKE)
diff --git a/src/debuglang/Makefile b/src/debuglang/Makefile
@@ -0,0 +1,18 @@
+PROJECTDIR=../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = debuglang.o
+TARGET = builtin.o
+
+all: $(TARGET)
+
+builtin.o: $(OBJS)
+ $(LD) $(RCODE_LDFLAGS) -r -o $@ $(OBJS)
+
+debuglang.h: $(SCRIPTDIR)/rmu.cmd
+ $(SCRIPTDIR)/gendebuglang.sh $(SCRIPTDIR)/rmu.cmd > $@
+
+debuglang.c: debuglang.h
+
+clean:
+ rm -f debuglang.h
diff --git a/src/debuglang/debuglang.c b/src/debuglang/debuglang.c
@@ -0,0 +1,336 @@
+#include <errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rcode.h>
+
+#include "debuglang.h"
+
+void
+print_tf(struct trapframe *tfp)
+{
+ printf("x0=0x%llx\tx1=0x%llx\tx2=0x%llx\tx3=0x%llx\n"
+ "x4=0x%llx\tx5=0x%llx\tx6=0x%llx\tx7=0x%llx\n"
+ "x8=0x%llx\tx9=0x%llx\tx10=0x%llx\tx11=0x%llx\n"
+ "x12=0x%llx\tx13=0x%llx\tx14=0x%llx\tx15=0x%llx\n"
+ "x16=0x%llx\tx17=0x%llx\tx18=0x%llx\tx19=0x%llx\n"
+ "x20=0x%llx\tx21=0x%llx\tx22=0x%llx\tx23=0x%llx\n"
+ "x24=0x%llx\tx25=0x%llx\tx26=0x%llx\tx27=0x%llx\n"
+ "x28=0x%llx\tx29=0x%llx\tx30=0x%llx\telr=%p\n"
+ "spsr=0x%llx\tesr=0x%llx\tfar=0x%llx\n"
+ "sp=0x%p\n",
+ tfp->x0, tfp->x1, tfp->x2, tfp->x3,
+ tfp->x4, tfp->x5, tfp->x6, tfp->x7,
+ tfp->x8, tfp->x9, tfp->x10, tfp->x11,
+ tfp->x12, tfp->x13, tfp->x14, tfp->x15,
+ tfp->x16, tfp->x17, tfp->x18, tfp->x19,
+ tfp->x20, tfp->x21, tfp->x22, tfp->x23,
+ tfp->x24, tfp->x25, tfp->x26, tfp->x27,
+ tfp->x28, tfp->x29, tfp->x30, tfp->elr,
+ tfp->spsr, tfp->esr, tfp->far, tfp->sp);
+}
+
+/* Read a value in a given base between 2 and 16 0 means default base;
+ * 10, unless the string begins with "0x" or "0b"
+ */
+unsigned long long
+base_read(char* str, int base, int *err)
+{
+ unsigned long long val;
+ char *endptr;
+
+ endptr = NULL;
+ errno = 0;
+ val = strtoull(str, &endptr, base);
+ if (str == endptr || errno != 0){
+ ERROR("strtoull error with '%s' in base %d\n", str, base);
+ if(err != NULL)
+ *err = 1;
+ }
+ return val;
+}
+
+/* Get reg struct for named reg */
+unsigned long long*
+get_named_reg(char* name, struct trapframe* tfp)
+{
+ size_t i;
+ char *regptr;
+
+ regptr=NULL;
+ for(i=0;i<NUM_NAMED_REGS;i++){
+ if(strcmp(name,named_regs[i].name)==0){
+ regptr = (char*) tfp;
+ regptr += named_regs[i].offset;
+ }
+ }
+ return (unsigned long long*) regptr;
+}
+
+/* Get rmc_command struct for named rmc command */
+const struct rmc_command*
+get_rmc_cmd(char* name)
+{
+ size_t i;
+
+ for(i=0;i<NUM_RMC_COMMANDS;i++){
+ if(strcmp(name,rmc_commands[i].name)==0){
+ return &rmc_commands[i];
+ }
+ }
+ return NULL;
+}
+
+/* Get command struct for named command */
+const struct command*
+get_command(char* name)
+{
+ size_t i;
+
+ for(i=0;i<NUM_COMMANDS;i++){
+ if(strcmp(name,commands[i].name)==0){
+ return &commands[i];
+ }
+ }
+ return NULL;
+}
+
+int
+do_set(char** argv,int argc, struct trapframe* tfp)
+{
+ unsigned long long *reg=NULL;
+ unsigned long long setval=0;
+ unsigned int base;
+ int err;
+
+ err = 0;
+
+ reg = get_named_reg(argv[1],tfp);
+ if( reg == NULL){
+ ERROR("Register '%s' not found\n",argv[1]);
+ return 1;
+ }
+
+ base = 0;
+
+ switch(argc){
+ case 4:
+ base = base_read(argv[3], 10, &err);
+ if(err)
+ return 1;
+ /* fallthrough */
+ case 3:
+ setval = base_read(argv[2], base, &err);
+ if(err)
+ return 1;
+ break;
+ default:
+ ERROR("Invalid number of parameters for set\n");
+ return 1;
+ }
+ INFO("set:0x%llx\n",setval);
+ *reg=setval;
+ return 0;
+}
+
+int
+do_read(char** argv,int argc, struct trapframe* tfp)
+{
+ unsigned long long* reg=NULL;
+ char* format_string;
+
+ reg = get_named_reg(argv[1],tfp);
+ if(reg == NULL){
+ ERROR("Register '%s' not found\n",argv[1]);
+ return 1;
+ }
+
+ switch(argc){
+ case 3:
+ switch(atoi(argv[2])){
+ case 10:
+ format_string="%llu\n";
+ break;
+ case 16:
+ format_string="%llx\n";
+ break;
+ default:
+ ERROR("Unsupported base for read:%s\nsupported: 10,16\n",
+ argv[2]);
+ return 1;
+ }
+ break;
+ case 2:
+ format_string="%llu\n";
+ break;
+ default:
+ ERROR("Invalid number of arguments for read\n");
+ return 1;
+ }
+ printf(format_string,*reg);
+ return 0;
+}
+
+int
+do_dump(char** argv,int argc, struct trapframe* tfp)
+{
+ print_tf(tfp);
+ return 0;
+}
+
+int
+do_trap(char** argv,int argc, struct trapframe* tfp)
+{
+ trap(tfp);
+ return 0;
+}
+
+int
+do_rmc(char** argv,int argc, struct trapframe* tfp)
+{
+ unsigned char class;
+ unsigned char func;
+ unsigned int base;
+ const struct rmc_command *rmc_cmd;
+ int err;
+
+ err = 0;
+
+ base = 0;
+ switch(argc){
+ case 4:
+ base = base_read(argv[3], 10, &err);
+ if(err)
+ return 1;
+ /* fallthrough */
+ case 3:
+ class = base_read(argv[1], base, &err);
+ func = base_read(argv[2], base, &err);
+ if(err)
+ return 1;
+ break;
+ case 2:
+ rmc_cmd = get_rmc_cmd(argv[1]);
+ if (rmc_cmd == NULL){
+ ERROR("rmc '%s' not found\n",argv[1]);
+ return 1;
+ }
+ class = rmc_cmd->class;
+ func = rmc_cmd->func;
+ break;
+ default:
+ ERROR("Invalid number of parameters for rmc\n");
+ return 1;
+ }
+ INFO("class:%d,func:%d\n",class,func);
+ tfp->esr=(unsigned long long) RMC<<26;
+ tfp->esr |= class;
+ tfp->esr |= (func<<8);
+ trap(tfp);
+ return 0;
+}
+
+/* Separate buffer whitespace */
+void
+tokenise(char* buff, char** argv, unsigned int* argc, char* sep)
+{
+ char* token;
+
+ *argc=0;
+ token=strtok(buff,sep);
+ while(token!=NULL){
+ argv[*argc]=token;
+ (*argc)++;
+ token=strtok(NULL,sep);
+ }
+ return;
+}
+
+char*
+trim(char* buff)
+{
+ int bufflen,i;
+ char* newbuff;
+
+ newbuff = buff;
+ bufflen=strlen(buff);
+
+ /* Trailing whitespace */
+ for(i = bufflen-1; i>0; i--){
+ if(buff[i]==' ' || buff[i]=='\t' || buff[i] == '\n'){
+ buff[i]='\0';;
+ }
+ else{
+ break;
+ }
+ }
+ /* Leading whitespace */
+ for(i = 0; i<bufflen; i++){
+ if(buff[i]==' ' || buff[i]=='\t' || buff[i] == '\n'){
+ newbuff+=1;
+ }
+ else{
+ break;
+ }
+ }
+ return newbuff;
+}
+
+int
+parse_cmd(char * cmd, struct trapframe* tfp)
+{
+ char* argv[MAX_PARTS];
+ unsigned int argc;
+ const struct command* com;
+
+ cmd = trim(cmd);
+
+ /* Get array of strings by separating on whitespace */
+ tokenise(cmd,argv,&argc," ");
+
+ if(argc != 0){
+ com = get_command(argv[0]);
+ }
+
+ if(com == NULL){
+ ERROR("Command '%s' not found\n",argv[0]);
+ return 1;
+ }
+
+ /* Call eval function for specific command */
+ com->eval(argv,argc, tfp);
+ return 0;
+}
+
+static void
+run(struct trapframe *tf)
+{
+ char buffer[BUFFER_SIZE];
+ char* end;
+
+ end=0;
+ do{
+ printf("$ ");
+ fflush(stdout);
+ end = fgets(buffer,BUFFER_SIZE,stdin);
+ if(strlen(buffer)>1){
+ parse_cmd(buffer, tf);
+ }
+ fflush(stdout);
+ }
+ while(end != NULL);
+}
+
+void
+debug(void)
+{
+ struct trapframe tf;
+ extern jmp_buf recover;
+
+ memset(&tf, 0, sizeof(struct trapframe));
+
+ setjmp(recover);
+ run(&tf);
+}