mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2025-07-06 12:16:37 +02:00
gdb: provide [fxsdk gdb] wrapper
This commit is contained in:
parent
056ce41c9e
commit
e847ad3f6e
2 changed files with 126 additions and 12 deletions
|
@ -51,6 +51,11 @@ ${R}fxsdk${n} (${R}send${n}|${R}send-fx${n}|${R}send-cg${n})
|
||||||
externally) for the fx-9860G, and fxlink for the fx-CG. For the G-III series,
|
externally) for the fx-9860G, and fxlink for the fx-CG. For the G-III series,
|
||||||
call fxlink directly instead of this command.
|
call fxlink directly instead of this command.
|
||||||
|
|
||||||
|
${R}fxsdk${n} ${R}gdb${n} [${g}<OPTIONS>${n}...] [${R}--${n} ${g}<GDB OPTIONS>${n}...]
|
||||||
|
Starts the GDB bridge and GDB itself. In general, you'll want at least one
|
||||||
|
GDB option--the path to the executable file to debug.
|
||||||
|
With --bridge-only, don't start GDB and instead enable bridge logs.
|
||||||
|
|
||||||
${R}fxsdk${n} ${R}path${n} (${R}sysroot${n}|${R}include${n}|${R}lib${n})
|
${R}fxsdk${n} ${R}path${n} (${R}sysroot${n}|${R}include${n}|${R}lib${n})
|
||||||
Prints commonly-used paths in the SuperH sysroot:
|
Prints commonly-used paths in the SuperH sysroot:
|
||||||
${R}sysroot${n} The root folder of the SuperH toolchain and libraries
|
${R}sysroot${n} The root folder of the SuperH toolchain and libraries
|
||||||
|
@ -335,6 +340,8 @@ case "$1" in
|
||||||
fxsdk_send_cg;;
|
fxsdk_send_cg;;
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
|
"gdb")
|
||||||
|
fxsdk-gdb-bridge "${@:2}";;
|
||||||
"path")
|
"path")
|
||||||
fxsdk_path "${@:2}";;
|
fxsdk_path "${@:2}";;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
|
||||||
|
@ -50,8 +53,8 @@ static struct fxlink_device *setup_calc(libusb_context *context, bool nostart)
|
||||||
struct fxlink_message *msg = fxlink_device_finish_bulk_IN(fdev);
|
struct fxlink_message *msg = fxlink_device_finish_bulk_IN(fdev);
|
||||||
if(!msg)
|
if(!msg)
|
||||||
continue;
|
continue;
|
||||||
|
hlog("gdb");
|
||||||
if(fxlink_message_is_apptype(msg, "gdb", "start")) {
|
if(fxlink_message_is_apptype(msg, "gdb", "start")) {
|
||||||
hlog("gdb");
|
|
||||||
log_("got start message\n");
|
log_("got start message\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +75,8 @@ static int setup_socket(char const *listen_path)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlink(listen_path);
|
||||||
|
|
||||||
struct sockaddr_un listen_address = {
|
struct sockaddr_un listen_address = {
|
||||||
.sun_family = AF_UNIX,
|
.sun_family = AF_UNIX,
|
||||||
.sun_path = {0},
|
.sun_path = {0},
|
||||||
|
@ -92,6 +97,58 @@ static int setup_socket(char const *listen_path)
|
||||||
|
|
||||||
hlog("socket");
|
hlog("socket");
|
||||||
log_("waiting for client on \"%s\"...\n", listen_address.sun_path);
|
log_("waiting for client on \"%s\"...\n", listen_address.sun_path);
|
||||||
|
|
||||||
|
return listen_socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int volatile gdb_terminated_flag = 0;
|
||||||
|
static int volatile interrupted_flag = 0;
|
||||||
|
|
||||||
|
void SIGINT_SIGCHLD_handler(int signal)
|
||||||
|
{
|
||||||
|
if(signal == SIGCHLD)
|
||||||
|
gdb_terminated_flag = 1;
|
||||||
|
else
|
||||||
|
interrupted_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pid_t fork_gdb(char **user_argv, char const *socket_path)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
while(user_argv[n])
|
||||||
|
n++;
|
||||||
|
|
||||||
|
char target_command[256];
|
||||||
|
sprintf(target_command, "target remote %s", socket_path);
|
||||||
|
|
||||||
|
char **argv = malloc((n + 5) * sizeof *argv);
|
||||||
|
argv[0] = "sh-elf-gdb";
|
||||||
|
argv[1] = "-q";
|
||||||
|
argv[2] = "-ex";
|
||||||
|
argv[3] = target_command;
|
||||||
|
memcpy(argv+4, user_argv, (n+1) * sizeof *argv);
|
||||||
|
|
||||||
|
struct sigaction action = {
|
||||||
|
.sa_handler = SIGINT_SIGCHLD_handler,
|
||||||
|
};
|
||||||
|
sigaction(SIGCHLD, &action, NULL);
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
|
||||||
|
/* Child - execvp() only returns if there is an error */
|
||||||
|
if(pid == 0) {
|
||||||
|
execvp("sh-elf-gdb", argv);
|
||||||
|
perror("execvp");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* Parent */
|
||||||
|
if(pid == -1)
|
||||||
|
perror("fork");
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int accept_gdb(int listen_socket)
|
||||||
|
{
|
||||||
int client_socket = accept(listen_socket, NULL, NULL);
|
int client_socket = accept(listen_socket, NULL, NULL);
|
||||||
if(client_socket < 0) {
|
if(client_socket < 0) {
|
||||||
close(listen_socket);
|
close(listen_socket);
|
||||||
|
@ -102,17 +159,42 @@ static int setup_socket(char const *listen_path)
|
||||||
return client_socket;
|
return client_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
struct options {
|
||||||
|
bool bridge_only;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Parse options, returns positional arguments to forward to gdb. */
|
||||||
|
static char **parse_argv(int argc, char **argv, struct options *opts)
|
||||||
|
{
|
||||||
|
int bridge_only = 0;
|
||||||
|
struct option longs[] = {
|
||||||
|
{ "bridge-only", no_argument, &bridge_only, 1 },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
getopt_long(argc, argv, "", longs, NULL);
|
||||||
|
|
||||||
|
opts->bridge_only = (bridge_only != 0);
|
||||||
|
return argv + optind + (argv[optind] && !strcmp(argv[optind], "--"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void noop_log_handler(int display_fmt, char const *str)
|
||||||
|
{
|
||||||
|
(void)display_fmt;
|
||||||
|
(void)str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
libusb_context *context = NULL;
|
libusb_context *context = NULL;
|
||||||
struct fxlink_device *fdev = NULL;
|
struct fxlink_device *fdev = NULL;
|
||||||
struct fxlink_pollfds fxlink_polled_fds = { 0 };
|
struct fxlink_pollfds fxlink_polled_fds = { 0 };
|
||||||
|
char socket_path[256] = { 0 };
|
||||||
|
pid_t gdb_pid = -1;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
if(argc != 2) {
|
struct options opts;
|
||||||
elog("Usage : %s [listen path]\n", argv[0]);
|
char **gdb_argv = parse_argv(argc, argv, &opts);
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = libusb_init(&context);
|
int err = libusb_init(&context);
|
||||||
if(err != 0) {
|
if(err != 0) {
|
||||||
|
@ -124,17 +206,37 @@ int main(int argc, char *argv[])
|
||||||
if(!fdev)
|
if(!fdev)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
int client_socket = setup_socket(argv[1]);
|
sprintf(socket_path, "/tmp/fxsdk-gdb-bridge-%03d-%03d.socket",
|
||||||
|
fdev->busNumber, fdev->deviceAddress);
|
||||||
|
|
||||||
|
int listen_socket = setup_socket(socket_path);
|
||||||
|
if(listen_socket < 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if(!opts.bridge_only) {
|
||||||
|
gdb_pid = fork_gdb(gdb_argv, socket_path);
|
||||||
|
if(gdb_pid == -1)
|
||||||
|
goto end;
|
||||||
|
/* Cut fxlink logs to not mix in with gdb's output */
|
||||||
|
fxlink_log_set_handler(noop_log_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
int client_socket = accept_gdb(listen_socket);
|
||||||
if(client_socket < 0)
|
if(client_socket < 0)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
struct sigaction action = {
|
||||||
|
.sa_handler = SIGINT_SIGCHLD_handler,
|
||||||
|
};
|
||||||
|
sigaction(SIGINT, &action, NULL);
|
||||||
|
|
||||||
/* Track libusb fds as an indirect way to watch the calculator itself */
|
/* Track libusb fds as an indirect way to watch the calculator itself */
|
||||||
struct pollfd client_socket_pollfd = {
|
struct pollfd client_socket_pollfd = {
|
||||||
.fd = client_socket, .events = POLLIN
|
.fd = client_socket, .events = POLLIN
|
||||||
};
|
};
|
||||||
fxlink_pollfds_track(&fxlink_polled_fds, context);
|
fxlink_pollfds_track(&fxlink_polled_fds, context);
|
||||||
|
|
||||||
while(true) {
|
while(!interrupted_flag && !gdb_terminated_flag) {
|
||||||
int err = fxlink_multipoll(-1,
|
int err = fxlink_multipoll(-1,
|
||||||
fxlink_polled_fds.fds, fxlink_polled_fds.count,
|
fxlink_polled_fds.fds, fxlink_polled_fds.count,
|
||||||
&client_socket_pollfd, 1,
|
&client_socket_pollfd, 1,
|
||||||
|
@ -150,12 +252,14 @@ int main(int argc, char *argv[])
|
||||||
struct fxlink_message *msg;
|
struct fxlink_message *msg;
|
||||||
while((msg = fxlink_device_finish_bulk_IN(fdev)) != NULL) {
|
while((msg = fxlink_device_finish_bulk_IN(fdev)) != NULL) {
|
||||||
if(!fxlink_message_is_apptype(msg, "gdb", "remote")) {
|
if(!fxlink_message_is_apptype(msg, "gdb", "remote")) {
|
||||||
|
hlog("gdb");
|
||||||
wlog("dropped a message of type %.16s:%.16s\n",
|
wlog("dropped a message of type %.16s:%.16s\n",
|
||||||
msg->application, msg->type);
|
msg->application, msg->type);
|
||||||
fxlink_device_start_bulk_IN(fdev);
|
fxlink_device_start_bulk_IN(fdev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
printf("CAL> %.*s\n", msg->size, (char *)msg->data);
|
if(opts.bridge_only)
|
||||||
|
printf("CAL> %.*s\n", msg->size, (char *)msg->data);
|
||||||
ssize_t send_ret = send(client_socket, msg->data, msg->size, 0);
|
ssize_t send_ret = send(client_socket, msg->data, msg->size, 0);
|
||||||
if(send_ret != msg->size) {
|
if(send_ret != msg->size) {
|
||||||
perror("send");
|
perror("send");
|
||||||
|
@ -182,7 +286,8 @@ int main(int argc, char *argv[])
|
||||||
perror("recv");
|
perror("recv");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
printf("GDB> %.*s\n", (int)recv_ret, buf);
|
if(opts.bridge_only)
|
||||||
|
printf("GDB> %.*s\n", (int)recv_ret, buf);
|
||||||
if(!fxlink_device_start_bulk_OUT(fdev, "gdb", "remote", buf, recv_ret, false)) {
|
if(!fxlink_device_start_bulk_OUT(fdev, "gdb", "remote", buf, recv_ret, false)) {
|
||||||
elog("unable to start bulk OUT transfer\n");
|
elog("unable to start bulk OUT transfer\n");
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -193,8 +298,10 @@ int main(int argc, char *argv[])
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
/* TODO: Close socket at end, including after ^C */
|
if(gdb_pid != -1)
|
||||||
|
waitpid(gdb_pid, NULL, 0);
|
||||||
|
if(socket_path[0])
|
||||||
|
unlink(socket_path);
|
||||||
if(fxlink_polled_fds.ctx)
|
if(fxlink_polled_fds.ctx)
|
||||||
fxlink_pollfds_stop(&fxlink_polled_fds);
|
fxlink_pollfds_stop(&fxlink_polled_fds);
|
||||||
if(fdev) {
|
if(fdev) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue