From: drowe67 Date: Wed, 22 May 2013 12:55:26 +0000 (+0000) Subject: some more stlink files X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=6c597c18a72aa2bd459a30b103b9ba63233f43e9;p=freetel-svn-tracking.git some more stlink files git-svn-id: https://svn.code.sf.net/p/freetel/code@1262 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/stm32/README.txt b/codec2-dev/stm32/README.txt index bc9ad743..eac2d04b 100644 --- a/codec2-dev/stm32/README.txt +++ b/codec2-dev/stm32/README.txt @@ -6,6 +6,7 @@ TODO + Describe what gdb_stdio does, describe what UT does. + Where raw files end up. + Dump files and how to use them. + + check if "CFLAGS: -mlittle-endian -mthumb -mthumb-interwork" needed Getting Started ------------------------- @@ -28,7 +29,10 @@ Getting Started $ git clone https://github.com/texane/stlink.git $ cd stlink ~/stlink$ git checkout bbecbc1e81b15b85829149424d048d96bd844939 - ~/stlink$ patch -p0 < ~/codec2-dev/stlink.patch + ~/stlink$ patch -p0 < ~/codec2-dev/stm32/stlink/stlink.patch + ~/stlink$ cp ~/codec2-dev/stm32/stlink/elfsym.* . + ~/stlink$ ./autogen.sh + ~/stlink$ ./configure ~/stlink$ make . Place a copy of hts1a.raw in the stlink directory and start st-util: @@ -36,7 +40,7 @@ Getting Started ~/stlink$ cp ~/codec2-dev/raw/hts1a . ~/stlink$ sudo ./st-util -f /home/david/codec2-dev/stm32/stm32f4_codec2.elf -. Start gdb: +. In _another_ console start gdb: $ ~/codec2-dev/stm32$ ~/sat/bin/arm-none-eabi-gdb stm32f4_codec2.elf @@ -77,8 +81,8 @@ Process 1. Profiling macros. -2. enable DUMP to dump files, note proofiling times will be corrupted -by this due to latency in talking to Host +2. enable DUMP variable in Makefile to dump files, note profiling +times will be corrupted by this due to latency in talking to Host 3. Compare outputs using octave/diff_codec. Worked example: @@ -88,5 +92,5 @@ diff_codec("~/stlink/ref/hts1a_out_1300.raw", "~/stlink/hts1a_out_1300.raw","~/s Gotcha ------ -using printf rather than gdb_stdio_printf, regular stdio functions are stubbed out so will link, just nothing will happen. +Using printf rather than gdb_stdio_printf, regular stdio functions are stubbed out so will link, just nothing will happen. diff --git a/codec2-dev/stm32/stlink.patch b/codec2-dev/stm32/stlink.patch deleted file mode 100644 index 74cf2401..00000000 --- a/codec2-dev/stm32/stlink.patch +++ /dev/null @@ -1,428 +0,0 @@ -diff --git Makefile.am Makefile.am -index a315dd7..7406216 100644 ---- Makefile.am -+++ Makefile.am -@@ -7,7 +7,7 @@ bin_PROGRAMS = st-flash st-util - noinst_LIBRARIES = libstlink.a - - st_flash_SOURCES = flash/main.c --st_util_SOURCES = gdbserver/gdb-remote.c gdbserver/gdb-remote.h gdbserver/gdb-server.c mingw/mingw.c mingw/mingw.h -+st_util_SOURCES = gdbserver/gdb-remote.c gdbserver/gdb-remote.h gdbserver/gdb-server.c gdbserver/elfsym.c mingw/mingw.c mingw/mingw.h - - CFILES = \ - src/stlink-common.c \ -@@ -24,14 +24,14 @@ HFILES = \ - - libstlink_a_SOURCES = $(CFILES) $(HFILES) - --libstlink_a_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -+libstlink_a_CPPFLAGS = -std=gnu99 -Wall -Wextra -g - libstlink_a_LIBADD = $(LIBOBJS) - - st_flash_LDADD = libstlink.a --st_flash_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw -+st_flash_CPPFLAGS = -std=gnu99 -Wall -Wextra -g -I$(top_srcdir)/src -I$(top_srcdir)/mingw - --st_util_LDADD = libstlink.a --st_util_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw -+st_util_LDADD = libstlink.a -lelf -+st_util_CPPFLAGS = -std=gnu99 -Wall -Wextra -g -I$(top_srcdir)/src -I$(top_srcdir)/mingw - - EXTRA_DIST = autogen.sh - -diff --git gdbserver/Makefile gdbserver/Makefile -index bd5c73d..6763388 100644 ---- gdbserver/Makefile -+++ gdbserver/Makefile -@@ -1,12 +1,11 @@ - PRG := st-util --OBJS = gdb-remote.o gdb-server.o -+OBJS = gdb-remote.o gdb-server.o elfsym.o - - CFLAGS+=-g -Wall -Werror -std=gnu99 -I../src - LDFLAGS=-L.. -lstlink - - # libusb location --LDFLAGS+=`pkg-config --libs libusb-1.0` --CFLAGS+=`pkg-config --cflags libusb-1.0` -+LDFLAGS+=`pkg-config --libs libusb-1.0` -lelfCFLAGS+=`pkg-config --cflags libusb-1.0` - - all: $(PRG) - -diff --git gdbserver/gdb-server.c gdbserver/gdb-server.c -index f92fc05..e54d136 100644 ---- gdbserver/gdb-server.c -+++ gdbserver/gdb-server.c -@@ -1,11 +1,12 @@ - /* -*- tab-width:8 -*- */ --#define DEBUG 0 -+//#define DEBUG 0 - /* - Copyright (C) 2011 Peter Zotov - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. - */ - -+#include - #include - #include - #include -@@ -20,14 +21,29 @@ - #include - #include - #endif -+#include -+#include -+#include - - #include - - #include "gdb-remote.h" -+#include "elfsym.h" - - #define DEFAULT_LOGGING_LEVEL 50 - #define DEFAULT_GDB_LISTEN_PORT 4242 - -+/* stdio command codes from target */ -+ -+#define GDB_STDIO_PRINTF 1 -+#define GDB_STDIO_FOPEN 2 -+#define GDB_STDIO_FCLOSE 3 -+#define GDB_STDIO_FWRITE 4 -+#define GDB_STDIO_FREAD 5 -+#define GDB_STDIO_FPRINTF 6 -+ -+#define MAX_STR 256 -+ - #define STRINGIFY_inner(name) #name - #define STRINGIFY(name) STRINGIFY_inner(name) - -@@ -46,11 +62,12 @@ typedef struct _st_state_t { - // "/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTE531X6-if00-port0" is only 58 chars - char devicename[100]; - int logging_level; -- int listen_port; -+ int listen_port; -+ char elf_filename[255]; - } st_state_t; - - --int serve(stlink_t *sl, int port); -+int serve(stlink_t *sl, int port, char *elf_filename); - char* make_memory_map(stlink_t *sl); - - -@@ -76,13 +93,14 @@ int parse_options(int argc, char** argv, st_state_t *st) { - " -p 4242, --listen_port=1234\n" - "\t\t\tSet the gdb server listen port. " - "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n" -+ " -f \tenable File I/O of target executable elf_filename" - ; - - - int option_index = 0; - int c; - int q; -- while ((c = getopt_long(argc, argv, "hv::d:s:1p:", long_options, &option_index)) != -1) { -+ while ((c = getopt_long(argc, argv, "hv::d:s:1p:1f:", long_options, &option_index)) != -1) { - switch (c) { - case 0: - printf("XXXXX Shouldn't really normally come here, only if there's no corresponding option\n"); -@@ -110,25 +128,29 @@ int parse_options(int argc, char** argv, st_state_t *st) { - strcpy(st->devicename, optarg); - } - break; -- case '1': -- st->stlink_version = 1; -- break; -- case 's': -- sscanf(optarg, "%i", &q); -- if (q < 0 || q > 2) { -- fprintf(stderr, "stlink version %d unknown!\n", q); -- exit(EXIT_FAILURE); -- } -- st->stlink_version = q; -- break; -- case 'p': -- sscanf(optarg, "%i", &q); -- if (q < 0) { -- fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); -- exit(EXIT_FAILURE); -- } -- st->listen_port = q; -- break; -+ case '1': -+ st->stlink_version = 1; -+ break; -+ case 's': -+ sscanf(optarg, "%i", &q); -+ if (q < 0 || q > 2) { -+ fprintf(stderr, "stlink version %d unknown!\n", q); -+ exit(EXIT_FAILURE); -+ } -+ st->stlink_version = q; -+ break; -+ case 'p': -+ sscanf(optarg, "%i", &q); -+ if (q < 0) { -+ fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); -+ exit(EXIT_FAILURE); -+ } -+ st->listen_port = q; -+ break; -+ case 'f': -+ sscanf(optarg, "%s", st->elf_filename); -+ printf("-f arg; %s\n", st->elf_filename); -+ break; - } - } - -@@ -162,7 +184,7 @@ int main(int argc, char** argv) { - sl = stlink_v1_open(state.logging_level); - if(sl == NULL) return 1; - break; -- } -+ } - - printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); - -@@ -177,7 +199,7 @@ int main(int argc, char** argv) { - } - #endif - -- while(serve(sl, state.listen_port) == 0); -+ while(serve(sl, state.listen_port, state.elf_filename) == 0); - - #ifdef __MINGW32__ - winsock_error: -@@ -625,7 +647,179 @@ error: - return error; - } - --int serve(stlink_t *sl, int port) { -+static unsigned int func_addr, ret_addr, pstr1_addr, pstr2_addr; -+static unsigned int strlen1_addr, strlen2_addr, file_addr, ptr_addr; -+static unsigned int size_addr, nmem_addr; -+ -+static void write_buffer(stlink_t *sl, int target_addr, char* buf, size_t size) { -+ /* write the buffer right after the loader */ -+ size_t chunk = size & ~0x3; -+ size_t rem = size & 0x3; -+ -+ if (chunk) { -+ memcpy(sl->q_buf, buf, chunk); -+ stlink_write_mem32(sl, target_addr, chunk); -+ } -+ if (rem) { -+ memcpy(sl->q_buf, buf+chunk, rem); -+ stlink_write_mem8(sl, target_addr+chunk, rem); -+ } -+} -+ -+static void read_buffer(stlink_t *sl, int target_addr, char* buf, size_t size) { -+ unsigned adj_start = target_addr % 4; -+ unsigned count_rnd = (size + adj_start + 4 - 1) / 4 * 4; -+ size_t i; -+ -+ stlink_read_mem32(sl, target_addr - adj_start, count_rnd); -+ -+ for(i=0; iq_buf[i + adj_start]; -+} -+ -+static void fileio(stlink_t *sl) -+{ -+ int func, pstr1, pstr2, strlen1, strlen2, ptr, size, nmem; -+ int ret = 0; -+ FILE *file; -+ char file_name[MAX_STR]; -+ char mode[MAX_STR]; -+ char *buf; -+ -+ stlink_read_mem32(sl, func_addr, 4); -+ func = read_uint32(sl->q_buf, 0); -+ -+ /* func != 0 means target has requested a system call */ -+ -+ switch(func) { -+ -+ case GDB_STDIO_PRINTF: -+ stlink_read_mem32(sl, pstr1_addr, 4); -+ pstr1 = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, strlen1_addr, 4); -+ strlen1 = read_uint32(sl->q_buf, 0); -+ buf = (char*)malloc(strlen1+1); -+ assert(buf != NULL); -+ read_buffer(sl, pstr1, buf, strlen1); -+ buf[strlen1] = 0; -+ #ifdef DEBUG -+ //printf("gdb_stdio printf pstr1: 0x%0x strlen1: %d buf: %s\n", pstr1, strlen1, buf); -+ #endif -+ fputs(buf, stdout); -+ free(buf); -+ -+ break; -+ -+ case GDB_STDIO_FPRINTF: -+ stlink_read_mem32(sl, file_addr, 4); -+ file = (FILE*)read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, pstr1_addr, 4); -+ pstr1 = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, strlen1_addr, 4); -+ strlen1 = read_uint32(sl->q_buf, 0); -+ buf = (char*)malloc(strlen1+1); -+ assert(buf != NULL); -+ read_buffer(sl, pstr1, buf, strlen1); -+ buf[strlen1] = 0; -+ #ifdef DEBUG -+ //printf("gdb_stdio fprintf pstr1: 0x%0x strlen1: %d buf: %s file: 0x%x\n", pstr1, strlen1, buf, (unsigned int)file); -+ #endif -+ fputs(buf, file); -+ free(buf); -+ -+ break; -+ -+ case GDB_STDIO_FOPEN: -+ stlink_read_mem32(sl, pstr1_addr, 4); -+ pstr1 = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, strlen1_addr, 4); -+ strlen1 = read_uint32(sl->q_buf, 0); -+ assert(strlen1 < MAX_STR); -+ read_buffer(sl, pstr1, file_name, strlen1); -+ file_name[strlen1] = 0; -+ -+ stlink_read_mem32(sl, pstr2_addr, 4); -+ pstr2 = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, strlen2_addr, 4); -+ strlen2 = read_uint32(sl->q_buf, 0); -+ assert(strlen2 < MAX_STR); -+ read_buffer(sl, pstr2, mode, strlen2); -+ mode[strlen2] = 0; -+ -+ file = fopen(file_name, mode); -+ -+ ret = (int)file; -+ #ifdef DEBUG -+ printf("gdb_stdio fopen file_name: %s mode: %s file: 0x%x\n", file_name, mode, (unsigned int)file); -+ #endif -+ break; -+ -+ case GDB_STDIO_FCLOSE: -+ stlink_read_mem32(sl, file_addr, 4); -+ file = (FILE*)read_uint32(sl->q_buf, 0); -+ fclose(file); -+ -+ #ifdef DEBUG -+ printf("gdb_stdio fclose file: 0x%x\n", (unsigned int)file); -+ #endif -+ break; -+ -+ case GDB_STDIO_FWRITE: -+ stlink_read_mem32(sl, ptr_addr, 4); -+ ptr = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, size_addr, 4); -+ size = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, nmem_addr, 4); -+ nmem = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, file_addr, 4); -+ file = (FILE*)read_uint32(sl->q_buf, 0); -+ -+ buf = (char*)malloc(size*nmem); -+ assert(buf != NULL); -+ read_buffer(sl, ptr, buf, size*nmem); -+ ret = fwrite(buf, size, nmem, file); -+ free(buf); -+ #ifdef DEBUG -+ printf("gdb_stdio fwrite ptr: 0x%x size: %d nmem: %d file: 0x%x\n", -+ ptr, size, nmem, (unsigned int)file); -+ #endif -+ break; -+ -+ case GDB_STDIO_FREAD: -+ stlink_read_mem32(sl, ptr_addr, 4); -+ ptr = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, size_addr, 4); -+ size = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, nmem_addr, 4); -+ nmem = read_uint32(sl->q_buf, 0); -+ stlink_read_mem32(sl, file_addr, 4); -+ file = (FILE*)read_uint32(sl->q_buf, 0); -+ -+ buf = (char*)malloc(size*nmem); -+ assert(buf != NULL); -+ ret = fread(buf, size, nmem, file); -+ write_buffer(sl, ptr, buf, size*nmem); -+ free(buf); -+ -+ #ifdef DEBUG -+ printf("gdb_stdio fread ptr: 0x%x size: %d nmem: %d file: 0x%x\n", -+ ptr, size, nmem, (unsigned int)file); -+ #endif -+ break; -+ } -+ -+ if (func) { -+ memcpy(sl->q_buf, &ret, sizeof(int)); -+ stlink_write_mem32(sl, ret_addr, 4); -+ -+ func = 0; -+ memcpy(sl->q_buf, &func, sizeof(int)); -+ stlink_write_mem32(sl, func_addr, 4); -+ } -+} -+ -+ -+int serve(stlink_t *sl, int port, char *elf_filename) { - int sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock < 0) { - perror("socket"); -@@ -650,7 +844,33 @@ int serve(stlink_t *sl, int port) { - perror("listen"); - return 1; - } -- -+ -+ /* init for file I/O */ -+ -+ func_addr = ret_addr = pstr1_addr = pstr2_addr = strlen1_addr = strlen2_addr = 0; -+ file_addr = ptr_addr = size_addr = nmem_addr = 0; -+ -+ printf("elf_filename: %s----------------------------------\n", elf_filename); -+ if (*elf_filename != 0) { -+ int fd = elfsym_open(elf_filename); -+ if (fd == -1) -+ exit(0); -+ func_addr = elfsym_get_symbol_address(fd, "gdb_stdio_func"); -+ ret_addr = elfsym_get_symbol_address(fd, "gdb_stdio_ret"); -+ pstr1_addr = elfsym_get_symbol_address(fd, "gdb_stdio_pstr1"); -+ pstr2_addr = elfsym_get_symbol_address(fd, "gdb_stdio_pstr2"); -+ strlen1_addr = elfsym_get_symbol_address(fd, "gdb_stdio_strlen1"); -+ strlen2_addr = elfsym_get_symbol_address(fd, "gdb_stdio_strlen2"); -+ file_addr = elfsym_get_symbol_address(fd, "gdb_stdio_file"); -+ ptr_addr = elfsym_get_symbol_address(fd, "gdb_stdio_ptr"); -+ size_addr = elfsym_get_symbol_address(fd, "gdb_stdio_size"); -+ nmem_addr = elfsym_get_symbol_address(fd, "gdb_stdio_nmem"); -+ elfsym_close(fd); -+ #ifdef DEBUG -+ printf("func_addr: 0x%x\n", func_addr); -+ #endif -+ } -+ - start_again: - stlink_force_debug(sl); - stlink_reset(sl); -@@ -924,8 +1144,13 @@ start_again: - if(sl->core_stat == STLINK_CORE_HALTED) { - break; - } -+ -+ /* file I/O if enabled */ -+ -+ if (*elf_filename != 0) -+ fileio(sl); - -- usleep(100000); -+ usleep(10000); - } - - reply = strdup("S05"); // TRAP diff --git a/codec2-dev/stm32/stlink/elfsym.c b/codec2-dev/stm32/stlink/elfsym.c new file mode 100644 index 00000000..1a62981b --- /dev/null +++ b/codec2-dev/stm32/stlink/elfsym.c @@ -0,0 +1,145 @@ +/* + elfsym.c + + Read symbol adresses from a .elf file. + + Based on libelf-howto.c from: http://em386.blogspot.com + + Unit test with: + + gcc elfsym.c -o elfsym -D__UNITTEST__ -Wall -lelf + ./elfsym elf_file.elf +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "elfsym.h" + +#define ERR -1 + +int elfsym_open(char file[]) { + int fd; /* File Descriptor */ + char *base_ptr; /* ptr to our object in memory */ + struct stat elf_stats; /* fstat struct */ + + if((fd = open(file, O_RDWR)) == ERR) { + printf("couldnt open %s\n", file); + return ERR; + } + + if((fstat(fd, &elf_stats))) { + printf("could not fstat %s\n", file); + close(fd); + return ERR; + } + + if((base_ptr = (char *) malloc(elf_stats.st_size)) == NULL) { + fprintf(stderr, "could not malloc\n"); + close(fd); + return ERR; + } + + if((read(fd, base_ptr, elf_stats.st_size)) < elf_stats.st_size) { + fprintf(stderr, "could not read %s\n", file); + free(base_ptr); + close(fd); + return ERR; + } + + /* Check libelf version first */ + + if(elf_version(EV_CURRENT) == EV_NONE) { + fprintf(stderr, "WARNING Elf Library is out of date!\n"); + } + + free(base_ptr); + + return fd; +} + + +void elfsym_close(int fd) { + close(fd); +} + +unsigned int elfsym_get_symbol_address(int fd, char symbol_name[]) +{ + Elf_Scn *scn; /* Section Descriptor */ + Elf_Data *edata; /* Data Descriptor */ + GElf_Sym sym; /* Symbol */ + GElf_Shdr shdr; /* Section Header */ + Elf *elf; /* Our Elf pointer for libelf */ + unsigned int symbol_address; + int symbol_count; + int i; + + /* Iterate through section headers, stop when we find symbols, + and check for match */ + + elf = elf_begin(fd, ELF_C_READ, NULL); + if (elf == 0) { + fprintf(stderr, "could not elf_begin\n"); + } + symbol_address = 0; + scn = NULL; + + while((scn = elf_nextscn(elf, scn)) != 0) { + gelf_getshdr(scn, &shdr); + + // When we find a section header marked SHT_SYMTAB stop and get symbols + edata = NULL; + if(shdr.sh_type == SHT_SYMTAB) { + // edata points to our symbol table + edata = elf_getdata(scn, edata); + + // how many symbols are there? this number comes from the size of + // the section divided by the entry size + symbol_count = shdr.sh_size / shdr.sh_entsize; + + // loop through to grab all symbols + for(i = 0; i < symbol_count; i++) { + // libelf grabs the symbol data using gelf_getsym() + gelf_getsym(edata, i, &sym); + + if (strcmp(symbol_name, + elf_strptr(elf, shdr.sh_link, sym.st_name)) == 0) { + symbol_address = sym.st_value; + } + } + + } + } + + return symbol_address; +} + +#ifdef __UNITTEST__ + +int main(int argc, char *argv[]) +{ + int fd; + unsigned int flag_addr, ptr_addr, file_addr, len_addr; + + fd = elfsym_open(argv[1]); + flag_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_flag"); + ptr_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_ptr"); + file_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_file"); + len_addr = elfsym_get_symbol_address(fd, "syscalls_gdb_len"); + elfsym_close(fd); + + printf("flag_addr: 0x%x\n", flag_addr); + printf("ptr_addr: 0x%x\n", ptr_addr); + printf("file_addr: 0x%x\n", file_addr); + printf("len_addr: 0x%x\n", len_addr); + + return 0; +} + +#endif diff --git a/codec2-dev/stm32/stlink/elfsym.h b/codec2-dev/stm32/stlink/elfsym.h new file mode 100644 index 00000000..fcd287ab --- /dev/null +++ b/codec2-dev/stm32/stlink/elfsym.h @@ -0,0 +1,14 @@ +/* + elfsym.h + + Read symbol adresses from a .elf file. +*/ + +#ifndef __ELFSYM__ +#define __ELFSYM__ + +int elfsym_open(char file[]); +void elfsym_close(int fd); +unsigned int elfsym_get_symbol_address(int fd, char symbol_name[]); + +#endif diff --git a/codec2-dev/stm32/stlink/stlink.patch b/codec2-dev/stm32/stlink/stlink.patch new file mode 100644 index 00000000..74cf2401 --- /dev/null +++ b/codec2-dev/stm32/stlink/stlink.patch @@ -0,0 +1,428 @@ +diff --git Makefile.am Makefile.am +index a315dd7..7406216 100644 +--- Makefile.am ++++ Makefile.am +@@ -7,7 +7,7 @@ bin_PROGRAMS = st-flash st-util + noinst_LIBRARIES = libstlink.a + + st_flash_SOURCES = flash/main.c +-st_util_SOURCES = gdbserver/gdb-remote.c gdbserver/gdb-remote.h gdbserver/gdb-server.c mingw/mingw.c mingw/mingw.h ++st_util_SOURCES = gdbserver/gdb-remote.c gdbserver/gdb-remote.h gdbserver/gdb-server.c gdbserver/elfsym.c mingw/mingw.c mingw/mingw.h + + CFILES = \ + src/stlink-common.c \ +@@ -24,14 +24,14 @@ HFILES = \ + + libstlink_a_SOURCES = $(CFILES) $(HFILES) + +-libstlink_a_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 ++libstlink_a_CPPFLAGS = -std=gnu99 -Wall -Wextra -g + libstlink_a_LIBADD = $(LIBOBJS) + + st_flash_LDADD = libstlink.a +-st_flash_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw ++st_flash_CPPFLAGS = -std=gnu99 -Wall -Wextra -g -I$(top_srcdir)/src -I$(top_srcdir)/mingw + +-st_util_LDADD = libstlink.a +-st_util_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw ++st_util_LDADD = libstlink.a -lelf ++st_util_CPPFLAGS = -std=gnu99 -Wall -Wextra -g -I$(top_srcdir)/src -I$(top_srcdir)/mingw + + EXTRA_DIST = autogen.sh + +diff --git gdbserver/Makefile gdbserver/Makefile +index bd5c73d..6763388 100644 +--- gdbserver/Makefile ++++ gdbserver/Makefile +@@ -1,12 +1,11 @@ + PRG := st-util +-OBJS = gdb-remote.o gdb-server.o ++OBJS = gdb-remote.o gdb-server.o elfsym.o + + CFLAGS+=-g -Wall -Werror -std=gnu99 -I../src + LDFLAGS=-L.. -lstlink + + # libusb location +-LDFLAGS+=`pkg-config --libs libusb-1.0` +-CFLAGS+=`pkg-config --cflags libusb-1.0` ++LDFLAGS+=`pkg-config --libs libusb-1.0` -lelfCFLAGS+=`pkg-config --cflags libusb-1.0` + + all: $(PRG) + +diff --git gdbserver/gdb-server.c gdbserver/gdb-server.c +index f92fc05..e54d136 100644 +--- gdbserver/gdb-server.c ++++ gdbserver/gdb-server.c +@@ -1,11 +1,12 @@ + /* -*- tab-width:8 -*- */ +-#define DEBUG 0 ++//#define DEBUG 0 + /* + Copyright (C) 2011 Peter Zotov + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. + */ + ++#include + #include + #include + #include +@@ -20,14 +21,29 @@ + #include + #include + #endif ++#include ++#include ++#include + + #include + + #include "gdb-remote.h" ++#include "elfsym.h" + + #define DEFAULT_LOGGING_LEVEL 50 + #define DEFAULT_GDB_LISTEN_PORT 4242 + ++/* stdio command codes from target */ ++ ++#define GDB_STDIO_PRINTF 1 ++#define GDB_STDIO_FOPEN 2 ++#define GDB_STDIO_FCLOSE 3 ++#define GDB_STDIO_FWRITE 4 ++#define GDB_STDIO_FREAD 5 ++#define GDB_STDIO_FPRINTF 6 ++ ++#define MAX_STR 256 ++ + #define STRINGIFY_inner(name) #name + #define STRINGIFY(name) STRINGIFY_inner(name) + +@@ -46,11 +62,12 @@ typedef struct _st_state_t { + // "/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTE531X6-if00-port0" is only 58 chars + char devicename[100]; + int logging_level; +- int listen_port; ++ int listen_port; ++ char elf_filename[255]; + } st_state_t; + + +-int serve(stlink_t *sl, int port); ++int serve(stlink_t *sl, int port, char *elf_filename); + char* make_memory_map(stlink_t *sl); + + +@@ -76,13 +93,14 @@ int parse_options(int argc, char** argv, st_state_t *st) { + " -p 4242, --listen_port=1234\n" + "\t\t\tSet the gdb server listen port. " + "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n" ++ " -f \tenable File I/O of target executable elf_filename" + ; + + + int option_index = 0; + int c; + int q; +- while ((c = getopt_long(argc, argv, "hv::d:s:1p:", long_options, &option_index)) != -1) { ++ while ((c = getopt_long(argc, argv, "hv::d:s:1p:1f:", long_options, &option_index)) != -1) { + switch (c) { + case 0: + printf("XXXXX Shouldn't really normally come here, only if there's no corresponding option\n"); +@@ -110,25 +128,29 @@ int parse_options(int argc, char** argv, st_state_t *st) { + strcpy(st->devicename, optarg); + } + break; +- case '1': +- st->stlink_version = 1; +- break; +- case 's': +- sscanf(optarg, "%i", &q); +- if (q < 0 || q > 2) { +- fprintf(stderr, "stlink version %d unknown!\n", q); +- exit(EXIT_FAILURE); +- } +- st->stlink_version = q; +- break; +- case 'p': +- sscanf(optarg, "%i", &q); +- if (q < 0) { +- fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); +- exit(EXIT_FAILURE); +- } +- st->listen_port = q; +- break; ++ case '1': ++ st->stlink_version = 1; ++ break; ++ case 's': ++ sscanf(optarg, "%i", &q); ++ if (q < 0 || q > 2) { ++ fprintf(stderr, "stlink version %d unknown!\n", q); ++ exit(EXIT_FAILURE); ++ } ++ st->stlink_version = q; ++ break; ++ case 'p': ++ sscanf(optarg, "%i", &q); ++ if (q < 0) { ++ fprintf(stderr, "Can't use a negative port to listen on: %d\n", q); ++ exit(EXIT_FAILURE); ++ } ++ st->listen_port = q; ++ break; ++ case 'f': ++ sscanf(optarg, "%s", st->elf_filename); ++ printf("-f arg; %s\n", st->elf_filename); ++ break; + } + } + +@@ -162,7 +184,7 @@ int main(int argc, char** argv) { + sl = stlink_v1_open(state.logging_level); + if(sl == NULL) return 1; + break; +- } ++ } + + printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); + +@@ -177,7 +199,7 @@ int main(int argc, char** argv) { + } + #endif + +- while(serve(sl, state.listen_port) == 0); ++ while(serve(sl, state.listen_port, state.elf_filename) == 0); + + #ifdef __MINGW32__ + winsock_error: +@@ -625,7 +647,179 @@ error: + return error; + } + +-int serve(stlink_t *sl, int port) { ++static unsigned int func_addr, ret_addr, pstr1_addr, pstr2_addr; ++static unsigned int strlen1_addr, strlen2_addr, file_addr, ptr_addr; ++static unsigned int size_addr, nmem_addr; ++ ++static void write_buffer(stlink_t *sl, int target_addr, char* buf, size_t size) { ++ /* write the buffer right after the loader */ ++ size_t chunk = size & ~0x3; ++ size_t rem = size & 0x3; ++ ++ if (chunk) { ++ memcpy(sl->q_buf, buf, chunk); ++ stlink_write_mem32(sl, target_addr, chunk); ++ } ++ if (rem) { ++ memcpy(sl->q_buf, buf+chunk, rem); ++ stlink_write_mem8(sl, target_addr+chunk, rem); ++ } ++} ++ ++static void read_buffer(stlink_t *sl, int target_addr, char* buf, size_t size) { ++ unsigned adj_start = target_addr % 4; ++ unsigned count_rnd = (size + adj_start + 4 - 1) / 4 * 4; ++ size_t i; ++ ++ stlink_read_mem32(sl, target_addr - adj_start, count_rnd); ++ ++ for(i=0; iq_buf[i + adj_start]; ++} ++ ++static void fileio(stlink_t *sl) ++{ ++ int func, pstr1, pstr2, strlen1, strlen2, ptr, size, nmem; ++ int ret = 0; ++ FILE *file; ++ char file_name[MAX_STR]; ++ char mode[MAX_STR]; ++ char *buf; ++ ++ stlink_read_mem32(sl, func_addr, 4); ++ func = read_uint32(sl->q_buf, 0); ++ ++ /* func != 0 means target has requested a system call */ ++ ++ switch(func) { ++ ++ case GDB_STDIO_PRINTF: ++ stlink_read_mem32(sl, pstr1_addr, 4); ++ pstr1 = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, strlen1_addr, 4); ++ strlen1 = read_uint32(sl->q_buf, 0); ++ buf = (char*)malloc(strlen1+1); ++ assert(buf != NULL); ++ read_buffer(sl, pstr1, buf, strlen1); ++ buf[strlen1] = 0; ++ #ifdef DEBUG ++ //printf("gdb_stdio printf pstr1: 0x%0x strlen1: %d buf: %s\n", pstr1, strlen1, buf); ++ #endif ++ fputs(buf, stdout); ++ free(buf); ++ ++ break; ++ ++ case GDB_STDIO_FPRINTF: ++ stlink_read_mem32(sl, file_addr, 4); ++ file = (FILE*)read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, pstr1_addr, 4); ++ pstr1 = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, strlen1_addr, 4); ++ strlen1 = read_uint32(sl->q_buf, 0); ++ buf = (char*)malloc(strlen1+1); ++ assert(buf != NULL); ++ read_buffer(sl, pstr1, buf, strlen1); ++ buf[strlen1] = 0; ++ #ifdef DEBUG ++ //printf("gdb_stdio fprintf pstr1: 0x%0x strlen1: %d buf: %s file: 0x%x\n", pstr1, strlen1, buf, (unsigned int)file); ++ #endif ++ fputs(buf, file); ++ free(buf); ++ ++ break; ++ ++ case GDB_STDIO_FOPEN: ++ stlink_read_mem32(sl, pstr1_addr, 4); ++ pstr1 = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, strlen1_addr, 4); ++ strlen1 = read_uint32(sl->q_buf, 0); ++ assert(strlen1 < MAX_STR); ++ read_buffer(sl, pstr1, file_name, strlen1); ++ file_name[strlen1] = 0; ++ ++ stlink_read_mem32(sl, pstr2_addr, 4); ++ pstr2 = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, strlen2_addr, 4); ++ strlen2 = read_uint32(sl->q_buf, 0); ++ assert(strlen2 < MAX_STR); ++ read_buffer(sl, pstr2, mode, strlen2); ++ mode[strlen2] = 0; ++ ++ file = fopen(file_name, mode); ++ ++ ret = (int)file; ++ #ifdef DEBUG ++ printf("gdb_stdio fopen file_name: %s mode: %s file: 0x%x\n", file_name, mode, (unsigned int)file); ++ #endif ++ break; ++ ++ case GDB_STDIO_FCLOSE: ++ stlink_read_mem32(sl, file_addr, 4); ++ file = (FILE*)read_uint32(sl->q_buf, 0); ++ fclose(file); ++ ++ #ifdef DEBUG ++ printf("gdb_stdio fclose file: 0x%x\n", (unsigned int)file); ++ #endif ++ break; ++ ++ case GDB_STDIO_FWRITE: ++ stlink_read_mem32(sl, ptr_addr, 4); ++ ptr = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, size_addr, 4); ++ size = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, nmem_addr, 4); ++ nmem = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, file_addr, 4); ++ file = (FILE*)read_uint32(sl->q_buf, 0); ++ ++ buf = (char*)malloc(size*nmem); ++ assert(buf != NULL); ++ read_buffer(sl, ptr, buf, size*nmem); ++ ret = fwrite(buf, size, nmem, file); ++ free(buf); ++ #ifdef DEBUG ++ printf("gdb_stdio fwrite ptr: 0x%x size: %d nmem: %d file: 0x%x\n", ++ ptr, size, nmem, (unsigned int)file); ++ #endif ++ break; ++ ++ case GDB_STDIO_FREAD: ++ stlink_read_mem32(sl, ptr_addr, 4); ++ ptr = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, size_addr, 4); ++ size = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, nmem_addr, 4); ++ nmem = read_uint32(sl->q_buf, 0); ++ stlink_read_mem32(sl, file_addr, 4); ++ file = (FILE*)read_uint32(sl->q_buf, 0); ++ ++ buf = (char*)malloc(size*nmem); ++ assert(buf != NULL); ++ ret = fread(buf, size, nmem, file); ++ write_buffer(sl, ptr, buf, size*nmem); ++ free(buf); ++ ++ #ifdef DEBUG ++ printf("gdb_stdio fread ptr: 0x%x size: %d nmem: %d file: 0x%x\n", ++ ptr, size, nmem, (unsigned int)file); ++ #endif ++ break; ++ } ++ ++ if (func) { ++ memcpy(sl->q_buf, &ret, sizeof(int)); ++ stlink_write_mem32(sl, ret_addr, 4); ++ ++ func = 0; ++ memcpy(sl->q_buf, &func, sizeof(int)); ++ stlink_write_mem32(sl, func_addr, 4); ++ } ++} ++ ++ ++int serve(stlink_t *sl, int port, char *elf_filename) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 0) { + perror("socket"); +@@ -650,7 +844,33 @@ int serve(stlink_t *sl, int port) { + perror("listen"); + return 1; + } +- ++ ++ /* init for file I/O */ ++ ++ func_addr = ret_addr = pstr1_addr = pstr2_addr = strlen1_addr = strlen2_addr = 0; ++ file_addr = ptr_addr = size_addr = nmem_addr = 0; ++ ++ printf("elf_filename: %s----------------------------------\n", elf_filename); ++ if (*elf_filename != 0) { ++ int fd = elfsym_open(elf_filename); ++ if (fd == -1) ++ exit(0); ++ func_addr = elfsym_get_symbol_address(fd, "gdb_stdio_func"); ++ ret_addr = elfsym_get_symbol_address(fd, "gdb_stdio_ret"); ++ pstr1_addr = elfsym_get_symbol_address(fd, "gdb_stdio_pstr1"); ++ pstr2_addr = elfsym_get_symbol_address(fd, "gdb_stdio_pstr2"); ++ strlen1_addr = elfsym_get_symbol_address(fd, "gdb_stdio_strlen1"); ++ strlen2_addr = elfsym_get_symbol_address(fd, "gdb_stdio_strlen2"); ++ file_addr = elfsym_get_symbol_address(fd, "gdb_stdio_file"); ++ ptr_addr = elfsym_get_symbol_address(fd, "gdb_stdio_ptr"); ++ size_addr = elfsym_get_symbol_address(fd, "gdb_stdio_size"); ++ nmem_addr = elfsym_get_symbol_address(fd, "gdb_stdio_nmem"); ++ elfsym_close(fd); ++ #ifdef DEBUG ++ printf("func_addr: 0x%x\n", func_addr); ++ #endif ++ } ++ + start_again: + stlink_force_debug(sl); + stlink_reset(sl); +@@ -924,8 +1144,13 @@ start_again: + if(sl->core_stat == STLINK_CORE_HALTED) { + break; + } ++ ++ /* file I/O if enabled */ ++ ++ if (*elf_filename != 0) ++ fileio(sl); + +- usleep(100000); ++ usleep(10000); + } + + reply = strdup("S05"); // TRAP