PDB downloader: workaround MS server bug Fix #8848

This commit is contained in:
Tatsuyuki Ishi 2017-11-25 19:24:33 +09:00 committed by Maijin
parent d9376abbf2
commit 6f53a6a69f
3 changed files with 89 additions and 54 deletions

View File

@ -63,4 +63,6 @@ Extracting cabinet: /home/inisider/Downloads/libs/user32.pd_
extracting /home/inisider/Downloads/libs/user32.pdb
All done, no errors.
````
To use the PDB downloader in unix like systems need to setup curl and cabextract, and for Windows just curl
The following dependencies are required for PDB downloader:
* curl
* cabextract (non-Windows only, optional)

View File

@ -5,17 +5,24 @@
#include <r_core.h>
#include "pdb_downloader.h"
static bool checkPrograms () {
static bool checkExtract() {
#if __WINDOWS__ && !__CYGWIN__
const char nul[] = "nul";
if (r_sys_cmd ("expand -? >nul") != 0) {
return false;
}
#else
const char nul[] = "/dev/null";
if (r_sys_cmd ("cabextract -v > /dev/null") != 0) {
return false;
}
#endif
return true;
}
static bool checkCurl() {
#if __WINDOWS__ && !__CYGWIN__
static const char nul[] = "nul";
#else
const char nul[] = "/dev/null";
#endif
if (r_sys_cmdf ("curl --version > %s", nul) != 0) {
return false;
@ -29,74 +36,98 @@ static int download(struct SPDBDownloader *pd) {
char *extractor_cmd = NULL;
char *abspath_to_archive = NULL;
char *archive_name = NULL;
size_t archive_name_len = 0;
const char *basepath = ".";
int res = 1, archive_name_len = 0;
int res = 0;
int cmd_ret;
if (!opt->dbg_file || !*opt->dbg_file) {
// no pdb debug file
return 0;
}
if (!checkPrograms ()) {
if (!checkCurl ()) {
return 0;
}
// dbg_file len is > 0
archive_name_len = strlen (opt->dbg_file);
archive_name = malloc (archive_name_len+1);
archive_name = malloc (archive_name_len + 1);
if (!archive_name) {
return 0;
}
memcpy (archive_name, opt->dbg_file, archive_name_len+1);
memcpy (archive_name, opt->dbg_file, archive_name_len + 1);
archive_name[archive_name_len - 1] = '_';
if (opt->path && *opt->path) {
basepath = opt->path;
}
abspath_to_archive = r_str_newf ("%s%s%s", basepath,
R_SYS_DIR, archive_name);
curl_cmd = r_str_newf ("curl -sA \"%s\" \"%s/%s/%s/%s\" -o \"%s\"",
opt->user_agent,
opt->symbol_server,
opt->dbg_file,
opt->guid,
archive_name,
abspath_to_archive);
// eprintf ("%s\n", curl_cmd);
if (checkExtract () || opt->extract == 0) {
res = 1;
abspath_to_archive = r_str_newf ("%s%s%s", basepath,
R_SYS_DIR, archive_name);
curl_cmd = r_str_newf ("curl -sfA \"%s\" \"%s/%s/%s/%s\" -o \"%s\"",
opt->user_agent,
opt->symbol_server,
opt->dbg_file,
opt->guid,
archive_name,
abspath_to_archive);
#if __WINDOWS__ && !__CYGWIN__
const char *cabextractor = "expand";
const char *format = "%s %s %s";
char *abspath_to_file = strdup (abspath_to_archive);
if (abspath_to_file) {
int abspath_to_archive_len = archive_name_len + strlen (basepath) + 2;
abspath_to_file[abspath_to_archive_len - 2] = 'b';
// extact_cmd -> %1 %2 %3
// %1 - 'expand'
// %2 - absolute path to archive
// %3 - absolute path to file that will be dearchive
extractor_cmd = r_str_newf (format, cabextractor,
abspath_to_archive, abspath_to_file);
}
const char *cabextractor = "expand";
const char *format = "%s %s %s";
char *abspath_to_file = strdup (abspath_to_archive);
if (abspath_to_file) {
int abspath_to_archive_len = archive_name_len + strlen (basepath) + 2;
abspath_to_file[abspath_to_archive_len - 2] = 'b';
// extractor_cmd -> %1 %2 %3
// %1 - 'expand'
// %2 - absolute path to archive
// %3 - absolute path to file that will be dearchive
extractor_cmd = r_str_newf (format, cabextractor,
abspath_to_archive, abspath_to_file);
}
#else
const char *cabextractor = "cabextract";
const char *format = "%s -d \"%s\" \"%s\"";
// cabextract -d %1 %2
// %1 - path to directory where to extract all files from cab arhcive
// %2 - absolute path to cab archive
extractor_cmd = r_str_newf (format,
cabextractor, basepath, abspath_to_archive);
const char *cabextractor = "cabextract";
const char *format = "%s -d \"%s\" \"%s\"";
// cabextract -d %1 %2
// %1 - path to directory where to extract all files from cab archive
// %2 - absolute path to cab archive
extractor_cmd = r_str_newf (format,
cabextractor, basepath, abspath_to_archive);
#endif
if (r_sys_cmd (curl_cmd) != 0) {
eprintf("curl has not been finish with success\n");
res = 0;
}
if (opt->extract > 0) {
if (res && (r_sys_cmd (extractor_cmd) != 0)) {
eprintf ("cab extrach has not been finished with success\n");
if ((cmd_ret = r_sys_cmd (curl_cmd) != 0)) {
eprintf("curl exited with error %d\n", cmd_ret);
res = 0;
}
r_file_rm (abspath_to_archive);
if (opt->extract > 0) {
if (res && ((cmd_ret = r_sys_cmd (extractor_cmd)) != 0)) {
eprintf ("cab extractor exited with error %d\n", cmd_ret);
res = 0;
}
r_file_rm (abspath_to_archive);
}
R_FREE (curl_cmd);
R_FREE (abspath_to_archive);
}
if (res == 0) {
eprintf ("Falling back to uncompressed pdb\n");
res = 1;
archive_name[archive_name_len - 1] = 'b';
abspath_to_archive = r_str_newf ("%s%s%s", basepath,
R_SYS_DIR, archive_name);
curl_cmd = r_str_newf ("curl -sfA \"%s\" \"%s/%s/%s/%s\" -o \"%s\"",
opt->user_agent,
opt->symbol_server,
opt->dbg_file,
opt->guid,
archive_name,
abspath_to_archive);
if ((cmd_ret = r_sys_cmd (curl_cmd) != 0)) {
eprintf("curl exited with error %d\n", cmd_ret);
res = 0;
}
R_FREE (curl_cmd);
R_FREE (abspath_to_archive);
}
R_FREE (archive_name);
R_FREE (curl_cmd);
R_FREE (extractor_cmd);
R_FREE (abspath_to_archive);
return res;
}
@ -124,7 +155,7 @@ void deinit_pdb_downloader(SPDBDownloader *pd) {
pd->download = 0;
}
int r_bin_pdb_download(RCore* core, int isradjson, int* actions_done, SPDBOptions* options) {
int r_bin_pdb_download(RCore *core, int isradjson, int *actions_done, SPDBOptions *options) {
int ret;
char *path;
SPDBDownloaderOpt opt;
@ -154,10 +185,10 @@ int r_bin_pdb_download(RCore* core, int isradjson, int* actions_done, SPDBOption
ret = pdb_downloader.download (&pdb_downloader);
if (isradjson && actions_done) {
printf ("%s\"pdb\":{\"file\":\"%s\",\"download\":%s}",
*actions_done ? "," : "", opt.dbg_file, ret ? "true" : "false");
*actions_done ? "," : "", opt.dbg_file, ret ? "true" : "false");
} else {
printf ("PDB \"%s\" download %s\n",
opt.dbg_file, ret ? "success" : "failed");
opt.dbg_file, ret ? "success" : "failed");
}
if (actions_done) {
(*actions_done)++;

View File

@ -1,7 +1,9 @@
#ifndef PDB_DOWNLOADER_H
#define PDB_DOWNLOADER_H
#include <r_types.h>
#include <r_core.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -9,7 +11,7 @@ extern "C" {
typedef struct SPDBOptions {
char *user_agent;
char *symbol_server;
int extract;
ut64 extract;
} SPDBOptions;
typedef struct SPDBDownloaderOpt {
@ -18,7 +20,7 @@ typedef struct SPDBDownloaderOpt {
char *dbg_file;
char *guid;
char *path;
int extract;
ut64 extract;
} SPDBDownloaderOpt;
typedef struct SPDBDownloader {
@ -42,7 +44,7 @@ void deinit_pdb_downloader(SPDBDownloader *pdb_downloader);
///
/// \brief download PDB file
R_API int r_bin_pdb_download (RCore* core, int isradjson, int* actions_done, SPDBOptions* options);
R_API int r_bin_pdb_download(RCore *core, int isradjson, int *actions_done, SPDBOptions *options);
#ifdef __cplusplus
}