some more stlink files
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 22 May 2013 12:55:26 +0000 (12:55 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 22 May 2013 12:55:26 +0000 (12:55 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1262 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/stm32/README.txt
codec2-dev/stm32/stlink.patch [deleted file]
codec2-dev/stm32/stlink/elfsym.c [new file with mode: 0644]
codec2-dev/stm32/stlink/elfsym.h [new file with mode: 0644]
codec2-dev/stm32/stlink/stlink.patch [new file with mode: 0644]

index bc9ad743149c76f49953ffaf6a9b26287c76b0fb..eac2d04b0379f9e6837a896a5113059ea194a040 100644 (file)
@@ -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 (file)
index 74cf240..0000000
+++ /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 <whitequark@whitequark.org>
-  Use of this source code is governed by a BSD-style
-  license that can be found in the LICENSE file.
- */
-+#include <assert.h>
- #include <getopt.h>
- #include <stdio.h>
- #include <string.h>
-@@ -20,14 +21,29 @@
- #include <arpa/inet.h>
- #include <signal.h>
- #endif
-+#include <sys/stat.h>
-+#include <unistd.h>
-+#include <fcntl.h>
- #include <stlink-common.h>
- #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 <elf_filename>\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; i<size; i++)
-+        buf[i] = sl->q_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;
-       }
--\r
-+
-+        /* 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 (file)
index 0000000..1a62981
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <gelf.h>
+#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 (file)
index 0000000..fcd287a
--- /dev/null
@@ -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 (file)
index 0000000..74cf240
--- /dev/null
@@ -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 <whitequark@whitequark.org>
+  Use of this source code is governed by a BSD-style
+  license that can be found in the LICENSE file.
+ */
++#include <assert.h>
+ #include <getopt.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -20,14 +21,29 @@
+ #include <arpa/inet.h>
+ #include <signal.h>
+ #endif
++#include <sys/stat.h>
++#include <unistd.h>
++#include <fcntl.h>
+ #include <stlink-common.h>
+ #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 <elf_filename>\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; i<size; i++)
++        buf[i] = sl->q_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;
+       }
+-\r
++
++        /* 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