new semihosting commands

This commit is contained in:
Koen De Vleeschauwer 2020-04-15 19:23:44 +02:00 committed by UweBonnes
parent ada17ada23
commit 8851504a41
5 changed files with 181 additions and 11 deletions

View File

@ -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");

View File

@ -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 {

View File

@ -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;

View File

@ -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)

View File

@ -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;