diff --git a/Makefile b/Makefile index a55f97e..603b311 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ install: mspdebug mspdebug.man mspdebug: main.o fet.o rf2500.o dis.o uif.o ihex.o elf32.o stab.o util.o \ bsl.o sim.o symmap.o gdb.o btree.o device.o rtools.o sym.o devcmd.o \ - cproc.o vector.o cproc_util.o expr.o fet_error.o + cproc.o vector.o cproc_util.o expr.o fet_error.o binfile.o $(CC) $(LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS) .c.o: diff --git a/binfile.c b/binfile.c new file mode 100644 index 0000000..edbe0d5 --- /dev/null +++ b/binfile.c @@ -0,0 +1,108 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "util.h" +#include "binfile.h" +#include "ihex.h" +#include "elf32.h" +#include "symmap.h" + +struct file_format { + int (*check)(FILE *in); + int (*extract)(FILE *in, binfile_imgcb_t cb, void *user_data); + int (*syms)(FILE *in, stab_t stab); +}; + +static const struct file_format formats[] = { + { + .check = elf32_check, + .extract = elf32_extract, + .syms = elf32_syms + }, + { + .check = ihex_check, + .extract = ihex_extract + }, + { + .check = symmap_check, + .syms = symmap_syms + } +}; + +static const struct file_format *identify(FILE *in) +{ + int i; + + for (i = 0; i < ARRAY_LEN(formats); i++) { + const struct file_format *f = &formats[i]; + + if (f->check(in) > 0) + return f; + } + + return NULL; +} + +int binfile_info(FILE *in) +{ + const struct file_format *fmt = identify(in); + int flags = 0; + + if (fmt) { + if (fmt->extract) + flags |= BINFILE_HAS_TEXT; + if (fmt->syms) + flags |= BINFILE_HAS_SYMS; + } + + return flags; +} + +int binfile_extract(FILE *in, binfile_imgcb_t cb, void *user_data) +{ + const struct file_format *fmt = identify(in); + + if (!fmt) { + fprintf(stderr, "binfile: unknown file format\n"); + return -1; + } + + if (!fmt->extract) { + fprintf(stderr, "binfile: this format contains no code\n"); + return -1; + } + + return fmt->extract(in, cb, user_data); +} + +int binfile_syms(FILE *in, stab_t stab) +{ + const struct file_format *fmt = identify(in); + + if (!fmt) { + fprintf(stderr, "binfile: unknown file format\n"); + return -1; + } + + if (!fmt->syms) { + fprintf(stderr, "binfile: this format contains no symbols\n"); + return -1; + } + + return fmt->syms(in, stab); +} diff --git a/binfile.h b/binfile.h index 9369dfa..c99c5bf 100644 --- a/binfile.h +++ b/binfile.h @@ -21,24 +21,32 @@ #include #include - #include "stab.h" /* Callback for binary image data */ -typedef int (*imgfunc_t)(void *user_data, - uint16_t addr, const uint8_t *data, int len); +typedef int (*binfile_imgcb_t)(void *user_data, + uint16_t addr, const uint8_t *data, int len); -/* Intel HEX file support */ -int ihex_check(FILE *in); -int ihex_extract(FILE *in, imgfunc_t cb, void *user_data); +#define BINFILE_HAS_SYMS 0x01 +#define BINFILE_HAS_TEXT 0x02 -/* ELF32 file support */ -int elf32_check(FILE *in); -int elf32_extract(FILE *in, imgfunc_t cb, void *user_data); -int elf32_syms(FILE *in, stab_t stab); +/* Examine the given file and figure out what it contains. If the file + * type is unknown, 0 is returned. If an IO error occurs, -1 is + * returned. Otherwise, the return value is a positive integer + * bitmask. + */ +int binfile_info(FILE *in); -/* *.map file support */ -int symmap_check(FILE *in); -int symmap_syms(FILE *in, stab_t stab); +/* If possible, extract the text from this file, feeding it in chunks + * of an indeterminate size to the callback given. + * + * Returns 0 if successful, -1 if an error occurs. + */ +int binfile_extract(FILE *in, binfile_imgcb_t cb, void *user_data); + +/* Attempt to load symbols from the file and store them in the given + * symbol table. Returns 0 on success or -1 if an error occurs. + */ +int binfile_syms(FILE *in, stab_t stab); #endif diff --git a/devcmd.c b/devcmd.c index af51c6e..a5c1bed 100644 --- a/devcmd.c +++ b/devcmd.c @@ -533,7 +533,6 @@ static int cmd_prog(cproc_t cp, char **arg) device_t dev = cproc_device(cp); stab_t stab = cproc_stab(cp); FILE *in; - int result = 0; struct prog_data prog; if (cproc_prompt_abort(cp, CPROC_MODIFY_SYMS)) @@ -552,14 +551,14 @@ static int cmd_prog(cproc_t cp, char **arg) prog_init(&prog, dev); - if (elf32_check(in)) { - result = elf32_extract(in, prog_feed, &prog); + if (binfile_extract(in, prog_feed, &prog) < 0) { + fclose(in); + return -1; + } + + if (binfile_info(in) & BINFILE_HAS_SYMS) { stab_clear(stab); - elf32_syms(in, stab); - } else if (ihex_check(in)) { - result = ihex_extract(in, prog_feed, &prog); - } else { - fprintf(stderr, "prog: %s: unknown file type\n", *arg); + binfile_syms(in, stab); } fclose(in); @@ -573,7 +572,7 @@ static int cmd_prog(cproc_t cp, char **arg) } cproc_unmodify(cp, CPROC_MODIFY_SYMS); - return result; + return 0; } static const struct cproc_command commands[] = { diff --git a/elf32.c b/elf32.c index cc11daf..f04a4ce 100644 --- a/elf32.c +++ b/elf32.c @@ -24,7 +24,7 @@ #else #include #endif -#include "binfile.h" +#include "elf32.h" #ifndef EM_MSP430 #define EM_MSP430 0x69 @@ -136,7 +136,7 @@ static uint32_t file_to_phys(struct elf32_info *info, uint32_t v) } static int feed_section(struct elf32_info *info, - FILE *in, int offset, int size, imgfunc_t cb, + FILE *in, int offset, int size, binfile_imgcb_t cb, void *user_data) { uint8_t buf[1024]; @@ -186,7 +186,7 @@ static int read_all(struct elf32_info *info, FILE *in) return 0; } -int elf32_extract(FILE *in, imgfunc_t cb, void *user_data) +int elf32_extract(FILE *in, binfile_imgcb_t cb, void *user_data) { struct elf32_info info; int i; diff --git a/elf32.h b/elf32.h new file mode 100644 index 0000000..e4d858c --- /dev/null +++ b/elf32.h @@ -0,0 +1,28 @@ +/* MSPDebug - debugging tool for the eZ430 + * Copyright (C) 2009, 2010 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ELF32_H_ +#define ELF32_H_ + +#include "binfile.h" + +int elf32_check(FILE *in); +int elf32_extract(FILE *in, binfile_imgcb_t cb, void *user_data); +int elf32_syms(FILE *in, stab_t stab); + +#endif diff --git a/ihex.c b/ihex.c index 47b720e..8ba3593 100644 --- a/ihex.c +++ b/ihex.c @@ -19,7 +19,7 @@ #include #include #include -#include "binfile.h" +#include "ihex.h" int ihex_check(FILE *in) { @@ -27,7 +27,7 @@ int ihex_check(FILE *in) return fgetc(in) == ':'; } -static int feed_line(FILE *in, uint8_t *data, int nbytes, imgfunc_t cb, +static int feed_line(FILE *in, uint8_t *data, int nbytes, binfile_imgcb_t cb, void *user_data) { uint8_t cksum = 0; @@ -52,7 +52,7 @@ static int feed_line(FILE *in, uint8_t *data, int nbytes, imgfunc_t cb, data + 4, nbytes - 5); } -int ihex_extract(FILE *in, imgfunc_t cb, void *user_data) +int ihex_extract(FILE *in, binfile_imgcb_t cb, void *user_data) { char buf[128]; int lno = 0; diff --git a/ihex.h b/ihex.h new file mode 100644 index 0000000..e84fe32 --- /dev/null +++ b/ihex.h @@ -0,0 +1,27 @@ +/* MSPDebug - debugging tool for the eZ430 + * Copyright (C) 2009, 2010 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef IHEX_H_ +#define IHEX_H_ + +#include "binfile.h" + +int ihex_check(FILE *in); +int ihex_extract(FILE *in, binfile_imgcb_t cb, void *user_data); + +#endif diff --git a/sym.c b/sym.c index 82f43c7..4b477e0 100644 --- a/sym.c +++ b/sym.c @@ -57,7 +57,6 @@ static int cmd_sym_load_add(cproc_t cp, int clear, char **arg) { stab_t stab = cproc_stab(cp); FILE *in; - int result = 0; if (clear && cproc_prompt_abort(cp, CPROC_MODIFY_SYMS)) return 0; @@ -68,24 +67,20 @@ static int cmd_sym_load_add(cproc_t cp, int clear, char **arg) return -1; } - if (clear) + if (clear) { stab_clear(stab); + cproc_unmodify(cp, CPROC_MODIFY_SYMS); + } else { + cproc_modify(cp, CPROC_MODIFY_SYMS); + } - if (elf32_check(in)) - result = elf32_syms(in, stab); - else if (symmap_check(in)) - result = symmap_syms(in, stab); - else - fprintf(stderr, "sym: %s: unknown file type\n", *arg); + if (binfile_syms(in, stab) < 0) { + fclose(in); + return -1; + } fclose(in); - - if (clear) - cproc_unmodify(cp, CPROC_MODIFY_SYMS); - else - cproc_modify(cp, CPROC_MODIFY_SYMS); - - return result; + return 0; } static int savemap_cb(void *user_data, const char *name, uint16_t value) diff --git a/symmap.c b/symmap.c index ff77273..ef5b740 100644 --- a/symmap.c +++ b/symmap.c @@ -19,7 +19,7 @@ #include #include #include -#include "binfile.h" +#include "symmap.h" int symmap_check(FILE *in) { diff --git a/symmap.h b/symmap.h new file mode 100644 index 0000000..639a2e3 --- /dev/null +++ b/symmap.h @@ -0,0 +1,27 @@ +/* MSPDebug - debugging tool for the eZ430 + * Copyright (C) 2009, 2010 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SYMMAP_H_ +#define SYMMAP_H_ + +#include "binfile.h" + +int symmap_check(FILE *in); +int symmap_syms(FILE *in, stab_t stab); + +#endif