| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- /*
- * Copyright (C) 2021 Ant Group. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include <bh_log.h>
- #include <handler.h>
- #include <limits.h>
- #include <string.h>
- #include <unistd.h>
- #include "debug_engine.h"
- #include "packets.h"
- #include "utils.h"
- #include "wasm_runtime.h"
- #define MAX_PACKET_SIZE (0x20000)
- static char tmpbuf[MAX_PACKET_SIZE];
- void
- handle_generay_set(WASMGDBServer *server, char *payload)
- {
- const char *name;
- char *args;
- args = strchr(payload, ':');
- if (args)
- *args++ = '\0';
- name = payload;
- LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
- if (!strcmp(name, "StartNoAckMode")) {
- server->noack = true;
- write_packet(server, "OK");
- }
- if (!strcmp(name, "ThreadSuffixSupported")) {
- write_packet(server, "");
- }
- if (!strcmp(name, "ListThreadsInStopReply")) {
- write_packet(server, "");
- }
- if (!strcmp(name, "EnableErrorStrings")) {
- write_packet(server, "OK");
- }
- }
- static void
- process_xfer(WASMGDBServer *server, const char *name, char *args)
- {
- const char *mode = args;
- args = strchr(args, ':');
- if (args)
- *args++ = '\0';
- if (!strcmp(name, "libraries") && !strcmp(mode, "read")) {
- // TODO: how to get current wasm file name?
- uint64_t addr = wasm_debug_instance_get_load_addr(
- (WASMDebugInstance *)server->thread->debug_instance);
- #if WASM_ENABLE_LIBC_WASI != 0
- char objname[128];
- wasm_debug_instance_get_current_object_name(
- (WASMDebugInstance *)server->thread->debug_instance, objname, 128);
- sprintf(tmpbuf,
- "l<library-list><library name=\"%s\"><section "
- "address=\"0x%lx\"/></library></library-list>",
- objname, addr);
- #else
- sprintf(tmpbuf,
- "l<library-list><library name=\"%s\"><section "
- "address=\"0x%lx\"/></library></library-list>",
- "nobody.wasm", addr);
- #endif
- write_packet(server, tmpbuf);
- }
- }
- void
- porcess_wasm_local(WASMGDBServer *server, char *args)
- {
- int frame_index;
- int local_index;
- char buf[16];
- int size = 16;
- bool ret;
- sprintf(tmpbuf, "E01");
- if (sscanf(args, "%d;%d", &frame_index, &local_index) == 2) {
- ret = wasm_debug_instance_get_local(
- (WASMDebugInstance *)server->thread->debug_instance, frame_index,
- local_index, buf, &size);
- if (ret && size > 0) {
- mem2hex(buf, tmpbuf, size);
- }
- }
- write_packet(server, tmpbuf);
- }
- void
- porcess_wasm_global(WASMGDBServer *server, char *args)
- {
- int frame_index;
- int global_index;
- char buf[16];
- int size = 16;
- bool ret;
- sprintf(tmpbuf, "E01");
- if (sscanf(args, "%d;%d", &frame_index, &global_index) == 2) {
- ret = wasm_debug_instance_get_global(
- (WASMDebugInstance *)server->thread->debug_instance, frame_index,
- global_index, buf, &size);
- if (ret && size > 0) {
- mem2hex(buf, tmpbuf, size);
- }
- }
- write_packet(server, tmpbuf);
- }
- void
- handle_generay_query(WASMGDBServer *server, char *payload)
- {
- const char *name;
- char *args;
- args = strchr(payload, ':');
- if (args)
- *args++ = '\0';
- name = payload;
- LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
- if (!strcmp(name, "C")) {
- uint64_t pid, tid;
- pid = wasm_debug_instance_get_pid(
- (WASMDebugInstance *)server->thread->debug_instance);
- tid = wasm_debug_instance_get_tid(
- (WASMDebugInstance *)server->thread->debug_instance);
- snprintf(tmpbuf, sizeof(tmpbuf), "QCp%lx.%lx", pid, tid);
- write_packet(server, tmpbuf);
- }
- if (!strcmp(name, "Supported")) {
- sprintf(tmpbuf, "qXfer:libraries:read+;PacketSize=%x;",
- MAX_PACKET_SIZE);
- write_packet(server, tmpbuf);
- }
- if (!strcmp(name, "Xfer")) {
- name = args;
- if (!args) {
- LOG_ERROR("payload parse error during handle_generay_query");
- return;
- }
- args = strchr(args, ':');
- if (args) {
- *args++ = '\0';
- process_xfer(server, name, args);
- }
- }
- if (!strcmp(name, "HostInfo")) {
- // Todo: change vendor to Intel for outside tree?
- char triple[256];
- mem2hex("wasm32-Ant-wasi-wasm", triple, strlen("wasm32-Ant-wasi-wasm"));
- sprintf(tmpbuf,
- "vendor:Ant;ostype:wasi;arch:wasm32;"
- "triple:%s;endian:little;ptrsize:4;",
- triple);
- write_packet(server, tmpbuf);
- }
- if (!strcmp(name, "GetWorkingDir")) {
- if (getcwd(tmpbuf, PATH_MAX))
- write_packet(server, tmpbuf);
- }
- if (!strcmp(name, "QueryGDBServer")) {
- write_packet(server, "");
- }
- if (!strcmp(name, "VAttachOrWaitSupported")) {
- write_packet(server, "");
- }
- if (!strcmp(name, "ProcessInfo")) {
- // Todo: process id parent-pid
- uint64_t pid;
- pid = wasm_debug_instance_get_pid(
- (WASMDebugInstance *)server->thread->debug_instance);
- char triple[256];
- // arch-vendor-os-env(format)
- mem2hex("wasm32-Ant-wasi-wasm", triple, strlen("wasm32-Ant-wasi-wasm"));
- sprintf(tmpbuf,
- "pid:%lx;parent-pid:%lx;vendor:Ant;ostype:wasi;arch:wasm32;"
- "triple:%s;endian:little;ptrsize:4;",
- pid, pid, triple);
- write_packet(server, tmpbuf);
- }
- if (!strcmp(name, "RegisterInfo0")) {
- sprintf(
- tmpbuf,
- "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;"
- "set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;");
- write_packet(server, tmpbuf);
- }
- else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) {
- write_packet(server, "E45");
- }
- if (!strcmp(name, "StructuredDataPlugins")) {
- write_packet(server, "");
- }
- if (args && (!strcmp(name, "MemoryRegionInfo"))) {
- uint64_t addr = strtol(args, NULL, 16);
- WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion(
- (WASMDebugInstance *)server->thread->debug_instance, addr);
- if (mem_info) {
- char name[256];
- mem2hex(mem_info->name, name, strlen(mem_info->name));
- sprintf(tmpbuf, "start:%lx;size:%lx;permissions:%s;name:%s;",
- (uint64)mem_info->start, mem_info->size,
- mem_info->permisson, name);
- write_packet(server, tmpbuf);
- wasm_debug_instance_destroy_memregion(
- (WASMDebugInstance *)server->thread->debug_instance, mem_info);
- }
- }
- if (!strcmp(name, "WasmData")) {
- }
- if (!strcmp(name, "WasmMem")) {
- }
- if (!strcmp(name, "Symbol")) {
- write_packet(server, "");
- }
- if (args && (!strcmp(name, "WasmCallStack"))) {
- uint64_t tid = strtol(args, NULL, 16);
- uint64_t buf[1024 / sizeof(uint64_t)];
- uint64_t count = wasm_debug_instance_get_call_stack_pcs(
- (WASMDebugInstance *)server->thread->debug_instance, tid, buf,
- 1024 / sizeof(uint64_t));
- if (count > 0) {
- mem2hex((char *)buf, tmpbuf, count * sizeof(uint64_t));
- write_packet(server, tmpbuf);
- }
- else
- write_packet(server, "");
- }
- if (args && (!strcmp(name, "WasmLocal"))) {
- porcess_wasm_local(server, args);
- }
- if (args && (!strcmp(name, "WasmGlobal"))) {
- porcess_wasm_global(server, args);
- }
- }
- static void
- send_thread_stop_status(WASMGDBServer *server, uint32_t status, uint64_t tid)
- {
- int tids_number, len = 0, i = 0;
- uint64_t tids[20];
- char pc_string[17];
- uint32_t gdb_status = status;
- if (status == 0) {
- sprintf(tmpbuf, "W%02x", status);
- write_packet(server, tmpbuf);
- return;
- }
- tids_number = wasm_debug_instance_get_tids(
- (WASMDebugInstance *)server->thread->debug_instance, tids, 20);
- uint64_t pc = wasm_debug_instance_get_pc(
- (WASMDebugInstance *)server->thread->debug_instance);
- if (status == WAMR_SIG_SINGSTEP) {
- gdb_status = WAMR_SIG_TRAP;
- }
- // TODO: how name a wasm thread?
- len +=
- sprintf(tmpbuf, "T%02xthread:%lx;name:%s;", gdb_status, tid, "nobody");
- if (tids_number > 0) {
- len += sprintf(tmpbuf + len, "threads:");
- while (i < tids_number) {
- if (i == tids_number - 1)
- len += sprintf(tmpbuf + len, "%lx;", tids[i]);
- else
- len += sprintf(tmpbuf + len, "%lx,", tids[i]);
- i++;
- }
- }
- mem2hex((void *)&pc, pc_string, 8);
- pc_string[8 * 2] = '\0';
- if (status == WAMR_SIG_TRAP) {
- len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
- pc_string, "breakpoint");
- }
- else if (status == WAMR_SIG_SINGSTEP) {
- len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
- pc_string, "trace");
- }
- else if (status > 0) {
- len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc,
- pc_string, "signal");
- }
- write_packet(server, tmpbuf);
- }
- void
- handle_v_packet(WASMGDBServer *server, char *payload)
- {
- const char *name;
- char *args;
- uint32_t status;
- args = strchr(payload, ';');
- if (args)
- *args++ = '\0';
- name = payload;
- LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
- if (!strcmp("Cont?", name))
- write_packet(server, "vCont;c;C;s;S;");
- if (!strcmp("Cont", name)) {
- if (args && args[0] == 's') {
- char *numstring = strchr(args, ':');
- if (numstring) {
- *numstring++ = '\0';
- uint64_t tid = strtol(numstring, NULL, 16);
- wasm_debug_instance_set_cur_thread(
- (WASMDebugInstance *)server->thread->debug_instance, tid);
- wasm_debug_instance_singlestep(
- (WASMDebugInstance *)server->thread->debug_instance, tid);
- tid = wasm_debug_instance_wait_thread(
- (WASMDebugInstance *)server->thread->debug_instance, tid,
- &status);
- send_thread_stop_status(server, status, tid);
- }
- }
- }
- }
- void
- handle_threadstop_request(WASMGDBServer *server, char *payload)
- {
- uint64_t tid = wasm_debug_instance_get_tid(
- (WASMDebugInstance *)server->thread->debug_instance);
- uint32_t status;
- tid = wasm_debug_instance_wait_thread(
- (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
- send_thread_stop_status(server, status, tid);
- }
- void
- handle_set_current_thread(WASMGDBServer *server, char *payload)
- {
- LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload, payload);
- if ('g' == *payload++) {
- uint64_t tid;
- tid = strtol(payload, NULL, 16);
- if (tid > 0)
- wasm_debug_instance_set_cur_thread(
- (WASMDebugInstance *)server->thread->debug_instance, tid);
- }
- write_packet(server, "OK");
- }
- void
- handle_get_register(WASMGDBServer *server, char *payload)
- {
- int i = strtol(payload, NULL, 16);
- if (i != 0) {
- write_packet(server, "E01");
- return;
- }
- uint64_t regdata = wasm_debug_instance_get_pc(
- (WASMDebugInstance *)server->thread->debug_instance);
- mem2hex((void *)®data, tmpbuf, 8);
- tmpbuf[8 * 2] = '\0';
- write_packet(server, tmpbuf);
- }
- void
- handle_get_json_request(WASMGDBServer *server, char *payload)
- {
- char *args;
- args = strchr(payload, ':');
- if (args)
- *args++ = '\0';
- write_packet(server, "");
- }
- void
- handle_get_read_binary_memory(WASMGDBServer *server, char *payload)
- {
- write_packet(server, "");
- }
- void
- handle_get_read_memory(WASMGDBServer *server, char *payload)
- {
- size_t maddr, mlen;
- bool ret;
- sprintf(tmpbuf, "%s", "");
- if (sscanf(payload, "%zx,%zx", &maddr, &mlen) == 2) {
- if (mlen * 2 > MAX_PACKET_SIZE) {
- LOG_ERROR("Buffer overflow!");
- mlen = MAX_PACKET_SIZE / 2;
- }
- char *buff = wasm_runtime_malloc(mlen);
- if (buff) {
- ret = wasm_debug_instance_get_mem(
- (WASMDebugInstance *)server->thread->debug_instance, maddr,
- buff, &mlen);
- if (ret) {
- mem2hex(buff, tmpbuf, mlen);
- }
- wasm_runtime_free(buff);
- }
- }
- write_packet(server, tmpbuf);
- }
- void
- handle_get_write_memory(WASMGDBServer *server, char *payload)
- {
- size_t maddr, mlen, hex_len;
- int offset, act_len;
- char *buff;
- bool ret;
- sprintf(tmpbuf, "%s", "");
- if (sscanf(payload, "%zx,%zx:%n", &maddr, &mlen, &offset) == 2) {
- payload += offset;
- hex_len = strlen(payload);
- act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen;
- buff = wasm_runtime_malloc(act_len);
- if (buff) {
- hex2mem(payload, buff, act_len);
- ret = wasm_debug_instance_set_mem(
- (WASMDebugInstance *)server->thread->debug_instance, maddr,
- buff, &mlen);
- if (ret) {
- sprintf(tmpbuf, "%s", "OK");
- }
- wasm_runtime_free(buff);
- }
- }
- write_packet(server, tmpbuf);
- }
- void
- handle_add_break(WASMGDBServer *server, char *payload)
- {
- size_t type, addr, length;
- if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
- if (type == eBreakpointSoftware) {
- bool ret = wasm_debug_instance_add_breakpoint(
- (WASMDebugInstance *)server->thread->debug_instance, addr,
- length);
- if (ret)
- write_packet(server, "OK");
- else
- write_packet(server, "E01");
- return;
- }
- }
- write_packet(server, "");
- }
- void
- handle_remove_break(WASMGDBServer *server, char *payload)
- {
- size_t type, addr, length;
- if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) {
- if (type == eBreakpointSoftware) {
- bool ret = wasm_debug_instance_remove_breakpoint(
- (WASMDebugInstance *)server->thread->debug_instance, addr,
- length);
- if (ret)
- write_packet(server, "OK");
- else
- write_packet(server, "E01");
- return;
- }
- }
- write_packet(server, "");
- }
- void
- handle_continue_request(WASMGDBServer *server, char *payload)
- {
- uint64_t tid;
- uint32_t status;
- wasm_debug_instance_continue(
- (WASMDebugInstance *)server->thread->debug_instance);
- tid = wasm_debug_instance_get_tid(
- (WASMDebugInstance *)server->thread->debug_instance);
- tid = wasm_debug_instance_wait_thread(
- (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
- send_thread_stop_status(server, status, tid);
- }
- void
- handle_kill_request(WASMGDBServer *server, char *payload)
- {
- uint64_t tid;
- uint32_t status;
- wasm_debug_instance_kill(
- (WASMDebugInstance *)server->thread->debug_instance);
- tid = wasm_debug_instance_get_tid(
- (WASMDebugInstance *)server->thread->debug_instance);
- tid = wasm_debug_instance_wait_thread(
- (WASMDebugInstance *)server->thread->debug_instance, tid, &status);
- send_thread_stop_status(server, status, tid);
- }
- static void
- handle_malloc(WASMGDBServer *server, char *payload)
- {
- char *args;
- uint64_t size;
- int map_port = MMAP_PROT_NONE;
- uint64_t addr;
- sprintf(tmpbuf, "%s", "E03");
- args = strstr(payload, ",");
- if (args) {
- *args++ = '\0';
- }
- else {
- LOG_ERROR("Payload parse error during handle malloc");
- return;
- }
- size = strtol(payload, NULL, 16);
- if (size > 0) {
- while (*args) {
- if (*args == 'r') {
- map_port |= MMAP_PROT_READ;
- }
- if (*args == 'w') {
- map_port |= MMAP_PROT_WRITE;
- }
- if (*args == 'x') {
- map_port |= MMAP_PROT_EXEC;
- }
- args++;
- }
- addr = wasm_debug_instance_mmap(
- (WASMDebugInstance *)server->thread->debug_instance, size,
- map_port);
- if (addr) {
- sprintf(tmpbuf, "%lx", addr);
- }
- }
- write_packet(server, tmpbuf);
- }
- static void
- handle_free(WASMGDBServer *server, char *payload)
- {
- uint64_t addr;
- bool ret;
- sprintf(tmpbuf, "%s", "E03");
- addr = strtol(payload, NULL, 16);
- ret = wasm_debug_instance_ummap(
- (WASMDebugInstance *)server->thread->debug_instance, addr);
- if (ret) {
- sprintf(tmpbuf, "%s", "OK");
- }
- write_packet(server, tmpbuf);
- }
- void
- handle____request(WASMGDBServer *server, char *payload)
- {
- char *args;
- if (payload[0] == 'M') {
- args = payload + 1;
- handle_malloc(server, args);
- }
- if (payload[0] == 'm') {
- args = payload + 1;
- handle_free(server, args);
- }
- }
|