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:
Giovanni 2022-06-27 23:52:07 +02:00 committed by GitHub
parent 6567e6ba4e
commit 648882d544
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 3492 additions and 56 deletions

View file

@ -4,7 +4,6 @@ packages:
- devel/pkgconf
- devel/gmake
- devel/llvm
- archivers/cabextract
- ftp/wget
- lang/python
environment:

View file

@ -4,7 +4,6 @@ packages:
- pkgconf
- gmake
- clang
- cabextract
- python38
environment:
CXX: clang++

View file

@ -4,7 +4,6 @@ packages:
- devel/pkgconf
- devel/gmake
- devel/llvm
- archivers/cabextract
- lang/python
environment:
CXX: clang++

View file

@ -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 }}

View file

@ -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
View file

@ -126,4 +126,5 @@ subprojects/tree-sitter-*/
subprojects/zlib-*/
subprojects/sigdb/
subprojects/libdemangle/
subprojects/libmspack/
dist/windows/Output

View file

@ -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

View file

@ -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
View 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;
}

View file

@ -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);
}

View file

@ -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;
}
/**

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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:

View file

@ -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);

View file

@ -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',

View file

@ -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')

View file

@ -0,0 +1,4 @@
[wrap-git]
url = https://github.com/kyz/libmspack.git
revision = 46b2f2dd5e0e3742efde5fda785bacb637157336
patch_directory = libmspack

View 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 */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View 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
)

View file

@ -0,0 +1 @@
option('debug_prints', type: 'boolean', value: false, description: 'enables/disables debug printfs')

View file

@ -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