Add libmspack and add idpx to extracts compressed pdb (#2728)
* Add libmspack, cabextract and add idpx to extracts compressed pdb * Remove cabextract from CIs since it is not anymore required.
This commit is contained in:
parent
6567e6ba4e
commit
648882d544
25 changed files with 3492 additions and 56 deletions
|
|
@ -4,7 +4,6 @@ packages:
|
|||
- devel/pkgconf
|
||||
- devel/gmake
|
||||
- devel/llvm
|
||||
- archivers/cabextract
|
||||
- ftp/wget
|
||||
- lang/python
|
||||
environment:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ packages:
|
|||
- pkgconf
|
||||
- gmake
|
||||
- clang
|
||||
- cabextract
|
||||
- python38
|
||||
environment:
|
||||
CXX: clang++
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ packages:
|
|||
- devel/pkgconf
|
||||
- devel/gmake
|
||||
- devel/llvm
|
||||
- archivers/cabextract
|
||||
- lang/python
|
||||
environment:
|
||||
CXX: clang++
|
||||
|
|
|
|||
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
|
|
@ -161,12 +161,12 @@ jobs:
|
|||
if: matrix.enabled
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Install pkg-config and cabextract with Homebrew
|
||||
- name: Install pkg-config with Homebrew
|
||||
if: matrix.os == 'macos-11' && matrix.enabled
|
||||
run: brew install pkg-config cabextract
|
||||
run: brew install pkg-config
|
||||
- name: Install python and other dependencies
|
||||
if: (matrix.run_tests || matrix.build_system == 'meson') && matrix.os != 'macos-11' && matrix.enabled
|
||||
run: sudo apt-get --assume-yes install python3-wheel python3-setuptools cabextract
|
||||
run: sudo apt-get --assume-yes install python3-wheel python3-setuptools
|
||||
- name: Install meson and ninja
|
||||
if: matrix.build_system == 'meson' && matrix.enabled
|
||||
run: pip3 install --user meson ninja PyYAML
|
||||
|
|
@ -412,7 +412,7 @@ jobs:
|
|||
- name: Install tools
|
||||
run: apt-get update && apt-get install --yes patch unzip git gcc-11 make curl pkg-config libc6-i386 build-essential
|
||||
- name: Install python and other dependencies
|
||||
run: apt-get install --yes python3-wheel python3-setuptools python3-pip cabextract
|
||||
run: apt-get install --yes python3-wheel python3-setuptools python3-pip
|
||||
- name: Install meson and ninja
|
||||
run: pip3 install meson ninja PyYAML
|
||||
- name: Checkout rizin
|
||||
|
|
@ -454,7 +454,7 @@ jobs:
|
|||
options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: apk add --no-cache git gcc g++ linux-headers cmake curl wget unzip py3-wheel py3-setuptools py3-pip meson ninja xz cabextract
|
||||
run: apk add --no-cache git gcc g++ linux-headers cmake curl wget unzip py3-wheel py3-setuptools py3-pip meson ninja xz
|
||||
- name: Checkout rizin
|
||||
run: |
|
||||
git clone https://github.com/${{ github.repository }}
|
||||
|
|
|
|||
2
.github/workflows/coverity-scan.yml
vendored
2
.github/workflows/coverity-scan.yml
vendored
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
|
||||
- name: Installing build dependencies
|
||||
run: |
|
||||
sudo apt-get --assume-yes install python3-wheel python3-setuptools cabextract
|
||||
sudo apt-get --assume-yes install python3-wheel python3-setuptools
|
||||
pip3 install --user meson ninja PyYAML
|
||||
if: steps.determine-repo.outputs.repo == 'rizinorg/rizin'
|
||||
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -126,4 +126,5 @@ subprojects/tree-sitter-*/
|
|||
subprojects/zlib-*/
|
||||
subprojects/sigdb/
|
||||
subprojects/libdemangle/
|
||||
subprojects/libmspack/
|
||||
dist/windows/Output
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ jobs:
|
|||
- binutils-aarch64-linux-gnu
|
||||
- binutils-arm-linux-gnueabi
|
||||
- binutils-x86-64-linux-gnu
|
||||
- cabextract
|
||||
# Linux with GCC on System Z
|
||||
- os: linux
|
||||
name: S390X
|
||||
|
|
@ -30,7 +29,6 @@ jobs:
|
|||
apt:
|
||||
packages:
|
||||
- binutils-mingw-w64-x86-64
|
||||
- cabextract
|
||||
# Linux with GCC on ARMv8 (64bit)
|
||||
- os: linux
|
||||
name: ARM64
|
||||
|
|
@ -43,7 +41,6 @@ jobs:
|
|||
- binutils-arm-linux-gnueabi
|
||||
- binutils-x86-64-linux-gnu
|
||||
- binutils-powerpc64le-linux-gnu
|
||||
- cabextract
|
||||
|
||||
allow_failures:
|
||||
# Linux with GCC on System Z
|
||||
|
|
@ -54,7 +51,6 @@ jobs:
|
|||
apt:
|
||||
packages:
|
||||
- binutils-mingw-w64-x86-64
|
||||
- cabextract
|
||||
|
||||
cache:
|
||||
- ccache
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@ rz_bin_sources = [
|
|||
'format/wasm/wasm.c',
|
||||
'format/zimg/zimg.c',
|
||||
|
||||
'pdb/cab_extract.c',
|
||||
'pdb/dbi.c',
|
||||
'pdb/gdata.c',
|
||||
'pdb/omap.c',
|
||||
|
|
@ -262,6 +263,7 @@ rz_bin = library('rz_bin', rz_bin_sources,
|
|||
rz_cons_dep,
|
||||
rz_io_dep,
|
||||
rz_type_dep,
|
||||
libmspack_dep,
|
||||
],
|
||||
install: true,
|
||||
implicit_include_directories: false,
|
||||
|
|
|
|||
257
librz/bin/pdb/cab_extract.c
Normal file
257
librz/bin/pdb/cab_extract.c
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
// SPDX-FileCopyrightText: 2022 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_bin.h>
|
||||
#include <rz_type.h>
|
||||
#include <mspack.h>
|
||||
|
||||
#include "pdb.h"
|
||||
|
||||
// checks all the files and guesses if is using unix or win paths
|
||||
static bool is_cab_using_unix_paths(struct mscabd_file *files) {
|
||||
bool slash = false, backslash = false;
|
||||
struct mscabd_file *fi = NULL;
|
||||
|
||||
for (fi = files; fi; fi = fi->next) {
|
||||
for (char *p = fi->filename; *p; p++) {
|
||||
if (*p == '/') {
|
||||
slash = true;
|
||||
} else if (*p == '\\') {
|
||||
backslash = true;
|
||||
}
|
||||
}
|
||||
if (slash && backslash) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!slash) {
|
||||
/* no slashes, therefore is windows */
|
||||
return false;
|
||||
} else if (!backslash) {
|
||||
/* slashes but no backslashes, therefore is unix */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* check if starts with a slash */
|
||||
if (!files->next) {
|
||||
char c, *p = fi->filename;
|
||||
while ((c = *p++)) {
|
||||
if (c == '\\') {
|
||||
return false; /* is windows */
|
||||
} else if (c == '/') {
|
||||
return true; /* is unix */
|
||||
}
|
||||
}
|
||||
/* impossible scenario since at least one slash was found */
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *oldname = NULL;
|
||||
size_t oldlen = 0;
|
||||
for (fi = files; fi; fi = fi->next) {
|
||||
const char *name = fi->filename;
|
||||
size_t len = 0;
|
||||
while (name[len]) {
|
||||
if ((name[len] == '\\') || (name[len] == '/')) {
|
||||
break;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
if (!name[len]) {
|
||||
len = 0;
|
||||
} else {
|
||||
len++;
|
||||
if (len == oldlen && !strncmp(name, oldname, len)) {
|
||||
return name[len - 1] != '\\';
|
||||
}
|
||||
}
|
||||
|
||||
oldname = name;
|
||||
oldlen = len;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_slash(const char *str) {
|
||||
return *str == '/' || *str == '\\';
|
||||
}
|
||||
|
||||
static bool is_previous_dir(const char *path) {
|
||||
return path[0] == '.' && path[1] == '.' && is_slash(path + 2);
|
||||
}
|
||||
|
||||
static char *sanitize_cab_filename(struct mscabd_file *file, const char *output_dir, bool is_unix) {
|
||||
char separator = '\\';
|
||||
char os_slash = '/';
|
||||
if (is_unix) {
|
||||
separator = '/';
|
||||
os_slash = '\\';
|
||||
}
|
||||
|
||||
size_t output_dir_len = strlen(output_dir) + 1; // includes the path separator
|
||||
size_t filename_len = strlen(file->filename);
|
||||
|
||||
char *sanitized = RZ_NEWS0(char, output_dir_len + (filename_len * 4) + 2);
|
||||
if (!sanitized) {
|
||||
RZ_LOG_ERROR("Cannot allocate sanitized name\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const ut8 *input = (const ut8 *)&file->filename[0];
|
||||
const ut8 *endp = (const ut8 *)&file->filename[filename_len];
|
||||
ut8 *output = (ut8 *)&sanitized[output_dir_len];
|
||||
|
||||
memcpy(sanitized, output_dir, output_dir_len);
|
||||
sanitized[output_dir_len - 1] = '/';
|
||||
|
||||
if (file->attribs & MSCAB_ATTRIB_UTF_NAME) {
|
||||
// sanitize utf-8 filename
|
||||
RzRune rune;
|
||||
for (; input < endp;) {
|
||||
rune = 0;
|
||||
int len = rz_utf8_decode(input, endp - input, &rune);
|
||||
if (!len) {
|
||||
len = 1;
|
||||
rune = 0xFFFD;
|
||||
} else if (rune <= 0 || rune > 0x10FFFF || (rune >= 0xD800 && rune <= 0xDFFF) || rune == 0xFFFE || rune == 0xFFFF) {
|
||||
len = 1;
|
||||
rune = 0xFFFD;
|
||||
}
|
||||
input += len;
|
||||
|
||||
if (rune == separator) {
|
||||
rune = '/';
|
||||
} else if (rune == os_slash) {
|
||||
rune = '\\';
|
||||
}
|
||||
|
||||
len = rz_utf8_encode(output, rune);
|
||||
output += len;
|
||||
}
|
||||
*output++ = '\0';
|
||||
} else {
|
||||
// sanitize ascii filename
|
||||
ut8 c = 0;
|
||||
while (input < endp) {
|
||||
c = *input++;
|
||||
if (c == separator) {
|
||||
c = '/';
|
||||
} else if (c == os_slash) {
|
||||
c = '\\';
|
||||
}
|
||||
*output++ = c;
|
||||
}
|
||||
*output++ = '\0';
|
||||
}
|
||||
|
||||
output = (ut8 *)&sanitized[output_dir_len];
|
||||
for (input = output; is_slash((const char *)input); input++) {
|
||||
// skip any leading slashes in the cab filename part
|
||||
}
|
||||
|
||||
if (input != output) {
|
||||
size_t len = strlen((char *)input);
|
||||
if (len > 0) {
|
||||
memmove(output, input, len + 1);
|
||||
} else {
|
||||
/* change filename composed entirely of leading slashes to underscores */
|
||||
strcpy((char *)output, "_");
|
||||
}
|
||||
}
|
||||
|
||||
// remove any "../" or "..\" in the filename
|
||||
for (; *output; output++) {
|
||||
if (is_previous_dir((const char *)output)) {
|
||||
output[0] = output[1] = '_';
|
||||
output += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
static const char *cab_error(struct mscab_decompressor *cd) {
|
||||
switch (cd->last_error(cd)) {
|
||||
case MSPACK_ERR_OPEN:
|
||||
return "MSPACK_ERR_OPEN";
|
||||
case MSPACK_ERR_READ:
|
||||
return "MSPACK_ERR_READ";
|
||||
case MSPACK_ERR_WRITE:
|
||||
return "MSPACK_ERR_WRITE";
|
||||
case MSPACK_ERR_SEEK:
|
||||
return "MSPACK_ERR_SEEK";
|
||||
case MSPACK_ERR_NOMEMORY:
|
||||
return "MSPACK_ERR_NOMEMORY";
|
||||
case MSPACK_ERR_SIGNATURE:
|
||||
return "MSPACK_ERR_SIGNATURE";
|
||||
case MSPACK_ERR_DATAFORMAT:
|
||||
return "MSPACK_ERR_DATAFORMAT";
|
||||
case MSPACK_ERR_CHECKSUM:
|
||||
return "MSPACK_ERR_CHECKSUM";
|
||||
case MSPACK_ERR_DECRUNCH:
|
||||
return "MSPACK_ERR_DECRUNCH";
|
||||
default:
|
||||
rz_warn_if_reached();
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Extracts compressed PDB files into a folder.
|
||||
*
|
||||
* \param file_cab The file cab
|
||||
* \param output_dir The output dir
|
||||
*
|
||||
* \return On success returns true, otherwise false.
|
||||
*/
|
||||
RZ_API bool rz_bin_pdb_extract_in_folder(RZ_NONNULL const char *file_cab, RZ_NONNULL const char *output_dir) {
|
||||
rz_return_val_if_fail(file_cab && output_dir, false);
|
||||
|
||||
if (!rz_file_exists(file_cab)) {
|
||||
RZ_LOG_ERROR("%s is not a file or does not exist.\n", file_cab);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rz_file_is_directory(output_dir)) {
|
||||
RZ_LOG_ERROR("%s is not a directory or does not exist.\n", output_dir);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct mscab_decompressor *cabd = NULL;
|
||||
struct mscabd_cabinet *cab = NULL;
|
||||
|
||||
if (!(cabd = mspack_create_cab_decompressor(NULL))) {
|
||||
RZ_LOG_ERROR("Cannot allocate mscab_decompressor.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(cab = cabd->open(cabd, file_cab))) {
|
||||
RZ_LOG_ERROR("Invalid compressed cab file: %s\n", file_cab);
|
||||
mspack_destroy_cab_decompressor(cabd);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
bool is_unix = is_cab_using_unix_paths(cab->files);
|
||||
for (struct mscabd_file *file = cab->files; file; file = file->next) {
|
||||
char *new_name = sanitize_cab_filename(file, output_dir, is_unix);
|
||||
if (!new_name) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
if (cabd->extract(cabd, file, new_name)) {
|
||||
RZ_LOG_ERROR("cab_extract: %s: %s\n", new_name, cab_error(cabd));
|
||||
free(new_name);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
RZ_LOG_INFO("cab_extract: extracted %s\n", new_name);
|
||||
free(new_name);
|
||||
}
|
||||
|
||||
cabd->close(cabd, cab);
|
||||
mspack_destroy_cab_decompressor(cabd);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
#include <rz_type.h>
|
||||
#include <string.h>
|
||||
#include <rz_demangler.h>
|
||||
#include <mspack.h>
|
||||
|
||||
#include "pdb.h"
|
||||
|
||||
|
|
@ -271,6 +272,17 @@ error:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool is_compressed_pdb(RzBuffer *buf) {
|
||||
ut8 magic[4] = { 0 };
|
||||
// avoids to seek back, when using rz_buf_read_at
|
||||
if (rz_buf_read_at(buf, 0, magic, sizeof(magic)) != sizeof(magic)) {
|
||||
return false;
|
||||
} else if (memcmp(magic, CAB_SIGNATURE, sizeof(magic))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Parse PDB file given the path
|
||||
*
|
||||
|
|
@ -281,9 +293,16 @@ RZ_API RZ_OWN RzPdb *rz_bin_pdb_parse_from_file(RZ_NONNULL const char *filename)
|
|||
rz_return_val_if_fail(filename, NULL);
|
||||
RzBuffer *buf = rz_buf_new_slurp(filename);
|
||||
if (!buf) {
|
||||
eprintf("%s: Error reading file \"%s\"\n", __FUNCTION__, filename);
|
||||
RZ_LOG_ERROR("%s: Error reading file \"%s\"\n", __FUNCTION__, filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_compressed_pdb(buf)) {
|
||||
rz_buf_free(buf);
|
||||
RZ_LOG_ERROR("The pdb file %s seems to be compressed, please use idpx command to extract the contents.\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rz_bin_pdb_parse_from_buf(buf);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,14 +8,6 @@
|
|||
#include <rz_socket.h>
|
||||
#include "pdb_downloader.h"
|
||||
|
||||
static bool checkExtract(void) {
|
||||
#if __WINDOWS__
|
||||
return rz_sys_system("expand -? >nul") == 0;
|
||||
#else
|
||||
return rz_sys_system("cabextract -v > /dev/null") == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool download_and_write(SPDBDownloaderOpt *opt, const char *file) {
|
||||
char *dir = rz_str_newf("%s%s%s%s%s",
|
||||
opt->symbol_store_path, RZ_SYS_DIR,
|
||||
|
|
@ -66,8 +58,7 @@ static bool download_and_write(SPDBDownloaderOpt *opt, const char *file) {
|
|||
|
||||
static char *download(struct SPDBDownloader *pd) {
|
||||
SPDBDownloaderOpt *opt = pd->opt;
|
||||
int res = 0;
|
||||
int cmd_ret;
|
||||
bool downloaded = false;
|
||||
|
||||
if (!opt->dbg_file || !*opt->dbg_file) {
|
||||
// no pdb debug file
|
||||
|
|
@ -85,7 +76,7 @@ static char *download(struct SPDBDownloader *pd) {
|
|||
return abspath_to_file;
|
||||
}
|
||||
|
||||
if (checkExtract() || opt->extract == 0) {
|
||||
if (opt->extract == 0) {
|
||||
char *extractor_cmd = NULL;
|
||||
char *archive_name = strdup(opt->dbg_file);
|
||||
archive_name[strlen(archive_name) - 1] = '_';
|
||||
|
|
@ -94,50 +85,32 @@ static char *download(struct SPDBDownloader *pd) {
|
|||
opt->dbg_file, RZ_SYS_DIR,
|
||||
opt->guid, RZ_SYS_DIR,
|
||||
archive_name);
|
||||
char *abspath_to_dir = rz_file_dirname(abspath_to_archive);
|
||||
|
||||
eprintf("Attempting to download compressed pdb in %s\n", abspath_to_archive);
|
||||
char *abs_arch_esc = rz_str_escape_sh(abspath_to_archive);
|
||||
#if __WINDOWS__
|
||||
char *abs_file_esc = rz_str_escape_sh(abspath_to_file);
|
||||
// expand %1 %2
|
||||
// %1 - absolute path to archive
|
||||
// %2 - absolute path to file that will be dearchive
|
||||
extractor_cmd = rz_str_newf("expand \"%s\" \"%s\"", abs_arch_esc, abs_file_esc);
|
||||
free(abs_file_esc);
|
||||
#else
|
||||
char *abspath_to_dir = rz_file_dirname(abspath_to_archive);
|
||||
char *abs_dir_esc = rz_str_escape_sh(abspath_to_dir);
|
||||
// cabextract -d %1 %2
|
||||
// %1 - path to directory where to extract all files from cab archive
|
||||
// %2 - absolute path to cab archive
|
||||
extractor_cmd = rz_str_newf("cabextract -d \"%s\" \"%s\"", abs_arch_esc, abs_dir_esc);
|
||||
free(abs_dir_esc);
|
||||
free(abspath_to_dir);
|
||||
#endif
|
||||
free(abs_arch_esc);
|
||||
res = download_and_write(opt, archive_name);
|
||||
downloaded = download_and_write(opt, archive_name);
|
||||
|
||||
if (opt->extract > 0 && res) {
|
||||
if (opt->extract > 0 && downloaded) {
|
||||
eprintf("Attempting to decompress pdb\n");
|
||||
if (res && ((cmd_ret = rz_sys_system(extractor_cmd)) != 0)) {
|
||||
eprintf("cab extractor exited with error %d\n", cmd_ret);
|
||||
res = 0;
|
||||
if (!rz_bin_pdb_extract_in_folder(abspath_to_archive, abspath_to_dir)) {
|
||||
downloaded = false;
|
||||
}
|
||||
rz_file_rm(abspath_to_archive);
|
||||
}
|
||||
free(archive_name);
|
||||
free(abspath_to_dir);
|
||||
free(abspath_to_archive);
|
||||
free(extractor_cmd);
|
||||
}
|
||||
if (res == 0) {
|
||||
if (!downloaded) {
|
||||
eprintf("Falling back to uncompressed pdb\n");
|
||||
eprintf("Attempting to download uncompressed pdb in %s\n", abspath_to_file);
|
||||
res = download_and_write(opt, opt->dbg_file);
|
||||
if (!res) {
|
||||
free(abspath_to_file);
|
||||
downloaded = download_and_write(opt, opt->dbg_file);
|
||||
if (!downloaded) {
|
||||
RZ_FREE(abspath_to_file);
|
||||
}
|
||||
}
|
||||
return res ? abspath_to_file : NULL;
|
||||
return downloaded ? abspath_to_file : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -522,8 +522,17 @@ RZ_IPI RzCmdStatus rz_cmd_info_pdb_download_handler(RzCore *core, int argc, cons
|
|||
if (state->mode == RZ_OUTPUT_MODE_JSON) {
|
||||
pj_end(state->d.pj);
|
||||
}
|
||||
if (r > 0) {
|
||||
eprintf("Error while downloading pdb file\n");
|
||||
if (r > 0 && state->mode != RZ_OUTPUT_MODE_JSON) {
|
||||
RZ_LOG_ERROR("Error while downloading pdb file\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
RZ_IPI RzCmdStatus rz_cmd_pdb_extract_handler(RzCore *core, int argc, const char **argv) {
|
||||
const char *file_cab = argv[1];
|
||||
const char *output_dir = argv[2];
|
||||
if (!rz_bin_pdb_extract_in_folder(file_cab, output_dir)) {
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
return RZ_CMD_STATUS_OK;
|
||||
|
|
|
|||
|
|
@ -395,6 +395,7 @@ static const RzCmdDescArg cmd_info_class_fields_args[2];
|
|||
static const RzCmdDescArg cmd_info_class_methods_args[2];
|
||||
static const RzCmdDescArg cmd_info_pdb_load_args[2];
|
||||
static const RzCmdDescArg cmd_info_pdb_show_args[2];
|
||||
static const RzCmdDescArg cmd_pdb_extract_args[3];
|
||||
static const RzCmdDescArg cmd_info_demangle_args[3];
|
||||
static const RzCmdDescArg cmd_info_kuery_args[2];
|
||||
static const RzCmdDescArg cmd_info_plugins_args[2];
|
||||
|
|
@ -8998,6 +8999,24 @@ static const RzCmdDescHelp cmd_info_pdb_download_help = {
|
|||
.args = cmd_info_pdb_download_args,
|
||||
};
|
||||
|
||||
static const RzCmdDescArg cmd_pdb_extract_args[] = {
|
||||
{
|
||||
.name = "file.pdb",
|
||||
.type = RZ_CMD_ARG_TYPE_FILE,
|
||||
|
||||
},
|
||||
{
|
||||
.name = "output_dir",
|
||||
.type = RZ_CMD_ARG_TYPE_FILE,
|
||||
|
||||
},
|
||||
{ 0 },
|
||||
};
|
||||
static const RzCmdDescHelp cmd_pdb_extract_help = {
|
||||
.summary = "Extracts a compressed PDB file to a folder",
|
||||
.args = cmd_pdb_extract_args,
|
||||
};
|
||||
|
||||
static const RzCmdDescHelp iD_help = {
|
||||
.summary = "Demangle symbol for given language",
|
||||
};
|
||||
|
|
@ -16120,6 +16139,9 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
|
|||
RzCmdDesc *cmd_info_pdb_download_cd = rz_cmd_desc_argv_state_new(core->rcmd, idp_cd, "idpd", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_info_pdb_download_handler, &cmd_info_pdb_download_help);
|
||||
rz_warn_if_fail(cmd_info_pdb_download_cd);
|
||||
|
||||
RzCmdDesc *cmd_pdb_extract_cd = rz_cmd_desc_argv_new(core->rcmd, idp_cd, "idpx", rz_cmd_pdb_extract_handler, &cmd_pdb_extract_help);
|
||||
rz_warn_if_fail(cmd_pdb_extract_cd);
|
||||
|
||||
RzCmdDesc *iD_cd = rz_cmd_desc_group_new(core->rcmd, i_cd, "iD", rz_cmd_info_demangle_handler, &cmd_info_demangle_help, &iD_help);
|
||||
rz_warn_if_fail(iD_cd);
|
||||
RzCmdDesc *cmd_info_demangle_list_cd = rz_cmd_desc_argv_state_new(core->rcmd, iD_cd, "iDl", RZ_OUTPUT_MODE_TABLE | RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_QUIET, rz_cmd_info_demangle_list_handler, &cmd_info_demangle_list_help);
|
||||
|
|
|
|||
|
|
@ -640,6 +640,7 @@ RZ_IPI RzCmdStatus rz_cmd_info_dwarf_handler(RzCore *core, int argc, const char
|
|||
RZ_IPI RzCmdStatus rz_cmd_info_pdb_load_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
|
||||
RZ_IPI RzCmdStatus rz_cmd_info_pdb_show_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
|
||||
RZ_IPI RzCmdStatus rz_cmd_info_pdb_download_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
|
||||
RZ_IPI RzCmdStatus rz_cmd_pdb_extract_handler(RzCore *core, int argc, const char **argv);
|
||||
RZ_IPI RzCmdStatus rz_cmd_info_demangle_handler(RzCore *core, int argc, const char **argv);
|
||||
RZ_IPI char **rz_cmd_info_demangle_lang_choices(RzCore *core);
|
||||
RZ_IPI RzCmdStatus rz_cmd_info_demangle_list_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
|
||||
|
|
|
|||
|
|
@ -136,6 +136,14 @@ commands:
|
|||
- RZ_OUTPUT_MODE_STANDARD
|
||||
- RZ_OUTPUT_MODE_JSON
|
||||
args: []
|
||||
- name: idpx
|
||||
summary: Extracts a compressed PDB file to a folder
|
||||
cname: cmd_pdb_extract
|
||||
args:
|
||||
- name: file.pdb
|
||||
type: RZ_CMD_ARG_TYPE_FILE
|
||||
- name: output_dir
|
||||
type: RZ_CMD_ARG_TYPE_FILE
|
||||
- name: iD
|
||||
summary: Demangle symbol for given language
|
||||
subcommands:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CAB_SIGNATURE "MSCF"
|
||||
#define PDB_SIGNATURE "Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\x00\x00\x00"
|
||||
#define PDB_SIGNATURE_LEN 32
|
||||
|
||||
|
|
@ -250,6 +251,7 @@ typedef struct rz_pdb_t {
|
|||
} RzPdb;
|
||||
|
||||
// PDB
|
||||
RZ_API bool rz_bin_pdb_extract_in_folder(RZ_NONNULL const char *file_cab, RZ_NONNULL const char *output_dir);
|
||||
RZ_API RZ_OWN RzPdb *rz_bin_pdb_parse_from_file(RZ_NONNULL const char *filename);
|
||||
RZ_API RZ_OWN RzPdb *rz_bin_pdb_parse_from_buf(RZ_NONNULL const RzBuffer *buf);
|
||||
RZ_API void rz_bin_pdb_free(RzPdb *pdb);
|
||||
|
|
|
|||
15
meson.build
15
meson.build
|
|
@ -292,6 +292,20 @@ if sys_magic_opt.enabled() or sys_magic_opt.auto()
|
|||
endif
|
||||
endif
|
||||
|
||||
# handle libmspack library
|
||||
sys_libmspack_opt = get_option('use_sys_libmspack')
|
||||
libmspack_dep = disabler()
|
||||
if sys_libmspack_opt.enabled() or sys_libmspack_opt.auto()
|
||||
libmspack_dep = dependency('libmspack', required: false, static: is_static_build)
|
||||
if not libmspack_dep.found()
|
||||
libmspack_dep = cc.find_library('mspack', required: sys_libmspack_opt, static: is_static_build)
|
||||
endif
|
||||
endif
|
||||
if (sys_libmspack_opt.auto() and not libmspack_dep.found()) or sys_libmspack_opt.disabled()
|
||||
libmspack_proj = subproject('libmspack', default_options: ['default_library=static'])
|
||||
libmspack_dep = libmspack_proj.get_variable('libmspack_dep')
|
||||
endif
|
||||
|
||||
# handle xxhash library
|
||||
r = run_command(py3_exe, check_meson_subproject_py, 'xxhash', check: false)
|
||||
if r.returncode() == 1 and get_option('subprojects_check')
|
||||
|
|
@ -751,6 +765,7 @@ summary({
|
|||
'Capstone version': capstone_dep.version(),
|
||||
'System magic library': sys_magic.found() and sys_magic.type_name() != 'internal',
|
||||
'System xxhash library': xxhash_dep.found() and xxhash_dep.type_name() != 'internal',
|
||||
'System libmspack library': libmspack_dep.found() and libmspack_dep.type_name() != 'internal',
|
||||
'System openssl library': sys_openssl.found() and sys_openssl.type_name() != 'internal',
|
||||
'System libuv library': libuv_dep.found() and libuv_dep.type_name() != 'internal',
|
||||
'System capstone library': capstone_dep.found() and capstone_dep.type_name() != 'internal',
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ option('use_sys_zlib', type: 'feature', value: 'disabled')
|
|||
option('use_sys_lz4', type: 'feature', value: 'disabled')
|
||||
option('use_sys_xxhash', type: 'feature', value: 'disabled')
|
||||
option('use_sys_openssl', type: 'feature', value: 'disabled')
|
||||
option('use_sys_libmspack', type: 'feature', value: 'disabled')
|
||||
option('use_sys_tree_sitter', type: 'feature', value: 'disabled')
|
||||
option('use_sys_libuv', type: 'feature', value: 'auto', description: 'Whether to force, suggest or not use at all the system version of libuv. If system version is not found, one is built statically, unless use_libuv is false.')
|
||||
option('use_libuv', type: 'boolean', value: true, description: 'If true, libuv is used to handle remote features')
|
||||
|
|
|
|||
4
subprojects/libmspack.wrap
Normal file
4
subprojects/libmspack.wrap
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[wrap-git]
|
||||
url = https://github.com/kyz/libmspack.git
|
||||
revision = 46b2f2dd5e0e3742efde5fda785bacb637157336
|
||||
patch_directory = libmspack
|
||||
89
subprojects/packagefiles/libmspack/config.h.inc
Normal file
89
subprojects/packagefiles/libmspack/config.h.inc
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef MSPACK_CONFIG_H
|
||||
#define MSPACK_CONFIG_H
|
||||
/* Define if building universal (internal helper macro) */
|
||||
|
||||
/* Turn debugging mode on? */
|
||||
#define DEBUG @DEBUG@
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H @HAVE_DLFCN_H@
|
||||
|
||||
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
|
||||
#define HAVE_FSEEKO @HAVE_FSEEKO@
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H @HAVE_INTTYPES_H@
|
||||
|
||||
/* Define to 1 if you have the `mkdir' function. */
|
||||
#define HAVE_MKDIR @HAVE_MKDIR@
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H @HAVE_STDINT_H@
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H @HAVE_STDIO_H@
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H @HAVE_STDLIB_H@
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H @HAVE_STRINGS_H@
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H @HAVE_STRING_H@
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@
|
||||
|
||||
/* Define to 1 if you have the `towlower' function. */
|
||||
#define HAVE_TOWLOWER @HAVE_TOWLOWER@
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H @HAVE_UNISTD_H@
|
||||
|
||||
/* Define to 1 if you have the `_mkdir' function. */
|
||||
#define HAVE__MKDIR @HAVE__MKDIR@
|
||||
|
||||
/* Define if mkdir takes only one argument. */
|
||||
#define MKDIR_TAKES_ONE_ARG @MKDIR_TAKES_ONE_ARG@
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.10.1alpha"
|
||||
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
#define SIZEOF_OFF_T @SIZEOF_OFF_T@
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#define STDC_HEADERS @STDC_HEADERS@
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#define WORDS_BIGENDIAN @WORDS_BIGENDIAN@
|
||||
|
||||
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
|
||||
#define _LARGEFILE_SOURCE @_LARGEFILE_SOURCE@
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#define _LARGE_FILES @_LARGE_FILES@
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#if !(@HAVE_MODE_T@)
|
||||
#define mode_t int
|
||||
#endif
|
||||
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
#if !(@HAVE_OFF_T@)
|
||||
#define off_t long int
|
||||
#endif
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#if !(@HAVE_SIZE_T@)
|
||||
#define size_t unsigned int
|
||||
#endif
|
||||
|
||||
#endif /* MSPACK_CONFIG_H */
|
||||
1514
subprojects/packagefiles/libmspack/libmspack/mspack/cabd.c
Normal file
1514
subprojects/packagefiles/libmspack/libmspack/mspack/cabd.c
Normal file
File diff suppressed because it is too large
Load diff
1382
subprojects/packagefiles/libmspack/libmspack/mspack/chmd.c
Normal file
1382
subprojects/packagefiles/libmspack/libmspack/mspack/chmd.c
Normal file
File diff suppressed because it is too large
Load diff
125
subprojects/packagefiles/libmspack/meson.build
Normal file
125
subprojects/packagefiles/libmspack/meson.build
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
project('libmspack', 'c', version: '0.10.1alpha', license : ['LGPL2'], meson_version: '>=0.55.0')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
# handle libmspack dependency
|
||||
libmspack_files = [
|
||||
'libmspack' / 'mspack' / 'cabc.c',
|
||||
'libmspack' / 'mspack' / 'cabd.c',
|
||||
'libmspack' / 'mspack' / 'chmc.c',
|
||||
'libmspack' / 'mspack' / 'chmd.c',
|
||||
'libmspack' / 'mspack' / 'crc32.c',
|
||||
'libmspack' / 'mspack' / 'hlpc.c',
|
||||
'libmspack' / 'mspack' / 'hlpd.c',
|
||||
'libmspack' / 'mspack' / 'kwajc.c',
|
||||
'libmspack' / 'mspack' / 'kwajd.c',
|
||||
'libmspack' / 'mspack' / 'litc.c',
|
||||
'libmspack' / 'mspack' / 'litd.c',
|
||||
'libmspack' / 'mspack' / 'lzssd.c',
|
||||
'libmspack' / 'mspack' / 'lzxc.c',
|
||||
'libmspack' / 'mspack' / 'lzxd.c',
|
||||
'libmspack' / 'mspack' / 'mszipc.c',
|
||||
'libmspack' / 'mspack' / 'mszipd.c',
|
||||
'libmspack' / 'mspack' / 'oabc.c',
|
||||
'libmspack' / 'mspack' / 'oabd.c',
|
||||
'libmspack' / 'mspack' / 'qtmc.c',
|
||||
'libmspack' / 'mspack' / 'qtmd.c',
|
||||
'libmspack' / 'mspack' / 'system.c',
|
||||
'libmspack' / 'mspack' / 'szddc.c',
|
||||
'libmspack' / 'mspack' / 'szddd.c',
|
||||
]
|
||||
|
||||
config_data = configuration_data()
|
||||
if get_option('debug_prints')
|
||||
debug_c = 'libmspack' / 'mspack' / 'debug.c'
|
||||
libmspack_files += debug_c
|
||||
config_data.set('DEBUG', 1)
|
||||
else
|
||||
config_data.set('DEBUG', 0)
|
||||
endif
|
||||
|
||||
# check on headers
|
||||
foreach item : [
|
||||
['dlfcn.h', '', [], 'HAVE_DLFCN_H'],
|
||||
['inttypes.h', '', [], 'HAVE_INTTYPES_H'],
|
||||
['stdint.h', '', [], 'HAVE_STDINT_H'],
|
||||
['stdio.h', '', [], 'HAVE_STDIO_H'],
|
||||
['stdlib.h', '', [], 'HAVE_STDLIB_H'],
|
||||
['strings.h', '', [], 'HAVE_STRINGS_H'],
|
||||
['string.h', '', [], 'HAVE_STRING_H'],
|
||||
['sys/stat.h', '', [], 'HAVE_SYS_STAT_H'],
|
||||
['sys/types.h', '', [], 'HAVE_SYS_TYPES_H'],
|
||||
['unistd.h', '', [], 'HAVE_UNISTD_H'],
|
||||
]
|
||||
ok = cc.has_header(item[0], prefix: item[1], dependencies: item[2])
|
||||
config_data.set10(item[3], ok)
|
||||
endforeach
|
||||
|
||||
have_unistd_h = config_data.get('HAVE_UNISTD_H')
|
||||
have_stdlib_h = config_data.get('HAVE_STDLIB_H')
|
||||
have_string_h = config_data.get('HAVE_STRING_H')
|
||||
config_data.set10('STDC_HEADERS', have_stdlib_h == 1 and have_string_h == 1)
|
||||
|
||||
# check on functions
|
||||
foreach item : [
|
||||
['fseeko', '#include <stdio.h>', [], 'HAVE_FSEEKO'],
|
||||
['mkdir', '#include <sys/stat.h>', [], 'HAVE_MKDIR'],
|
||||
['_mkdir', '#include <direct.h>', [], 'HAVE__MKDIR'],
|
||||
['towlower', '#include <wctype.h>', [], 'HAVE_TOWLOWER'],
|
||||
]
|
||||
ok = cc.has_function(item[0], prefix: item[1], dependencies: item[2])
|
||||
config_data.set10(item[3], ok)
|
||||
endforeach
|
||||
|
||||
code = '#include <sys/stat.h>\n#if @0@\n#include <unistd.h>\n#endif\nint main(void) { mkdir ("."); return 0; }'.format(have_unistd_h)
|
||||
mkdir_takes_one_arg = cc.links(code, name: 'mkdir has one argument')
|
||||
config_data.set10('MKDIR_TAKES_ONE_ARG', mkdir_takes_one_arg)
|
||||
|
||||
# check types
|
||||
foreach item : [
|
||||
['mode_t', '#include <sys/types.h>', [], 'HAVE_MODE_T'],
|
||||
['off_t', '#include <sys/types.h>', [], 'HAVE_OFF_T'],
|
||||
['size_t', '#include <sys/types.h>', [], 'HAVE_SIZE_T'],
|
||||
]
|
||||
sz = cc.sizeof(item[0], prefix: item[1], dependencies: item[2])
|
||||
config_data.set10(item[3], sz > 0)
|
||||
endforeach
|
||||
|
||||
off_t_type = 'off_t'
|
||||
off_t_prfx = '#include <sys/types.h>'
|
||||
if config_data.get('HAVE_OFF_T') == 1
|
||||
off_t_type = 'long int'
|
||||
off_t_prfx = ''
|
||||
endif
|
||||
config_data.set('SIZEOF_OFF_T', cc.sizeof(off_t_type, prefix: off_t_prfx))
|
||||
|
||||
# check endianness
|
||||
is_big_endian = target_machine.endian() == 'big'
|
||||
config_data.set10('WORDS_BIGENDIAN', is_big_endian)
|
||||
|
||||
if host_machine.system() == 'aix'
|
||||
config_data.set('_LARGE_FILES', 1)
|
||||
config_data.set('_LARGEFILE_SOURCE', 0)
|
||||
else
|
||||
config_data.set('_LARGE_FILES', 0)
|
||||
config_data.set10('_LARGEFILE_SOURCE', host_machine.system() != 'windows')
|
||||
endif
|
||||
|
||||
config_h = configure_file(
|
||||
input: 'config.h.inc',
|
||||
output: 'config.h',
|
||||
configuration: config_data,
|
||||
)
|
||||
|
||||
libmspack_inc = [include_directories(['libmspack' / 'mspack', 'libmspack'])]
|
||||
|
||||
libmspack = static_library('libmspack', libmspack_files,
|
||||
dependencies: [],
|
||||
include_directories: libmspack_inc,
|
||||
implicit_include_directories: false
|
||||
)
|
||||
|
||||
libmspack_dep = declare_dependency(
|
||||
link_with: libmspack,
|
||||
include_directories: libmspack_inc
|
||||
)
|
||||
1
subprojects/packagefiles/libmspack/meson_options.txt
Normal file
1
subprojects/packagefiles/libmspack/meson_options.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
option('debug_prints', type: 'boolean', value: false, description: 'enables/disables debug printfs')
|
||||
|
|
@ -316,3 +316,21 @@ struct _TP_CALLBACK_ENVIRON_V3 {
|
|||
};
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=Extract pdb via idbx
|
||||
FILE==
|
||||
CMDS=<<EOF
|
||||
idpi bins/pdb/basic32.pd_
|
||||
e log.level=3
|
||||
idpx bins/pdb/basic32.pd_ .tmp
|
||||
!rz-hash -a md5 .tmp/basic32.pdb
|
||||
EOF
|
||||
REGEXP_FILTER_ERR=(ERROR:.+\nINFO:.+\n)
|
||||
EXPECT_ERR=<<EOF
|
||||
ERROR: The pdb file bins/pdb/basic32.pd_ seems to be compressed, please use idpx command to extract the contents.
|
||||
INFO: cab_extract: extracted .tmp/basic32.pdb
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
.tmp/basic32.pdb: 0x00000000-0x00649000 md5: a6c609e6b62cd0b9fbea5400bf370891
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
Loading…
Reference in a new issue