29 #define QSUPPORTED_MAX_RETRIES 5
34 static int set_interface_attribs(
int fd,
int speed,
int parity) {
35 #if defined(_MSC_VER) || defined(__MINGW32__)
36 #pragma message("gdbclient/core.c: set_interface_attribs not implemented")
40 if (tcgetattr (
fd, &
tty) != 0) {
44 cfsetospeed (&
tty, speed);
45 cfsetispeed (&
tty, speed);
62 tty.c_cflag |= parity;
100 g->gdbr_lock_depth++;
109 g->gdbr_lock_depth++;
119 assert(
g->gdbr_lock_depth > 0);
120 bool last_leave =
g->gdbr_lock_depth == 1;
121 g->gdbr_lock_depth--;
125 g->isbreaked =
false;
135 if (
g->stub_features.qXfer_features_read) {
143 if (
g->data_len == 0 || (
g->data_len == 3 &&
g->data[0] ==
'E')) {
147 g->stub_features.lldb.g =
true;
156 const char *
message =
"qSupported:multiprocess+;qRelocInsn+;xmlRegisters=i386";
168 g->stub_features.pkt_sz = 64;
172 if ((env_pktsz = (
ut32)strtoul(env_pktsz_str,
NULL, 10))) {
214 g->isbreaked =
false;
225 if (
g->stub_features.QStartNoAckMode) {
226 if ((ret =
send_msg(
g,
"QStartNoAckMode")) < 0) {
230 if (!strncmp(
g->data,
"OK", 2)) {
242 g->stub_features.qC =
true;
249 g->stub_features.qC =
false;
266 if (strcmp(
g->data,
"OK")) {
269 if (
g->stub_features.qXfer_features_read) {
292 g->stop_reason.is_valid =
false;
294 if (
g->target.valid) {
295 free(
g->target.regprofile);
305 char cmd[64] = { 0 };
316 g->stub_features.multiprocess)) < 0) {
319 g->stop_reason.is_valid =
false;
324 if (strcmp(
g->data,
"OK")) {
350 if (
g->data_len == 0) {
351 g->stub_features.vContSupported =
false;
355 g->data[
g->data_len] =
'\0';
356 if (!(ptr = strtok(
g->data + strlen(
"vCont;"),
";"))) {
363 g->stub_features.vcont.s =
true;
366 g->stub_features.vcont.S =
true;
369 g->stub_features.vcont.c =
true;
372 g->stub_features.vcont.C =
true;
375 g->stub_features.vcont.t =
true;
378 g->stub_features.vcont.r =
true;
381 g->stub_features.vContSupported =
true;
382 ptr = strtok(
NULL,
";");
412 g->stop_reason.is_valid =
false;
417 g->stub_features.extended_mode = 0;
423 g->stub_features.extended_mode = 0;
426 if (strncmp(
g->data,
"OK", 2)) {
427 g->stub_features.extended_mode = 0;
431 g->stub_features.extended_mode = 1;
444 if (!
g || !
g->sock) {
451 g->stop_reason.is_valid =
false;
454 if (
g->stub_features.extended_mode == -1) {
458 if (!
g->stub_features.extended_mode) {
498 if (!
g || !
g->sock) {
507 g->stop_reason.is_valid =
false;
525 if (!
g || !
g->sock || !
g->stub_features.multiprocess) {
534 g->stop_reason.is_valid =
false;
558 if (strncmp(
g->data,
"OK", 2)) {
575 if (!
g || !
g->sock) {
584 g->stop_reason.is_valid =
false;
586 if (
g->stub_features.multiprocess) {
610 if (!
g || !
g->sock || !
g->stub_features.multiprocess) {
619 g->stop_reason.is_valid =
false;
640 if (strncmp(
g->data,
"OK", 2)) {
658 if (!
g || !
g->sock) {
688 if (!
g || !
g->data) {
729 int last, ret_len, pkt;
744 int data_sz =
g->stub_features.pkt_sz / 2;
745 int num_pkts =
len / data_sz;
746 last =
len % data_sz;
748 for (pkt = 0; pkt < num_pkts; pkt++) {
751 (
ut64)address + (pkt * data_sz),
752 (
ut64)data_sz) < 0) {
768 int delta = (pkt * data_sz);
777 ret_len +=
g->data_len;
783 (
ut64)(address + (num_pkts * data_sz)),
800 int delta = num_pkts * data_sz;
804 ret_len +=
g->data_len;
813 int ret_len, ret,
tmp;
814 int page_size =
g->page_size;
822 tmp = page_size - (address & (page_size - 1));
836 while (
len > page_size) {
845 address += page_size;
847 ret_len += page_size;
862 int command_len, pkt, max_cmd_len = 64;
863 ut64 num_pkts, last, data_sz;
869 data_sz =
g->stub_features.pkt_sz / 2;
873 num_pkts =
len / data_sz;
874 last =
len % data_sz;
875 if (!(
tmp =
calloc(max_cmd_len +
g->stub_features.pkt_sz,
sizeof(
char)))) {
883 for (pkt = num_pkts - 1; pkt >= 0; pkt--) {
886 address + (pkt * data_sz), data_sz)) < 0) {
890 pack_hex((
char *)data + (pkt * data_sz), data_sz, (
tmp + command_len));
904 address + (num_pkts * data_sz), last)) < 0) {
908 pack_hex((
char *)data + (num_pkts * data_sz), last, (
tmp + command_len));
931 char thread_id[64] = { 0 };
937 if (tid <= 0 ||
write_thread_id(thread_id,
sizeof(thread_id) - 1,
g->pid, tid,
g->stub_features.multiprocess) < 0) {
951 char thread_id[64] = { 0 };
964 if (tid <= 0 ||
write_thread_id(thread_id,
sizeof(thread_id) - 1,
g->pid, tid,
g->stub_features.multiprocess) < 0) {
1021 if (!
g || !
g->stub_features.P) {
1031 eprintf(
"command is too small\n");
1047 g->stub_features.P =
false;
1070 while (
g->registers[
i].size > 0) {
1071 if (!strcmp(
g->registers[
i].name,
name)) {
1076 if (
g->registers[
i].size == 0) {
1077 eprintf(
"Error registername <%s> not found in profile\n",
name);
1100 unsigned int x,
len;
1116 len = strlen(registers);
1123 reg = strtok(buff,
",");
1125 char *name_end = strchr(
reg,
'=');
1126 if (name_end ==
NULL) {
1134 while (
g->registers[
i].size > 0) {
1135 if (strcmp(
g->registers[
i].name,
reg) == 0) {
1136 const ut64 register_size =
g->registers[
i].size;
1147 if (name_end[1] ==
'x' || name_end[1] ==
'X') {
1150 const int val_len = strlen(name_end);
1151 strcpy(
value + (register_size * 2 - val_len), name_end);
1153 for (
x = 0;
x < register_size;
x++) {
1213 char tmp[255] = { 0 };
1221 if (!
g->stub_features.vContSupported) {
1224 bool supported =
false;
1227 if (
g->stub_features.vcont.s) {
1232 if (
g->stub_features.vcont.S) {
1237 if (
g->stub_features.vcont.c) {
1242 if (
g->stub_features.vcont.C) {
1247 if (
g->stub_features.vcont.t) {
1252 if (
g->stub_features.vcont.r) {
1275 g->stop_reason.is_valid =
false;
1285 g->isbreaked =
false;
1303 char tmp[255] = { 0 };
1342 g->stop_reason.is_valid =
false;
1397 char tmp[255] = { 0 };
1431 g->stop_reason.is_valid =
false;
1453 if (
g->remote_file_fd >= 0) {
1454 eprintf(
"%s: Remote file already open\n", __func__);
1465 strcpy(
buf,
"vFile:open:");
1490 if (!
g || !
buf || !max_len) {
1494 eprintf(
"%s: Too big a file read requested: %" PFMT64d, __func__, max_len);
1497 if (
g->remote_file_fd < 0) {
1498 eprintf(
"%s: No remote file opened\n", __func__);
1506 data_sz =
g->stub_features.pkt_sz / 2;
1508 while (ret < max_len) {
1511 (
int)
g->remote_file_fd, (
ut64)
RZ_MIN(data_sz, max_len - ret),
1546 if (
g->remote_file_fd < 0) {
1547 eprintf(
"%s: No remote file opened\n", __func__);
1562 g->remote_file_fd = -1;
1582 len = strlen(
cmd) * 2 + 8;
1586 strcpy(
buf,
"qRcmd,");
1591 g->stop_reason.is_valid =
false;
1604 if (
g->data_len == 0) {
1612 if (!strncmp(
g->data,
"OK", 2)) {
1615 if (
g->data[0] ==
'O' &&
g->data_len % 2 == 1) {
1618 g->data[
g->data_len - 1] =
'\0';
1619 cb_printf(
"%s",
g->data + 1);
1636 char msg[128], pidstr[16];
1645 len =
g->stub_features.pkt_sz;
1646 memset(pidstr, 0,
sizeof(pidstr));
1647 if (
g->stub_features.multiprocess &&
pid > 0) {
1665 g->data[
g->data_len] =
'\0';
1666 if (
g->data[0] ==
'l') {
1667 if (
g->data_len == 1) {
1673 if (
g->data[0] !=
'm') {
1677 off += strlen(
g->data + 1);
1702 if (
g->stub_features.multiprocess &&
pid <= 0) {
1709 char msg[64] = { 0 }, thread_id[63] = { 0 };
1711 g->stub_features.multiprocess) < 0) {
1720 if (
g->data_len == 3 &&
g->data[0] ==
'E') {
1734 int tpid = -1, ttid = -1;
1735 char *ptr, *ptr2, *exec_file;
1751 if (
g->stub_features.qXfer_threads_read) {
1760 eprintf(
"WARNING: Showing possibly incomplete pid list due to xml protocol failure\n");
1770 g->data[
g->data_len] =
'\0';
1773 if ((ptr2 = strchr(ptr,
','))) {
1777 if (
read_thread_id(ptr, &tpid, &ttid,
g->stub_features.multiprocess) < 0) {
1782 rz_list_foreach (
list,
iter, dpid) {
1783 if (tpid == dpid->
pid) {
1793 if (tpid !=
g->pid) {
1794 dpid->
ppid =
g->pid;
1796 dpid->
uid = dpid->
gid = -1;
1806 if (
g->data[0] ==
'l') {
1820 rz_list_foreach (
list,
iter, dpid) {
1836 int tpid = -1, ttid = -1;
1837 char *ptr, *ptr2, *exec_file;
1851 if (
g->stub_features.qXfer_threads_read) {
1864 g->data[
g->data_len] =
'\0';
1867 if ((ptr2 = strchr(ptr,
','))) {
1872 g->stub_features.multiprocess) < 0) {
1876 if (
g->stub_features.multiprocess && tpid !=
pid) {
1884 dpid->
uid = dpid->
gid = -1;
1898 if (
g->data[0] ==
'l') {
1903 rz_list_foreach (
list,
iter, dpid) {
1918 rz_list_foreach (
list,
iter, dpid) {
1946 ptr =
g->data + strlen(
"TextSeg=");
1950 off = strtoull(ptr,
NULL, 16);
1954 if (!(ptr = strchr(ptr,
';'))) {
1959 ptr += strlen(
"DataSeg=");
1963 off = strtoull(ptr,
NULL, 16);
1973 ptr =
g->data + strlen(
"Text=");
1977 off = strtoull(ptr,
NULL, 16);
1985 ptr += strlen(
";Data=");
1990 off = strtoull(ptr,
NULL, 16);
1994 if (!(ptr = strchr(ptr,
';'))) {
1999 ptr += strlen(
"Bss=");
2003 off = strtoull(ptr,
NULL, 16);
RZ_API void * rz_cons_sleep_begin(void)
RZ_API void rz_cons_break_pop(void)
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
RZ_API void rz_cons_sleep_end(void *user)
static static fork const void static count static fd const char const char static newpath const char static path const char path
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
RZ_API char * sdb_fmt(const char *fmt,...)
int send_ack(libgdbr_t *g)
Functions sends a single ack ('+')
RZ_API void Ht_() free(HtName_(Ht) *ht)
int read_packet(libgdbr_t *instance, bool vcont)
int send_msg(libgdbr_t *g, const char *command)
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define GDB_REMOTE_TYPE_LLDB
#define MSG_NOT_SUPPORTED
static void list(RzEgg *egg)
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
void * malloc(size_t size)
void * calloc(size_t number, size_t size)
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
assert(limit<=UINT32_MAX/2)
static const char hex[16]
static const char * conditions[]
int handle_G(libgdbr_t *g)
int handle_M(libgdbr_t *g)
int handle_lldb_read_reg(libgdbr_t *g)
int handle_vFile_pread(libgdbr_t *g, ut8 *buf)
int handle_m(libgdbr_t *g)
int handle_vFile_close(libgdbr_t *g)
int handle_setbp(libgdbr_t *g)
int handle_cont(libgdbr_t *g)
int handle_stop_reason(libgdbr_t *g)
int handle_g(libgdbr_t *g)
int handle_removebp(libgdbr_t *g)
int handle_attach(libgdbr_t *g)
int handle_qSupported(libgdbr_t *g)
int handle_vFile_open(libgdbr_t *g)
int handle_qC(libgdbr_t *g)
int handle_P(libgdbr_t *g)
RZ_API int rz_socket_close(RzSocket *s)
RZ_API bool rz_socket_is_connected(RzSocket *)
RZ_API int rz_socket_connect_serial(RzSocket *sock, const char *path, int speed, int parity)
#define rz_socket_connect_tcp(a, b, c, d)
RZ_API int rz_socket_write(RzSocket *s, void *buf, int len)
RZ_API char * rz_str_append(char *ptr, const char *string)
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
int(* PrintfCallback)(const char *str,...) RZ_PRINTF_CHECK(1
static struct sockaddr static addrlen static backlog const void static flags void flags
static struct sockaddr static addrlen static backlog const void msg
int unpack_hex(const char *src, ut64 len, char *dst)
int write_thread_id(char *dest, int len, int pid, int tid, bool multiprocess)
int read_thread_id(const char *src, int *pid, int *tid, bool multiprocess)
int pack_hex(const char *src, ut64 len, char *dst)
int gdbr_write_register(libgdbr_t *g, int index, char *value, int len)
int gdbr_disconnect(libgdbr_t *g)
disconnects the lib
int gdbr_read_memory(libgdbr_t *g, ut64 address, ut8 *buf, int len)
int gdbr_check_extended_mode(libgdbr_t *g)
checks for extended mode availability
int gdbr_remove_hwa(libgdbr_t *g, ut64 address, int sizebp)
int gdbr_remove_bp(libgdbr_t *g, ut64 address, int sizebp)
int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode)
static int gdbr_connect_lldb(libgdbr_t *g)
static void gdbr_break_process(void *arg)
int gdbr_write_registers(libgdbr_t *g, char *registers)
int gdbr_check_vcont(libgdbr_t *g)
checks which subcommands of the vCont packet are supported
int gdbr_attach(libgdbr_t *g, int pid)
attaches to a process
int gdbr_remove_hwbp(libgdbr_t *g, ut64 address, int sizebp)
bool gdbr_lock_tryenter(libgdbr_t *g)
int gdbr_read_registers(libgdbr_t *g)
int gdbr_connect(libgdbr_t *g, const char *host, int port)
Function connects to a gdbserver instance.
int gdbr_remove_hwr(libgdbr_t *g, ut64 address, int sizebp)
int gdbr_detach(libgdbr_t *g)
detaches from a process
bool gdbr_lock_enter(libgdbr_t *g)
Acquires the gdbr lock and sets up breaking.
RzList * gdbr_threads_list(libgdbr_t *g, int pid)
get list of threads for given pid
int remove_bp(libgdbr_t *g, ut64 address, enum Breakpoint type, int sizebp)
int gdbr_set_bp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Function sets normal breakpoint (0xcc, int3)
char * gdbr_exec_file_read(libgdbr_t *g, int pid)
int gdbr_remove_hww(libgdbr_t *g, ut64 address, int sizebp)
void gdbr_lock_leave(libgdbr_t *g)
Releases the gdbr lock.
RzList * gdbr_pids_list(libgdbr_t *g, int pid)
get a list of the child processes of the given pid
static void reg_cache_init(libgdbr_t *g)
int gdbr_detach_pid(libgdbr_t *g, int pid)
bool gdbr_is_thread_dead(libgdbr_t *g, int pid, int tid)
int gdbr_set_hwa(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
int test_command(libgdbr_t *g, const char *command)
static int gdbr_read_memory_page(libgdbr_t *g, ut64 address, ut8 *buf, int len)
int gdbr_set_hwbp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
int gdbr_step(libgdbr_t *g, int tid)
int gdbr_continue(libgdbr_t *g, int pid, int tid, int sig)
static struct @443 reg_cache
int gdbr_set_hwr(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
int gdbr_write_reg(libgdbr_t *g, const char *name, char *value, int len)
int gdbr_write_memory(libgdbr_t *g, ut64 address, const uint8_t *data, ut64 len)
int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len)
ut64 gdbr_get_baddr(libgdbr_t *g)
int set_bp(libgdbr_t *g, ut64 address, const char *conditions, enum Breakpoint type, int sizebp)
#define QSUPPORTED_MAX_RETRIES
void gdbr_invalidate_reg_cache()
invalidates the reg cache
int gdbr_select(libgdbr_t *g, int pid, int tid)
static int gdbr_read_registers_lldb(libgdbr_t *g)
int send_vcont(libgdbr_t *g, const char *command, const char *thread_id)
Function sends a vCont command to the gdbserver.
int gdbr_kill(libgdbr_t *g)
kills the process the remote gdbserver is debugging (TODO: handle pid)
int gdbr_send_qRcmd(libgdbr_t *g, const char *cmd, PrintfCallback cb_printf)
sends a qRcmd packet which basically passes a command to the remote target's interpreter.
int gdbr_set_hww(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
int gdbr_stop_reason(libgdbr_t *g)
gets reason why remote target stopped
int gdbr_write_bin_registers(libgdbr_t *g, const char *regs, int len)
Function writes general purpose registers.
int gdbr_close_file(libgdbr_t *g)
int gdbr_kill_pid(libgdbr_t *g, int pid)
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
RZ_API bool rz_th_lock_tryenter(RZ_NONNULL RzThreadLock *thl)
Tries to acquire a RzThreadLock structure.
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
int gdbr_read_processes_xml(libgdbr_t *g, int pid, RzList *list)
int gdbr_read_target_xml(libgdbr_t *g)
static const z80_opcode fd[]
#define buffer_size(buffer)