Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions librz/include/rz_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ typedef struct rz_io_plugin_t {
int (*create)(RzIO *io, const char *file, int mode, int type);
bool (*check)(RzIO *io, const char *, bool many);
ut8 *(*get_buf)(RzIODesc *desc, ut64 *size);
bool (*download_file)(RzIO *io, RzIODesc *fd, const char *remote, const char *local);
} RzIOPlugin;

typedef struct rz_io_map_t {
Expand Down Expand Up @@ -384,6 +385,7 @@ RZ_API bool rz_io_desc_is_blockdevice(RzIODesc *desc);
RZ_API bool rz_io_desc_is_chardevice(RzIODesc *desc);
RZ_API bool rz_io_desc_exchange(RzIO *io, int fd, int fdx); // this should get 2 descs
RZ_API bool rz_io_desc_is_dbg(RzIODesc *desc);
RZ_API bool rz_io_desc_download_file(RzIODesc *desc, const char *remote, const char *local);
RZ_API int rz_io_desc_get_pid(RzIODesc *desc);
RZ_API int rz_io_desc_get_tid(RzIODesc *desc);
RZ_API bool rz_io_desc_get_base(RzIODesc *desc, ut64 *base);
Expand Down
7 changes: 7 additions & 0 deletions librz/io/io_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ RZ_API bool rz_io_desc_is_dbg(RzIODesc *desc) {
return false;
}

RZ_API bool rz_io_desc_download_file(RzIODesc *desc, const char *remote, const char *local) {
if (!desc || !desc->plugin || !desc->plugin->download_file || RZ_STR_ISEMPTY(remote) || RZ_STR_ISEMPTY(local)) {
return false;
}
return desc->plugin->download_file(desc->io, desc, remote, local);
}

RZ_API int rz_io_desc_get_pid(RzIODesc *desc) {
//-1 and -2 are reserved
if (!desc) {
Expand Down
68 changes: 67 additions & 1 deletion librz/io/p/io_gdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

#define RZ_GDB_MAGIC rz_str_djb2_hash("gdb")

#define MIN_DOWNLOAD_CHUNK 64
#define MAX_DOWNLOAD_CHUNK 65536

static int __close(RzIODesc *fd);

static bool __plugin_open(RzIO *io, const char *file, bool many) {
Expand Down Expand Up @@ -207,6 +210,56 @@ static int __gettid(RzIODesc *fd) {
extern int send_msg(libgdbr_t *g, const char *command);
extern int read_packet(libgdbr_t *instance, bool vcont);

static bool gdbr_download_file(libgdbr_t *g, const char *remote, const char *local) {
rz_return_val_if_fail(g && remote && local, false);
// empty the destination file by writing nothing in non-append mode
if (!rz_file_dump(local, NULL, 0, false)) {
return false;
}
// open the remote file on the stub side
if (gdbr_open_file(g, remote, O_RDONLY, 0) < 0) {
return false;
}

uint32_t off = 0;
bool ok = true;
// clamp the download size between a reasonable MIN floor and MAX ceiling
ut32 chunk = RZ_MAX(MIN_DOWNLOAD_CHUNK, g->stub_features.pkt_sz / 2);
chunk = RZ_MIN(chunk, MAX_DOWNLOAD_CHUNK);
ut8 *buf = malloc(chunk);
if (!buf) {
gdbr_close_file(g);
return false;
}

int ret;
do {
ret = gdbr_pread_file(g, buf, chunk, off);
if (ret < 0) {
ok = false;
break;
}
if (ret == 0) {
break;
}
if (!rz_file_dump(local, buf, ret, true)) {
ok = false;
break;
}
off += ret;
} while ((ut32)ret == chunk);
free(buf);
gdbr_close_file(g);
return ok;
}

static bool io_gdb_download_file(RzIO *io, RzIODesc *fd, const char *remote, const char *local) {
if (!fd || !fd->data) {
return false;
}
return gdbr_download_file(fd->data, remote, local);
}

static char *__system(RzIO *io, RzIODesc *fd, const char *cmd) {
if (!fd || !fd->data) {
return NULL;
Expand All @@ -228,10 +281,22 @@ static char *__system(RzIO *io, RzIODesc *fd, const char *cmd) {
" R! pktsz - get max packet size used\n"
" R! pktsz bytes - set max. packet size as 'bytes' bytes\n"
" R! exec_file [pid] - get file which was executed for"
" current/specified pid\n");
" current/specified pid\n"
" R! download_file remote local - download remote file to local path\n");
return NULL;
}
libgdbr_t *desc = fd->data;
if (rz_str_startswith(cmd, "download_file")) {
int argc = 0;
char **argv = rz_str_argv(cmd, &argc);
if (!argv || argc != 3) {
rz_str_argv_free(argv);
return rz_str_dup("0");
}
bool ok = gdbr_download_file(desc, argv[1], argv[2]);
rz_str_argv_free(argv);
return rz_str_dup(ok ? "1" : "0");
}
if (rz_str_startswith(cmd, "pktsz")) {
const char *ptr = rz_str_trim_head_ro(cmd + 5);
if (!isdigit((ut8)*ptr)) {
Expand Down Expand Up @@ -430,6 +495,7 @@ RzIOPlugin rz_io_plugin_gdb = {
.system = __system,
.getpid = __getpid,
.gettid = __gettid,
.download_file = io_gdb_download_file,
.isdbg = true
};

Expand Down
48 changes: 46 additions & 2 deletions librz/main/rizin.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ static bool is_valid_dmp_file(RzCoreFile *fh) {
return d && strncmp(d->name, "dmp://", 6);
}

static char *download_gdb_remote_file(RzIODesc *iod, const char *remote_path) {
if (!iod || RZ_STR_ISEMPTY(remote_path)) {
return NULL;
}
char *local_path = NULL;
int fd = rz_file_mkstemp("gdbexe", &local_path);
if (fd == -1 || !local_path) {
free(local_path);
return NULL;
}
close(fd);
if (!rz_io_desc_download_file(iod, remote_path, local_path)) {
rz_file_rm(local_path);
RZ_FREE(local_path);
}
return local_path;
}

static char *get_file_in_cur_dir(const char *filepath) {
filepath = rz_file_basename(filepath);
if (rz_file_exists(filepath) && !rz_file_is_directory(filepath)) {
Expand Down Expand Up @@ -428,6 +446,7 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
bool do_list_io_plugins = false;
char *file = NULL;
char *pfile = NULL;
char *gdb_downloaded_exe = NULL;
const char *asmarch = NULL;
const char *asmos = NULL;
const char *forcebin = NULL;
Expand Down Expand Up @@ -1073,12 +1092,33 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
}
} else if (is_valid_gdb_file(fh) || is_valid_dmp_file(fh)) {
filepath = iod->name;
if (RZ_STR_ISNOTEMPTY(filepath) && rz_file_exists(filepath) && !rz_file_is_directory(filepath)) {
bool is_gdb_remote = rz_str_startswith(pfile, "gdb://");
bool is_localhost_gdb_remote = rz_str_startswith(pfile, "gdb://localhost:");
bool local_file_exists = RZ_STR_ISNOTEMPTY(filepath) && rz_file_exists(filepath) && !rz_file_is_directory(filepath);
bool should_download = is_gdb_remote && RZ_STR_ISNOTEMPTY(filepath) && (!is_localhost_gdb_remote || !local_file_exists);
if (should_download) {
char *downloaded = NULL;
if (addr == UINT64_MAX) {
addr = rz_debug_get_baddr(r->dbg, filepath);
}
if (rz_cons_yesno('n', "Download remote executable '%s' to a temporary file? (y/N) ", filepath)) {
downloaded = download_gdb_remote_file(iod, filepath);
if (!downloaded) {
RZ_LOG_ERROR("Failed to download remote executable '%s'.\n", filepath);
}
}
if (downloaded) {
gdb_downloaded_exe = downloaded;
free(iod->name);
iod->name = rz_str_dup(downloaded);
rz_core_bin_load(r, NULL, addr);
}
} else if (local_file_exists) {
if (addr == UINT64_MAX) {
addr = rz_debug_get_baddr(r->dbg, filepath);
}
rz_core_bin_load(r, filepath, addr);
} else if ((filepath = get_file_in_cur_dir(filepath))) {
} else if (!is_gdb_remote && (filepath = get_file_in_cur_dir(filepath))) {
// Present in local directory
if (iod) {
free(iod->name);
Expand Down Expand Up @@ -1574,6 +1614,10 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
// execution.
// rz_core_file_close (r, fh);
rz_core_free(r);
if (gdb_downloaded_exe) {
rz_file_rm(gdb_downloaded_exe);
free(gdb_downloaded_exe);
}
rz_cons_set_raw(0);
rz_cons_free();
LISTS_FREE();
Expand Down
1 change: 1 addition & 0 deletions subprojects/rzgdb/include/gdbclient/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ int gdbr_remove_hwa(libgdbr_t *g, ut64 address, int sizebp);
* File read from remote target (only one file open at a time for now)
*/
int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode);
int gdbr_pread_file(libgdbr_t *g, ut8 *buf, ut64 max_len, uint32_t start_offset);
int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len);
int gdbr_close_file(libgdbr_t *g);

Expand Down
8 changes: 6 additions & 2 deletions subprojects/rzgdb/src/gdbclient/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1507,7 +1507,7 @@ int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode) {
return ret;
}

int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len) {
int gdbr_pread_file(libgdbr_t *g, ut8 *buf, ut64 max_len, uint32_t start_offset) {
int ret, ret1;
char command[64];
ut64 data_sz;
Expand All @@ -1534,7 +1534,7 @@ int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len) {
if (snprintf(command, sizeof(command) - 1,
"vFile:pread:%x,%" PFMT64x ",%" PFMT64x,
(int)g->remote_file_fd, (ut64)RZ_MIN(data_sz, max_len - ret),
(ut64)ret) < 0) {
(ut64)start_offset + ret) < 0) {
ret = -1;
goto end;
}
Expand All @@ -1561,6 +1561,10 @@ int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len) {
return ret;
}

int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len) {
return gdbr_pread_file(g, buf, max_len, 0);
}

int gdbr_close_file(libgdbr_t *g) {
int ret = -1;
char buf[64];
Expand Down
16 changes: 16 additions & 0 deletions test/db/archos/linux-x64/dbg_gdbserver
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,19 @@ EXPECT=<<EOF
s bins/elf/analysis/pie
EOF
RUN

NAME=gdbserver download_file
FILE=bins/elf/analysis/pie
CMDS=<<EOF
!rm -f gdbserver_download_file.tmp
!scripts/gdbserver.py --port 12348 --binary bins/elf/analysis/pie
oodf gdb://127.0.0.1:12348
R! download_file bins/elf/analysis/pie gdbserver_download_file.tmp
!rz-hash -qqa sha256 gdbserver_download_file.tmp
!rm -f gdbserver_download_file.tmp
EOF
EXPECT=<<EOF
1
7f1c67175bc493d6008bec675f0a05ed281d3867c4f2320300f0b4ebecff3f27
EOF
RUN
Loading