new semihosting commands
This commit is contained in:
parent
ada17ada23
commit
8851504a41
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "general.h"
|
||||
#include "ctype.h"
|
||||
#include "hex_utils.h"
|
||||
#include "gdb_if.h"
|
||||
#include "gdb_packet.h"
|
||||
|
@ -429,9 +430,37 @@ handle_v_packet(char *packet, int plen)
|
|||
else
|
||||
gdb_putpacketz("E01");
|
||||
|
||||
} else if (!strcmp(packet, "vRun;")) {
|
||||
} else if (!strncmp(packet, "vRun", 4)) {
|
||||
/* Parse command line for get_cmdline semihosting call */
|
||||
char cmdline[83];
|
||||
char *pbuf = cmdline;
|
||||
char *tok = packet + 4;
|
||||
if (*tok == ';') tok++;
|
||||
*cmdline='\0';
|
||||
while(*tok != '\0') {
|
||||
if(strlen(cmdline)+3 >= sizeof(cmdline)) break;
|
||||
if (*tok == ';') {
|
||||
*pbuf++=' ';
|
||||
*pbuf='\0';
|
||||
tok++;
|
||||
continue;
|
||||
}
|
||||
if (isxdigit(*tok) && isxdigit(*(tok+1))) {
|
||||
unhexify(pbuf, tok, 2);
|
||||
if ((*pbuf == ' ') || (*pbuf == '\\')) {
|
||||
*(pbuf+1)=*pbuf;
|
||||
*pbuf++='\\';
|
||||
}
|
||||
pbuf++;
|
||||
tok+=2;
|
||||
*pbuf='\0';
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Run target program. For us (embedded) this means reset. */
|
||||
if(cur_target) {
|
||||
target_set_cmdline(cur_target, cmdline);
|
||||
target_reset(cur_target);
|
||||
gdb_putpacketz("T05");
|
||||
} else if(last_target) {
|
||||
|
@ -440,6 +469,7 @@ handle_v_packet(char *packet, int plen)
|
|||
|
||||
/* If we were able to attach to the target again */
|
||||
if (cur_target) {
|
||||
target_set_cmdline(cur_target, cmdline);
|
||||
target_reset(cur_target);
|
||||
gdb_putpacketz("T05");
|
||||
} else gdb_putpacketz("E01");
|
||||
|
|
|
@ -80,6 +80,7 @@ void target_reset(target *t);
|
|||
void target_halt_request(target *t);
|
||||
enum target_halt_reason target_halt_poll(target *t, target_addr *watch);
|
||||
void target_halt_resume(target *t, bool step);
|
||||
void target_set_cmdline(target *t, char *cmdline);
|
||||
|
||||
/* Break-/watchpoint functions */
|
||||
enum target_breakwatch {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
*
|
||||
* Copyright (C) 2012 Black Sphere Technologies Ltd.
|
||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
* and Koen De Vleeschauwer.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under tSchreibe Objekte: 100% (21/21), 3.20 KiB | 3.20 MiB/s, Fertig.
|
||||
he terms of the GNU General Public License as published by
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
|
@ -1009,11 +1009,14 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
|||
#endif
|
||||
|
||||
/* Semihosting support */
|
||||
/* ARM Semihosting syscall numbers, from ARM doc DUI0471C, Chapter 8 */
|
||||
#define SYS_CLOSE 0x02
|
||||
/* ARM Semihosting syscall numbers, from "Semihosting for AArch32 and AArch64 Version 3.0" */
|
||||
|
||||
#define SYS_CLOCK 0x10
|
||||
#define SYS_CLOSE 0x02
|
||||
#define SYS_ELAPSED 0x30
|
||||
#define SYS_ERRNO 0x13
|
||||
#define SYS_EXIT 0x18
|
||||
#define SYS_EXIT_EXTENDED 0x20
|
||||
#define SYS_FLEN 0x0C
|
||||
#define SYS_GET_CMDLINE 0x15
|
||||
#define SYS_HEAPINFO 0x16
|
||||
|
@ -1033,6 +1036,28 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
|||
#define SYS_WRITEC 0x03
|
||||
#define SYS_WRITE0 0x04
|
||||
|
||||
#if !defined(PC_HOSTED)
|
||||
/* probe memory access functions */
|
||||
static void probe_mem_read(target *t __attribute__((unused)), void *probe_dest, target_addr target_src, size_t len)
|
||||
{
|
||||
uint8_t *dst = (uint8_t *)probe_dest;
|
||||
uint8_t *src = (uint8_t *)target_src;
|
||||
|
||||
DEBUG("probe_mem_read\n");
|
||||
while (len--) *dst++=*src++;
|
||||
return;
|
||||
}
|
||||
|
||||
static void probe_mem_write(target *t __attribute__((unused)), target_addr target_dest, const void *probe_src, size_t len)
|
||||
{
|
||||
uint8_t *dst = (uint8_t *)target_dest;
|
||||
uint8_t *src = (uint8_t *)probe_src;
|
||||
|
||||
DEBUG("probe_mem_write\n");
|
||||
while (len--) *dst++=*src++;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
static int cortexm_hostio_request(target *t)
|
||||
{
|
||||
uint32_t arm_regs[t->regs_size];
|
||||
|
@ -1073,6 +1098,7 @@ static int cortexm_hostio_request(target *t)
|
|||
ret++;
|
||||
break;
|
||||
}
|
||||
/* FIXME handle requests for special filename ':semihosting-features' */
|
||||
|
||||
ret = tc_open(t, params[0], params[2] + 1, pflag, 0644);
|
||||
if (ret != -1)
|
||||
|
@ -1093,8 +1119,24 @@ static int cortexm_hostio_request(target *t)
|
|||
ret = params[2] - ret;
|
||||
break;
|
||||
case SYS_WRITEC: /* writec */
|
||||
ret = tc_write(t, 2, arm_regs[1], 1);
|
||||
ret = tc_write(t, STDERR_FILENO, arm_regs[1], 1);
|
||||
break;
|
||||
case SYS_WRITE0:{ /* write0 */
|
||||
ret = -1;
|
||||
target_addr str_begin = arm_regs[1];
|
||||
target_addr str_end = str_begin;
|
||||
while (target_mem_read8(t, str_end) != 0) {
|
||||
if (target_check_error(t)) break;
|
||||
str_end++;
|
||||
}
|
||||
int len = str_end - str_begin;
|
||||
if (len != 0) {
|
||||
int rc = tc_write(t, STDERR_FILENO, str_begin, len);
|
||||
if (rc != len) break;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
case SYS_ISTTY: /* isatty */
|
||||
ret = tc_isatty(t, params[0] - 1);
|
||||
break;
|
||||
|
@ -1112,17 +1154,102 @@ static int cortexm_hostio_request(target *t)
|
|||
ret = tc_system(t, params[0] - 1, params[1] + 1);
|
||||
break;
|
||||
|
||||
case SYS_FLEN: /* Not supported, fake success */
|
||||
t->tc->errno_ = 0;
|
||||
break;
|
||||
case SYS_FLEN:
|
||||
#if defined(PC_HOSTED)
|
||||
t->tc->errno_ = 0;
|
||||
break;
|
||||
#else
|
||||
{ /* file length */
|
||||
ret = -1;
|
||||
uint32_t fio_stat[16]; /* same size as fio_stat in gdb/include/gdb/fileio.h */
|
||||
//DEBUG("SYS_FLEN fio_stat addr %p\n", fio_stat);
|
||||
void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len);
|
||||
void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len);
|
||||
saved_mem_read = t->mem_read;
|
||||
saved_mem_write = t->mem_write;
|
||||
t->mem_read = probe_mem_read;
|
||||
t->mem_write = probe_mem_write;
|
||||
int rc = tc_fstat(t, params[0] - 1, (target_addr)fio_stat); /* write fstat() result in fio_stat[] */
|
||||
t->mem_read = saved_mem_read;
|
||||
t->mem_write = saved_mem_write;
|
||||
if (rc) break; /* tc_fstat() failed */
|
||||
uint32_t fst_size_msw = fio_stat[7]; /* most significant 32 bits of fst_size in fio_stat */
|
||||
uint32_t fst_size_lsw = fio_stat[8]; /* least significant 32 bits of fst_size in fio_stat */
|
||||
if (fst_size_msw != 0) break; /* file size too large for uint32_t return type */
|
||||
ret = __builtin_bswap32(fst_size_lsw); /* convert from bigendian to target order */
|
||||
break;
|
||||
}
|
||||
|
||||
case SYS_TIME: { /* gettimeofday */
|
||||
ret = -1;
|
||||
uint32_t fio_timeval[3]; /* same size as fio_timeval in gdb/include/gdb/fileio.h */
|
||||
//DEBUG("SYS_TIME fio_timeval addr %p\n", fio_timeval);
|
||||
void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len);
|
||||
void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len);
|
||||
saved_mem_read = t->mem_read;
|
||||
saved_mem_write = t->mem_write;
|
||||
t->mem_read = probe_mem_read;
|
||||
t->mem_write = probe_mem_write;
|
||||
int rc = tc_gettimeofday(t, (target_addr) fio_timeval, (target_addr) NULL); /* write gettimeofday() result in fio_timeval[] */
|
||||
t->mem_read = saved_mem_read;
|
||||
t->mem_write = saved_mem_write;
|
||||
if (rc) break; /* tc_gettimeofday() failed */
|
||||
uint32_t ftv_sec = fio_timeval[0]; /* time in seconds, first field in fio_timeval */
|
||||
ret = __builtin_bswap32(ftv_sec); /* convert from bigendian to target order */
|
||||
break;
|
||||
}
|
||||
|
||||
case SYS_READC: { /* readc */
|
||||
uint8_t ch;
|
||||
//DEBUG("SYS_READC ch addr %p\n", &ch);
|
||||
void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len);
|
||||
void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len);
|
||||
saved_mem_read = t->mem_read;
|
||||
saved_mem_write = t->mem_write;
|
||||
t->mem_read = probe_mem_read;
|
||||
t->mem_write = probe_mem_write;
|
||||
int rc = tc_read(t, params[0] - 1, (target_addr) &ch, 1); /* read a character in ch */
|
||||
t->mem_read = saved_mem_read;
|
||||
t->mem_write = saved_mem_write;
|
||||
if (rc == 1) ret = ch;
|
||||
else ret = -1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case SYS_ERRNO: /* Return last errno from GDB */
|
||||
ret = t->tc->errno_;
|
||||
break;
|
||||
|
||||
case SYS_TIME: /* gettimeofday */
|
||||
/* FIXME How do we use gdb's gettimeofday? */
|
||||
case SYS_EXIT: /* _exit() */
|
||||
tc_printf(t, "_exit(0x%x)\n", params[0]);
|
||||
target_halt_resume(t, 1);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case SYS_GET_CMDLINE: { /* get_cmdline */
|
||||
uint32_t retval[2];
|
||||
ret = -1;
|
||||
target_addr buf_ptr = params[0];
|
||||
target_addr buf_len = params[1];
|
||||
if (strlen(t->cmdline)+1 > buf_len) break;
|
||||
if(target_mem_write(t, buf_ptr, t->cmdline, strlen(t->cmdline)+1)) break;
|
||||
retval[0] = buf_ptr;
|
||||
retval[1] = strlen(t->cmdline)+1;
|
||||
if(target_mem_write(t, arm_regs[1], retval, sizeof(retval))) break;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// not implemented yet:
|
||||
case SYS_HEAPINFO: /* heapinfo */
|
||||
case SYS_CLOCK: /* clock */
|
||||
case SYS_ELAPSED: /* elapsed */
|
||||
case SYS_ISERROR: /* iserror */
|
||||
case SYS_TICKFREQ: /* tickfreq */
|
||||
case SYS_TMPNAM: /* tmpnam */
|
||||
ret = -1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
arm_regs[0] = ret;
|
||||
|
|
|
@ -401,6 +401,15 @@ enum target_halt_reason target_halt_poll(target *t, target_addr *watch)
|
|||
|
||||
void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); }
|
||||
|
||||
/* Command line for semihosting get_cmdline */
|
||||
void target_set_cmdline(target *t, char *cmdline) {
|
||||
uint32_t len_dst;
|
||||
len_dst = sizeof(t->cmdline)-1;
|
||||
strncpy(t->cmdline, cmdline, len_dst -1);
|
||||
t->cmdline[strlen(t->cmdline)]='\0';
|
||||
DEBUG("cmdline: >%s<\n", t->cmdline);
|
||||
}
|
||||
|
||||
/* Break-/watchpoint functions */
|
||||
int target_breakwatch_set(target *t,
|
||||
enum target_breakwatch type, target_addr addr, size_t len)
|
||||
|
|
|
@ -72,6 +72,8 @@ struct breakwatch {
|
|||
uint32_t reserved[4]; /* for use by the implementing driver */
|
||||
};
|
||||
|
||||
#define MAX_CMDLINE 81
|
||||
|
||||
struct target_s {
|
||||
bool attached;
|
||||
struct target_controller *tc;
|
||||
|
@ -118,6 +120,7 @@ struct target_s {
|
|||
/* Other stuff */
|
||||
const char *driver;
|
||||
const char *core;
|
||||
char cmdline[MAX_CMDLINE];
|
||||
struct target_command_s *commands;
|
||||
|
||||
struct target_s *next;
|
||||
|
|
Loading…
Reference in New Issue