From 855825a5e07fbae5a29cbf078673e1612e9b41bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Tue, 6 Apr 2021 13:14:23 +0200 Subject: [PATCH 01/19] Update to new RzType Module (#221) --- src/RizinTypeFactory.cpp | 52 ++++++++++++++++++++-------------------- src/RizinTypeFactory.h | 16 ++++++------- test/db/extras/ghidra | 6 ++--- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/RizinTypeFactory.cpp b/src/RizinTypeFactory.cpp index 885053e0..d5621315 100644 --- a/src/RizinTypeFactory.cpp +++ b/src/RizinTypeFactory.cpp @@ -3,8 +3,8 @@ #include "RizinTypeFactory.h" #include "RizinArchitecture.h" -#include #include +#include #include "RizinUtils.h" @@ -12,26 +12,26 @@ RizinTypeFactory::RizinTypeFactory(RizinArchitecture *arch) : TypeFactory(arch), arch(arch) { - ctype = rz_parse_ctype_new(); + ctype = rz_type_ctype_new(); if(!ctype) throw LowlevelError("Failed to create RParseCType"); } RizinTypeFactory::~RizinTypeFactory() { - rz_parse_ctype_free(ctype); + rz_type_ctype_free(ctype); } -Datatype *RizinTypeFactory::addRizinStruct(RzAnalysisBaseType *type, std::set &stack_types) +Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::set &stack_types) { - assert(type->kind == RZ_ANALYSIS_BASE_TYPE_KIND_STRUCT); + assert(type->kind == RZ_BASE_TYPE_KIND_STRUCT); std::vector fields; try { TypeStruct *r = getTypeStruct(type->name); void *it; - rz_vector_foreach_cpp(&type->struct_data.members, [&](RzAnalysisStructMember *member) { + rz_vector_foreach_cpp(&type->struct_data.members, [&](RzTypeStructMember *member) { if(!member->type || !member->name) return; Datatype *member_type = fromCString(member->type, nullptr, &stack_types); @@ -67,13 +67,13 @@ Datatype *RizinTypeFactory::addRizinStruct(RzAnalysisBaseType *type, std::setkind == RZ_ANALYSIS_BASE_TYPE_KIND_ENUM); + assert(type->kind == RZ_BASE_TYPE_KIND_ENUM); std::vector namelist; std::vector vallist; std::vector assignlist; - rz_vector_foreach_cpp(&type->enum_data.cases, [&](RzAnalysisEnumCase *ceys) { + rz_vector_foreach_cpp(&type->enum_data.cases, [&](RzTypeEnumCase *ceys) { if(!ceys->name) return; namelist.push_back(ceys->name); @@ -95,9 +95,9 @@ Datatype *RizinTypeFactory::addRizinEnum(RzAnalysisBaseType *type) } } -Datatype *RizinTypeFactory::addRizinTypedef(RzAnalysisBaseType *type, std::set &stack_types) +Datatype *RizinTypeFactory::addRizinTypedef(RzBaseType *type, std::set &stack_types) { - assert(type->kind == RZ_ANALYSIS_BASE_TYPE_KIND_TYPEDEF); + assert(type->kind == RZ_BASE_TYPE_KIND_TYPEDEF); if(!type->type) return nullptr; Datatype *resolved = fromCString(type->type, nullptr, &stack_types); @@ -120,29 +120,29 @@ Datatype *RizinTypeFactory::queryRizin(const string &n, std::set &s Datatype *r = nullptr; RzCoreLock core(arch->getCore()); - RzAnalysisBaseType *type = rz_analysis_get_base_type(core->analysis, n.c_str()); + RzBaseType *type = rz_type_db_get_base_type(core->analysis->typedb, n.c_str()); if(!type || !type->name) { if(type) - rz_analysis_base_type_free(type); + rz_type_base_type_free(type); goto beach; } switch(type->kind) { - case RZ_ANALYSIS_BASE_TYPE_KIND_STRUCT: + case RZ_BASE_TYPE_KIND_STRUCT: r = addRizinStruct(type, stack_types); break; - case RZ_ANALYSIS_BASE_TYPE_KIND_ENUM: + case RZ_BASE_TYPE_KIND_ENUM: r = addRizinEnum(type); break; - case RZ_ANALYSIS_BASE_TYPE_KIND_TYPEDEF: + case RZ_BASE_TYPE_KIND_TYPEDEF: r = addRizinTypedef(type, stack_types); break; // TODO: atomic too? default: break; } - rz_analysis_base_type_free(type); + rz_type_base_type_free(type); beach: stack_types.erase(n); return r; @@ -165,24 +165,24 @@ Datatype *RizinTypeFactory::findById(const string &n, uint8 id) Datatype *RizinTypeFactory::fromCString(const string &str, string *error, std::set *stackTypes) { char *error_cstr = nullptr; - RParseCTypeType *type = rz_parse_ctype_parse(ctype, str.c_str(), &error_cstr); + RTypeCTypeType *type = rz_type_ctype_parse(ctype, str.c_str(), &error_cstr); if(error) *error = error_cstr ? error_cstr : ""; if(!type) return nullptr; Datatype *r = fromCType(type, error, stackTypes); - rz_parse_ctype_type_free(type); + rz_type_ctype_type_free(type); return r; } -Datatype *RizinTypeFactory::fromCType(const RParseCTypeType *ctype, string *error, std::set *stackTypes) +Datatype *RizinTypeFactory::fromCType(const RTypeCTypeType *ctype, string *error, std::set *stackTypes) { switch(ctype->kind) { - case RZ_PARSE_CTYPE_TYPE_KIND_IDENTIFIER: + case RZ_TYPE_CTYPE_TYPE_KIND_IDENTIFIER: { - if(ctype->identifier.kind == RZ_PARSE_CTYPE_IDENTIFIER_KIND_UNION) + if(ctype->identifier.kind == RZ_TYPE_CTYPE_IDENTIFIER_KIND_UNION) { if(error) *error = "Union types not supported in Decompiler"; @@ -196,13 +196,13 @@ Datatype *RizinTypeFactory::fromCType(const RParseCTypeType *ctype, string *erro *error = "Unknown type identifier " + std::string(ctype->identifier.name); return nullptr; } - if(ctype->identifier.kind == RZ_PARSE_CTYPE_IDENTIFIER_KIND_STRUCT && r->getMetatype() != TYPE_STRUCT) + if(ctype->identifier.kind == RZ_TYPE_CTYPE_IDENTIFIER_KIND_STRUCT && r->getMetatype() != TYPE_STRUCT) { if(error) *error = "Type identifier " + std::string(ctype->identifier.name) + " is not the name of a struct"; return nullptr; } - if(ctype->identifier.kind == RZ_PARSE_CTYPE_IDENTIFIER_KIND_ENUM && !r->isEnumType()) + if(ctype->identifier.kind == RZ_TYPE_CTYPE_IDENTIFIER_KIND_ENUM && !r->isEnumType()) { if(error) *error = "Type identifier " + std::string(ctype->identifier.name) + " is not the name of an enum"; @@ -210,7 +210,7 @@ Datatype *RizinTypeFactory::fromCType(const RParseCTypeType *ctype, string *erro } return r; } - case RZ_PARSE_CTYPE_TYPE_KIND_POINTER: + case RZ_TYPE_CTYPE_TYPE_KIND_POINTER: { Datatype *sub = fromCType(ctype->pointer.type, error, stackTypes); if(!sub) @@ -218,7 +218,7 @@ Datatype *RizinTypeFactory::fromCType(const RParseCTypeType *ctype, string *erro auto space = arch->getDefaultCodeSpace(); return this->getTypePointer(space->getAddrSize(), sub, space->getWordSize()); } - case RZ_PARSE_CTYPE_TYPE_KIND_ARRAY: + case RZ_TYPE_CTYPE_TYPE_KIND_ARRAY: { Datatype *sub = fromCType(ctype->array.type, error, stackTypes); if(!sub) diff --git a/src/RizinTypeFactory.h b/src/RizinTypeFactory.h index 91a78869..70337c9f 100644 --- a/src/RizinTypeFactory.h +++ b/src/RizinTypeFactory.h @@ -5,9 +5,9 @@ #include -typedef struct rz_parse_ctype_t RParseCType; -typedef struct rz_parse_ctype_type_t RParseCTypeType; -typedef struct rz_analysis_base_type_t RzAnalysisBaseType; +typedef struct rz_type_ctype_t RTypeCType; +typedef struct rz_type_ctype_type_t RTypeCTypeType; +typedef struct rz_base_type_t RzBaseType; class RizinArchitecture; @@ -15,11 +15,11 @@ class RizinTypeFactory : public TypeFactory { private: RizinArchitecture *arch; - RParseCType *ctype; + RTypeCType *ctype; - Datatype *addRizinStruct(RzAnalysisBaseType *type, std::set &stack_types); - Datatype *addRizinEnum(RzAnalysisBaseType *type); - Datatype *addRizinTypedef(RzAnalysisBaseType *type, std::set &stack_types); + Datatype *addRizinStruct(RzBaseType *type, std::set &stack_types); + Datatype *addRizinEnum(RzBaseType *type); + Datatype *addRizinTypedef(RzBaseType *type, std::set &stack_types); Datatype *queryRizin(const string &n, std::set &stack_types); protected: @@ -33,7 +33,7 @@ class RizinTypeFactory : public TypeFactory ~RizinTypeFactory() override; Datatype *fromCString(const string &str, string *error = nullptr, std::set *stackTypes = nullptr); - Datatype *fromCType(const RParseCTypeType *ctype, string *error = nullptr, std::set *stackTypes = nullptr); + Datatype *fromCType(const RTypeCTypeType *ctype, string *error = nullptr, std::set *stackTypes = nullptr); }; #endif //RZ_GHIDRA_RizinTYPEFACTORY_H diff --git a/test/db/extras/ghidra b/test/db/extras/ghidra index acc052ad..17e13533 100644 --- a/test/db/extras/ghidra +++ b/test/db/extras/ghidra @@ -2090,8 +2090,8 @@ afvr rsi s2 "const char *" @ sym.imp.strcmp to bins/types.h # TODO: remove when parsed struct from r2 is correct -k analysis/types/struct.Bright.ambassador=enum Ambassador,16,0 -k analysis/types/struct.Bright.window=struct Window,8,0 +tk struct.Bright.ambassador=enum Ambassador,16,0 +tk struct.Bright.window=struct Window,8,0 s sym.Aeropause afvr rdi bright "Bright *" @@ -3116,4 +3116,4 @@ void sym.imp.exit noreturn (void) return; } EOF -RUN \ No newline at end of file +RUN From 38a8b1bac81c65ad6c44d6d17c835fd6dcd4a16c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 7 Apr 2021 18:44:25 +0200 Subject: [PATCH 02/19] Update for dev/stable Split --- .github/workflows/ci.yml | 3 ++- .github/workflows/codeql-analysis.yml | 4 ++-- .mergify.yml | 8 -------- .travis.yml | 3 ++- README.md | 15 +++++++++++++++ 5 files changed, 21 insertions(+), 12 deletions(-) delete mode 100644 .mergify.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b61de180..2bac63c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,8 @@ name: CI on: push: branches: - - master + - dev + - stable pull_request: jobs: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1bf8f590..f6951851 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,9 +2,9 @@ name: "CodeQL" on: push: - branches: [master] + branches: [dev, stable] pull_request: - branches: [master] + branches: [dev, stable] schedule: - cron: '0 16 * * 0' diff --git a/.mergify.yml b/.mergify.yml deleted file mode 100644 index 7baa5660..00000000 --- a/.mergify.yml +++ /dev/null @@ -1,8 +0,0 @@ -pull_request_rules: - - name: merge on green with label - conditions: - - base=master - - label=merge-on-green - actions: - merge: - method: squash diff --git a/.travis.yml b/.travis.yml index d9ca12ab..6eeb68a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,8 @@ language: cpp branches: only: - - master + - dev + - stable jobs: fast_finish: true diff --git a/README.md b/README.md index 060c2399..812fffc7 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,21 @@ To also build the Cutter plugin, pass `-DBUILD_CUTTER_PLUGIN=ON -DCUTTER_SOURCE_ /my/path/rz-ghidra/build> make && make install ``` +## Versioning and Rizin Compatibility + +Rizin has a quickly evolving C API so it is necessary to be explicit about which versions +of rz-ghidra are compatible with which versions of Rizin: + +When using Rizin and rz-ghidra from git: +* rz-ghidra branch `dev` follows along Rizin branch `dev`. +* rz-ghidra branch `stable` follows along Rizin branch `stable`. + +Regarding releases, rz-ghidra is generally released simultaneously with Rizin and +often uses the same version numbers (but not guaranteed, do not depend on these numbers!). +Also, along with every Rizin release a tag like `rz-0.1.2` is created on rz-ghidra, which exactly +points to an rz-ghidra release and indicates that this release is compatible with the specified Rizin version. +These tags can be used by distribution maintainers to look up how to set up dependencies. + ## License Please note that this plugin is available under the **LGPLv3**, which From 529ae2c17c6162dba0bcffb30ef966f333d43365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 7 Apr 2021 19:43:19 +0200 Subject: [PATCH 03/19] Create Tarball in CI (Fix #219) --- .github/workflows/dist.yml | 63 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/dist.yml diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml new file mode 100644 index 00000000..823f34a2 --- /dev/null +++ b/.github/workflows/dist.yml @@ -0,0 +1,63 @@ +name: Distribution +on: + push: + branches: + +jobs: + tarball: + name: Create source tarball + if: startsWith(github.ref, 'refs/tags/deploy-test-') || startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Checkout submodules + run: | + git submodule init + git submodule update + - name: Create tarball + shell: bash + run: | + find . -name ".git*" | xargs rm -rfv + shopt -s extglob + mkdir rz-ghidra + mv !(rz-ghidra) rz-ghidra + tar -czvf rz-ghidra-src.tar.xz rz-ghidra + - uses: actions/upload-artifact@v2 + with: + name: rz-ghidra-src.tar.xz + path: rz-ghidra-src.tar.xz + + create-release: + name: Create draft release and upload artifacts + runs-on: ubuntu-latest + if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/deploy-test-') || startsWith(github.ref, 'refs/tags/v')) + needs: [ + tarball + ] + steps: + - uses: actions/checkout@v2 + - name: Extract version + id: extract_version + run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//} + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ steps.extract_version.outputs.version }} + draft: true + prerelease: false + - uses: actions/download-artifact@v2 + - name: Display structure of downloaded files + run: ls -R + - name: Upload rz-ghidra src tarball + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./rz-ghidra-src.tar.xz/rz-ghidra-src.tar.xz + asset_name: rz-ghidra-src-${{ steps.extract_version.outputs.version }}.tar.xz + asset_content_type: application/zip From 5d34a9addce8f4e993a60ccc3f11e88c5518b827 Mon Sep 17 00:00:00 2001 From: Paul I Date: Tue, 6 Apr 2021 21:28:06 +0300 Subject: [PATCH 04/19] Fix Windows build --- cmake/FindRizin.cmake | 3 ++- src/ArchMap.cpp | 4 ++-- src/ArchMap.h | 4 ++-- src/SleighAsm.h | 8 ++++++++ src/analysis_ghidra.cpp | 8 ++++---- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cmake/FindRizin.cmake b/cmake/FindRizin.cmake index 27c6a16a..ccbd62b8 100644 --- a/cmake/FindRizin.cmake +++ b/cmake/FindRizin.cmake @@ -17,7 +17,7 @@ if(WIN32) find_path(Rizin_INCLUDE_DIRS - NAMES rz_core.h rz_bin.h rz_util.h + NAMES rz_core.h rz_bin.h rz_util.h rz_type.h HINTS "$ENV{HOME}/bin/prefix/rizin/include/librz" /usr/local/include/librz @@ -53,6 +53,7 @@ if(WIN32) syscall socket magic + type crypto) set(Rizin_LIBRARIES "") diff --git a/src/ArchMap.cpp b/src/ArchMap.cpp index c9fed016..2f20230f 100644 --- a/src/ArchMap.cpp +++ b/src/ArchMap.cpp @@ -145,7 +145,7 @@ std::string CompilerFromCore(RzCore *core) return comp_it->second; } -std::string SleighIdFromCore(RzCore *core) +RZ_API std::string SleighIdFromCore(RzCore *core) { SleighArchitecture::collectSpecFiles(std::cerr); auto langs = SleighArchitecture::getLanguageDescriptions(); @@ -164,7 +164,7 @@ std::string StrToLower(std::string s) return s; } -std::string SleighIdFromSleighAsmConfig(const char *cpu, int bits, bool bigendian, const vector &langs) +RZ_API std::string SleighIdFromSleighAsmConfig(const char *cpu, int bits, bool bigendian, const vector &langs) { if(std::string(cpu).find(':') != string::npos) // complete id specified return cpu; diff --git a/src/ArchMap.h b/src/ArchMap.h index d8ee864d..6228dbd5 100644 --- a/src/ArchMap.h +++ b/src/ArchMap.h @@ -14,11 +14,11 @@ * For regular rizin plugins, guess the matching sleigh id, * for the specific sleigh plugin, same as SleighIdFromSleighAsmConfig() */ -std::string SleighIdFromCore(RzCore *core); +RZ_API std::string SleighIdFromCore(RzCore *core); /** * Match sleigh id from sleigh-plugin specific settings (asm.cpu) */ -std::string SleighIdFromSleighAsmConfig(const char *cpu, int bits, bool bigendian, const vector &langs); +RZ_API std::string SleighIdFromSleighAsmConfig(const char *cpu, int bits, bool bigendian, const vector &langs); #endif diff --git a/src/SleighAsm.h b/src/SleighAsm.h index af61551e..01b6d9e2 100644 --- a/src/SleighAsm.h +++ b/src/SleighAsm.h @@ -7,6 +7,14 @@ #include #include #include + +#ifdef LoadImage +#undef LoadImage +#endif +#ifdef CONST +#undef CONST +#endif + #include "architecture.hh" #include "sleigh_arch.hh" #include "SleighInstruction.h" diff --git a/src/analysis_ghidra.cpp b/src/analysis_ghidra.cpp index d02f4f3f..c8bc7d57 100644 --- a/src/analysis_ghidra.cpp +++ b/src/analysis_ghidra.cpp @@ -2371,7 +2371,7 @@ static bool sleigh_esil_float_add(RzAnalysisEsil *esil) long double tmp = s + d; auto raised = fetestexcept(FE_OVERFLOW); if(raised & FE_OVERFLOW) - ret = esil_pushnum_float(esil, 0.0 / 0.0); + ret = esil_pushnum_float(esil, NAN); else ret = esil_pushnum_float(esil, s + d); } @@ -2416,7 +2416,7 @@ static bool sleigh_esil_float_sub(RzAnalysisEsil *esil) long double tmp = d - s; auto raised = fetestexcept(FE_OVERFLOW); if(raised & FE_OVERFLOW) - ret = esil_pushnum_float(esil, 0.0 / 0.0); + ret = esil_pushnum_float(esil, NAN); else ret = esil_pushnum_float(esil, d - s); } @@ -2461,7 +2461,7 @@ static bool sleigh_esil_float_mul(RzAnalysisEsil *esil) long double tmp = s * d; auto raised = fetestexcept(FE_OVERFLOW); if(raised & FE_OVERFLOW) - ret = esil_pushnum_float(esil, 0.0 / 0.0); + ret = esil_pushnum_float(esil, NAN); else ret = esil_pushnum_float(esil, s * d); } @@ -2506,7 +2506,7 @@ static bool sleigh_esil_float_div(RzAnalysisEsil *esil) long double tmp = d / s; auto raised = fetestexcept(FE_OVERFLOW); if(raised & FE_OVERFLOW) - ret = esil_pushnum_float(esil, 0.0 / 0.0); + ret = esil_pushnum_float(esil, NAN); else ret = esil_pushnum_float(esil, d / s); } From 2ce213e6377113367d7d21c102efb46701bdcb6f Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Mon, 15 Mar 2021 13:53:21 +0800 Subject: [PATCH 05/19] Add Windows GHA CI --- .github/vsdevenv.ps1 | 10 ++++++++ .github/workflows/ci.yml | 54 ++++++++++++++++++++++++++++++++++++++++ cmake/FindRizin.cmake | 2 +- 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 .github/vsdevenv.ps1 diff --git a/.github/vsdevenv.ps1 b/.github/vsdevenv.ps1 new file mode 100644 index 00000000..f5732f3f --- /dev/null +++ b/.github/vsdevenv.ps1 @@ -0,0 +1,10 @@ +$bits = $args[0] +$installationPath = vswhere.exe -latest -property installationPath +if (-not $installationPath -or -not (test-path "$installationPath\VC\Auxiliary\Build\vcvars$bits.bat")) { + throw "vcvars$bits.bat file not found" +} +& "${env:COMSPEC}" /s /c "`"$installationPath\VC\Auxiliary\Build\vcvars$bits.bat`" > nul 2>&1 && set" | . { process { + if ($_ -match '^([^=]+)=(.*)') { + [System.Environment]::SetEnvironmentVariable($matches[1], $matches[2]) + } +}} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bac63c2..fc1119fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,13 @@ on: - stable pull_request: +env: + ARTIFACT_NAME: rz-ghidra-git + RIZIN_INSTALL_PREFIX: ${{ github.workspace }}/rizin-prefix + CUTTER_INSTALL_PATH: ${{ github.workspace }}/cutter + RIZIN_PLUGIN_PATH: /rizin/lib/plugins + CUTTER_PLUGIN_PATH: /cutter/plugins/native + jobs: build: strategy: @@ -30,3 +37,50 @@ jobs: run: cd scripts && docker build -t rz-ghidra . -f Dockerfile.${{ matrix.image }} && cd .. - name: Build and Test run: docker run --rm -v "`pwd`:/build" -t rz-ghidra /bin/bash -c "cd /build && scripts/ci-script ${{ matrix.args }}" + windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - uses: actions/setup-python@v2 + - name: Preparing msvc toolchain + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install meson ninja PyYAML + - uses: actions/checkout@v2 + with: + repository: rizinorg/rizin + path: rizin + - name: Extract rizin version + shell: pwsh + run: echo "##[set-output name=branch;]$( python sys\\version.py )" + id: extract_version + working-directory: rizin + - name: Build with meson + ninja + shell: pwsh + run: | + .github\vsdevenv.ps1 64 + meson --buildtype=release --prefix="${{ env.RIZIN_INSTALL_PREFIX }}" build + ninja -C build + ninja -C build install + working-directory: rizin + - name: Build Rz-Ghidra + shell: pwsh + run: | + .github\vsdevenv.ps1 64 + $env:ARTIFACT_PATH = "${{ github.workspace }}\${{ env.ARTIFACT_NAME }}" + $env:PATH = "$env:PATH;C:$env:HOMEPATH\AppData\Local\Programs\rizin\bin" + $env:PKG_CONFIG_PATH = "C:$env:HOMEPATH\AppData\Local\Programs\rizin\lib\pkgconfig" + $env:PKG_CONFIG_PATH + pkg-config --list-all + mkdir build + cd build + cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="${{ env.RIZIN_INSTALL_PREFIX }};${{ env.RIZIN_INSTALL_PREFIX }}\include\librz;${{ env.RIZIN_INSTALL_PREFIX }}\include\librz\sdb" -DCMAKE_INSTALL_PREFIX=${{ env.ARTIFACT_PATH }} -DBUILD_CUTTER_PLUGIN=OFF -DBUILD_SLEIGH_PLUGIN=OFF -DRIZIN_INSTALL_PLUGDIR=${{ env.RIZIN_PLUGIN_PATH }} + cmake --build . --config Release + cmake --build . --config Release --target install + diff --git a/cmake/FindRizin.cmake b/cmake/FindRizin.cmake index ccbd62b8..12f20800 100644 --- a/cmake/FindRizin.cmake +++ b/cmake/FindRizin.cmake @@ -25,7 +25,7 @@ if(WIN32) find_path(SDB_INCLUDE_DIR NAMES sdb.h sdbht.h sdb_version.h HINTS - "$ENV{HOME}/bin/prefix/rizin/include/libr/sdb" + "$ENV{HOME}/bin/prefix/rizin/include/librz/sdb" /usr/local/include/librz/sdb /usr/include/librz/sdb) From 863801eafb55dc77c57cf6c455a602cb910e4a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Tue, 13 Apr 2021 14:33:26 +0200 Subject: [PATCH 06/19] Update for RzTypeCTypeType -> RzType in Rizin 23fbbf889e8da41efca7ccb5e4e30c8a0837c427 (#227) --- src/RizinTypeFactory.cpp | 24 ++++++++++++------------ src/RizinTypeFactory.h | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/RizinTypeFactory.cpp b/src/RizinTypeFactory.cpp index d5621315..5aa1213f 100644 --- a/src/RizinTypeFactory.cpp +++ b/src/RizinTypeFactory.cpp @@ -12,14 +12,14 @@ RizinTypeFactory::RizinTypeFactory(RizinArchitecture *arch) : TypeFactory(arch), arch(arch) { - ctype = rz_type_ctype_new(); - if(!ctype) + parser = rz_ast_parser_new(); + if(!parser) throw LowlevelError("Failed to create RParseCType"); } RizinTypeFactory::~RizinTypeFactory() { - rz_type_ctype_free(ctype); + rz_ast_parser_free(parser); } Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::set &stack_types) @@ -165,22 +165,22 @@ Datatype *RizinTypeFactory::findById(const string &n, uint8 id) Datatype *RizinTypeFactory::fromCString(const string &str, string *error, std::set *stackTypes) { char *error_cstr = nullptr; - RTypeCTypeType *type = rz_type_ctype_parse(ctype, str.c_str(), &error_cstr); + RzType *type = rz_type_parse(parser, str.c_str(), &error_cstr); if(error) *error = error_cstr ? error_cstr : ""; if(!type) return nullptr; - Datatype *r = fromCType(type, error, stackTypes); - rz_type_ctype_type_free(type); + Datatype *r = fromRzType(type, error, stackTypes); + rz_type_free(type); return r; } -Datatype *RizinTypeFactory::fromCType(const RTypeCTypeType *ctype, string *error, std::set *stackTypes) +Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std::set *stackTypes) { switch(ctype->kind) { - case RZ_TYPE_CTYPE_TYPE_KIND_IDENTIFIER: + case RZ_TYPE_KIND_IDENTIFIER: { if(ctype->identifier.kind == RZ_TYPE_CTYPE_IDENTIFIER_KIND_UNION) { @@ -210,17 +210,17 @@ Datatype *RizinTypeFactory::fromCType(const RTypeCTypeType *ctype, string *error } return r; } - case RZ_TYPE_CTYPE_TYPE_KIND_POINTER: + case RZ_TYPE_KIND_POINTER: { - Datatype *sub = fromCType(ctype->pointer.type, error, stackTypes); + Datatype *sub = fromRzType(ctype->pointer.type, error, stackTypes); if(!sub) return nullptr; auto space = arch->getDefaultCodeSpace(); return this->getTypePointer(space->getAddrSize(), sub, space->getWordSize()); } - case RZ_TYPE_CTYPE_TYPE_KIND_ARRAY: + case RZ_TYPE_KIND_ARRAY: { - Datatype *sub = fromCType(ctype->array.type, error, stackTypes); + Datatype *sub = fromRzType(ctype->array.type, error, stackTypes); if(!sub) return nullptr; return this->getTypeArray(ctype->array.count, sub); diff --git a/src/RizinTypeFactory.h b/src/RizinTypeFactory.h index 70337c9f..feca933c 100644 --- a/src/RizinTypeFactory.h +++ b/src/RizinTypeFactory.h @@ -5,8 +5,8 @@ #include -typedef struct rz_type_ctype_t RTypeCType; -typedef struct rz_type_ctype_type_t RTypeCTypeType; +typedef struct rz_ast_parser_t RzASTParser; +typedef struct rz_type_t RzType; typedef struct rz_base_type_t RzBaseType; class RizinArchitecture; @@ -15,7 +15,7 @@ class RizinTypeFactory : public TypeFactory { private: RizinArchitecture *arch; - RTypeCType *ctype; + RzASTParser *parser; Datatype *addRizinStruct(RzBaseType *type, std::set &stack_types); Datatype *addRizinEnum(RzBaseType *type); @@ -33,7 +33,7 @@ class RizinTypeFactory : public TypeFactory ~RizinTypeFactory() override; Datatype *fromCString(const string &str, string *error = nullptr, std::set *stackTypes = nullptr); - Datatype *fromCType(const RTypeCTypeType *ctype, string *error = nullptr, std::set *stackTypes = nullptr); + Datatype *fromRzType(const RzType *ctype, string *error = nullptr, std::set *stackTypes = nullptr); }; #endif //RZ_GHIDRA_RizinTYPEFACTORY_H From 5feec47c9db7a0876c90bc748f69acb16de6719c Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Fri, 7 May 2021 18:52:07 +0800 Subject: [PATCH 07/19] Fix tests to use `rizin =` instead of `rizin -` (#233) --- test/db/extras/analysis_ghidra | 4 ++-- test/db/extras/asm_ghidra | 6 +++--- test/db/extras/ghidra | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/db/extras/analysis_ghidra b/test/db/extras/analysis_ghidra index 1665052e..23e6a9f4 100644 --- a/test/db/extras/analysis_ghidra +++ b/test/db/extras/analysis_ghidra @@ -197,7 +197,7 @@ EOF RUN NAME=v850cmp -FILE=- +FILE== EXPECT=< Date: Fri, 7 May 2021 19:54:26 +0800 Subject: [PATCH 08/19] Add missing include (#231) --- src/analysis_ghidra.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analysis_ghidra.cpp b/src/analysis_ghidra.cpp index c8bc7d57..191e6152 100644 --- a/src/analysis_ghidra.cpp +++ b/src/analysis_ghidra.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "SleighAsm.h" #include "SleighAnalysisValue.h" From c6c8348a84df056eef3611be4347b9c99a6b9449 Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Sat, 8 May 2021 16:47:02 +0800 Subject: [PATCH 09/19] Use extern "C" for exported symbols --- src/rz_ghidra.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rz_ghidra.h b/src/rz_ghidra.h index 30533696..1dd97dd5 100644 --- a/src/rz_ghidra.h +++ b/src/rz_ghidra.h @@ -4,6 +4,14 @@ #include #include +#if __cplusplus +extern "C" { +#endif + RZ_API RzAnnotatedCode *rz_ghidra_decompile_annotated_code(RzCore *core, ut64 addr); +#if __cplusplus +} +#endif + #endif //RZ_GHIDRA_H From 40ea3766d1bb283e255e31b9e7c3a61885dd3cb0 Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Fri, 7 May 2021 17:56:38 +0800 Subject: [PATCH 10/19] Add pkg-config files --- CMakeLists.txt | 13 +++++++++++++ rz_ghidra.pc.in | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 rz_ghidra.pc.in diff --git a/CMakeLists.txt b/CMakeLists.txt index ba0213f6..2155248b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,9 @@ endif() add_subdirectory(ghidra) add_subdirectory(third-party) +set(PUBLIC_HEADERS + src/rz_ghidra.h) + set(CORE_SOURCE src/core_ghidra.cpp src/RizinArchitecture.cpp @@ -78,6 +81,10 @@ set_target_properties(core_ghidra PROPERTIES OUTPUT_NAME core_ghidra PREFIX "") +configure_file( + ${PROJECT_SOURCE_DIR}/rz_ghidra.pc.in + ${PROJECT_BINARY_DIR}/rz_ghidra.pc + @ONLY) if(BUILD_CUTTER_PLUGIN) add_subdirectory(cutter-plugin) @@ -116,8 +123,14 @@ if(SLEIGHHOME_DEFAULT) endif() endif() +if(NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "Output directory for libraries.") +endif() + install(TARGETS core_ghidra DESTINATION "${RIZIN_INSTALL_PLUGDIR}") if(BUILD_SLEIGH_PLUGIN) install(TARGETS asm_ghidra DESTINATION "${RIZIN_INSTALL_PLUGDIR}") install(TARGETS analysis_ghidra DESTINATION "${RIZIN_INSTALL_PLUGDIR}") endif() +install(FILES ${PUBLIC_HEADERS} DESTINATION "${CMAKE_INSTALL_PREFIX}/include") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/rz_ghidra.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") diff --git a/rz_ghidra.pc.in b/rz_ghidra.pc.in new file mode 100644 index 00000000..22d248c0 --- /dev/null +++ b/rz_ghidra.pc.in @@ -0,0 +1,13 @@ +prefix="@CMAKE_INSTALL_PREFIX@" +exec_prefix="${prefix}" +includedir="${prefix}/include" + +Name: RzGhidra +Description: RzGhidra Rizin plugin library +URL: https://github.com/rizinorg/rz-ghidra +Version: @PROJECT_VERSION@ +Requires: rz_core +Requires.private: rz_core +Cflags: -I"${includedir}" +Libs: -L"${prefix}/@RIZIN_INSTALL_PLUGDIR@" -l:core_ghidra@CMAKE_SHARED_LIBRARY_SUFFIX@ +Libs.private: -L"${prefix}/@RIZIN_INSTALL_PLUGDIR@" -l:core_ghidra@CMAKE_SHARED_LIBRARY_SUFFIX@ From c2ffa894e942a56e994ba1e4217b5f8d37e5df22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 4 Aug 2021 12:15:27 +0200 Subject: [PATCH 11/19] Preliminary update for RzType changes (#238) --- src/RizinScope.cpp | 6 +++-- src/RizinScope.h | 6 ++--- src/RizinTypeFactory.cpp | 42 +++++++++++----------------------- src/RizinTypeFactory.h | 2 -- test/bins/types.h | 2 +- test/db/extras/analysis_ghidra | 2 -- test/db/extras/ghidra | 19 +++++++++++---- 7 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/RizinScope.cpp b/src/RizinScope.cpp index 08ffcc83..e41456ae 100644 --- a/src/RizinScope.cpp +++ b/src/RizinScope.cpp @@ -221,10 +221,12 @@ FunctionSymbol *RizinScope::registerFunction(RzAnalysisFunction *fcn) const { rz_list_foreach_cpp(vars, [&](RzAnalysisVar *var) { std::string typeError; - Datatype *type = var->type ? arch->getTypeFactory()->fromCString(var->type, &typeError) : nullptr; + Datatype *type = var->type ? arch->getTypeFactory()->fromRzType(var->type, &typeError) : nullptr; if(!type) { - arch->addWarning("Failed to match type " + to_string(var->type) + " for variable " + to_string(var->name) + " to Decompiler type: " + typeError); + char *tstr = rz_type_as_string(core->analysis->typedb, var->type); + arch->addWarning("Failed to match type " + to_string(tstr ? tstr : "?") + " for variable " + to_string(var->name) + " to Decompiler type: " + typeError); + rz_mem_free(tstr); type = arch->types->getBase(core->analysis->bits / 8, TYPE_UNKNOWN); if(!type) return; diff --git a/src/RizinScope.h b/src/RizinScope.h index 3da85d9a..3b1d5a18 100644 --- a/src/RizinScope.h +++ b/src/RizinScope.h @@ -54,17 +54,17 @@ class RizinScope : public Scope void adjustCaches(void) override { cache->adjustCaches(); } SymbolEntry *findAddr(const Address &addr,const Address &usepoint) const override; SymbolEntry *findContainer(const Address &addr,int4 size, const Address &usepoint) const override; - SymbolEntry *findClosestFit(const Address &addr,int4 size, const Address &usepoint) const { throw LowlevelError("findClosestFit unimplemented"); } + SymbolEntry *findClosestFit(const Address &addr,int4 size, const Address &usepoint) const override { throw LowlevelError("findClosestFit unimplemented"); } Funcdata *findFunction(const Address &addr) const override; ExternRefSymbol *findExternalRef(const Address &addr) const override; LabSymbol *findCodeLabel(const Address &addr) const override; bool isNameUsed(const string &name, const Scope *op2) const override { throw LowlevelError("isNameUsed unimplemented"); } Funcdata *resolveExternalRefFunction(ExternRefSymbol *sym) const override; - SymbolEntry *findOverlap(const Address &addr,int4 size) const { throw LowlevelError("findOverlap unimplemented"); } + SymbolEntry *findOverlap(const Address &addr,int4 size) const override { throw LowlevelError("findOverlap unimplemented"); } SymbolEntry *findBefore(const Address &addr) const { throw LowlevelError("findBefore unimplemented"); } SymbolEntry *findAfter(const Address &addr) const { throw LowlevelError("findAfter unimplemented"); } - void findByName(const string &name,vector &res) const { throw LowlevelError("findByName unimplemented"); } + void findByName(const string &name,vector &res) const override { throw LowlevelError("findByName unimplemented"); } MapIterator begin() const override { throw LowlevelError("begin unimplemented"); } MapIterator end() const override { throw LowlevelError("end unimplemented"); } list::const_iterator beginDynamic() const override { throw LowlevelError("beginDynamic unimplemented"); } diff --git a/src/RizinTypeFactory.cpp b/src/RizinTypeFactory.cpp index 5aa1213f..1333fd83 100644 --- a/src/RizinTypeFactory.cpp +++ b/src/RizinTypeFactory.cpp @@ -12,14 +12,10 @@ RizinTypeFactory::RizinTypeFactory(RizinArchitecture *arch) : TypeFactory(arch), arch(arch) { - parser = rz_ast_parser_new(); - if(!parser) - throw LowlevelError("Failed to create RParseCType"); } RizinTypeFactory::~RizinTypeFactory() { - rz_ast_parser_free(parser); } Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::set &stack_types) @@ -34,11 +30,14 @@ Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::set(&type->struct_data.members, [&](RzTypeStructMember *member) { if(!member->type || !member->name) return; - Datatype *member_type = fromCString(member->type, nullptr, &stack_types); + Datatype *member_type = fromRzType(member->type, nullptr, &stack_types); if(!member_type) { - arch->addWarning(std::string("Failed to match type ") + member->type + " of member " + member->name + RzCoreLock core(arch->getCore()); + char *tstr = rz_type_as_string(core->analysis->typedb, member->type); + arch->addWarning(std::string("Failed to match type ") + (tstr ? tstr : "?") + " of member " + member->name + " in struct " + type->name); + rz_mem_free(tstr); return; } @@ -100,7 +99,7 @@ Datatype *RizinTypeFactory::addRizinTypedef(RzBaseType *type, std::setkind == RZ_BASE_TYPE_KIND_TYPEDEF); if(!type->type) return nullptr; - Datatype *resolved = fromCString(type->type, nullptr, &stack_types); + Datatype *resolved = fromRzType(type->type, nullptr, &stack_types); if(!resolved) return nullptr; Datatype *typedefd = resolved->clone(); @@ -122,11 +121,7 @@ Datatype *RizinTypeFactory::queryRizin(const string &n, std::set &s RzCoreLock core(arch->getCore()); RzBaseType *type = rz_type_db_get_base_type(core->analysis->typedb, n.c_str()); if(!type || !type->name) - { - if(type) - rz_type_base_type_free(type); goto beach; - } switch(type->kind) { case RZ_BASE_TYPE_KIND_STRUCT: @@ -142,7 +137,6 @@ Datatype *RizinTypeFactory::queryRizin(const string &n, std::set &s default: break; } - rz_type_base_type_free(type); beach: stack_types.erase(n); return r; @@ -162,27 +156,13 @@ Datatype *RizinTypeFactory::findById(const string &n, uint8 id) return findById(n, id, stackTypes); } -Datatype *RizinTypeFactory::fromCString(const string &str, string *error, std::set *stackTypes) -{ - char *error_cstr = nullptr; - RzType *type = rz_type_parse(parser, str.c_str(), &error_cstr); - if(error) - *error = error_cstr ? error_cstr : ""; - if(!type) - return nullptr; - - Datatype *r = fromRzType(type, error, stackTypes); - rz_type_free(type); - return r; -} - Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std::set *stackTypes) { switch(ctype->kind) { case RZ_TYPE_KIND_IDENTIFIER: { - if(ctype->identifier.kind == RZ_TYPE_CTYPE_IDENTIFIER_KIND_UNION) + if(ctype->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_UNION) { if(error) *error = "Union types not supported in Decompiler"; @@ -196,13 +176,13 @@ Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std:: *error = "Unknown type identifier " + std::string(ctype->identifier.name); return nullptr; } - if(ctype->identifier.kind == RZ_TYPE_CTYPE_IDENTIFIER_KIND_STRUCT && r->getMetatype() != TYPE_STRUCT) + if(ctype->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_STRUCT && r->getMetatype() != TYPE_STRUCT) { if(error) *error = "Type identifier " + std::string(ctype->identifier.name) + " is not the name of a struct"; return nullptr; } - if(ctype->identifier.kind == RZ_TYPE_CTYPE_IDENTIFIER_KIND_ENUM && !r->isEnumType()) + if(ctype->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_ENUM && !r->isEnumType()) { if(error) *error = "Type identifier " + std::string(ctype->identifier.name) + " is not the name of an enum"; @@ -225,6 +205,10 @@ Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std:: return nullptr; return this->getTypeArray(ctype->array.count, sub); } + case RZ_TYPE_KIND_CALLABLE: + { + // TODO! + } } return nullptr; } diff --git a/src/RizinTypeFactory.h b/src/RizinTypeFactory.h index feca933c..69e50b89 100644 --- a/src/RizinTypeFactory.h +++ b/src/RizinTypeFactory.h @@ -15,7 +15,6 @@ class RizinTypeFactory : public TypeFactory { private: RizinArchitecture *arch; - RzASTParser *parser; Datatype *addRizinStruct(RzBaseType *type, std::set &stack_types); Datatype *addRizinEnum(RzBaseType *type); @@ -32,7 +31,6 @@ class RizinTypeFactory : public TypeFactory RizinTypeFactory(RizinArchitecture *arch); ~RizinTypeFactory() override; - Datatype *fromCString(const string &str, string *error = nullptr, std::set *stackTypes = nullptr); Datatype *fromRzType(const RzType *ctype, string *error = nullptr, std::set *stackTypes = nullptr); }; diff --git a/test/bins/types.h b/test/bins/types.h index 12de3fbf..da037a39 100644 --- a/test/bins/types.h +++ b/test/bins/types.h @@ -29,4 +29,4 @@ struct Bright typedef struct Bright *BrightPtr; typedef struct Bright BrightTypedefd; -typedef struct BrightTypedefd *BrightTypedefdPtr; +typedef BrightTypedefd *BrightTypedefdPtr; diff --git a/test/db/extras/analysis_ghidra b/test/db/extras/analysis_ghidra index 23e6a9f4..e00ea6be 100644 --- a/test/db/extras/analysis_ghidra +++ b/test/db/extras/analysis_ghidra @@ -205,7 +205,6 @@ address: 0x0 opcode: cmp r7, r6 esilcost: 0 disasm: cmp r7, r6 -pseudo: r6 == r7 mnemonic: cmp mask: ffff prefix: 0 @@ -241,7 +240,6 @@ address: 0x0 opcode: ld.w 0x4[r29], r11 esilcost: 4 disasm: ld.w 0x4[r29], r11 -pseudo: ld.w 0x4[r29],r11 mnemonic: ld.w mask: ffffffff prefix: 0 diff --git a/test/db/extras/ghidra b/test/db/extras/ghidra index 236bd978..27bfb2a5 100644 --- a/test/db/extras/ghidra +++ b/test/db/extras/ghidra @@ -197,6 +197,7 @@ EXPECT=< + + @@ -3073,8 +3080,10 @@ void sym.KillList(LL arg1) return; } EOF +BROKEN=1 RUN +BROKEN=1 NAME=strings FILE=bins/strings CMDS=< Date: Thu, 9 Sep 2021 20:21:50 +0200 Subject: [PATCH 12/19] Fix struct member offsets for RzType (#243) --- src/RizinTypeFactory.cpp | 10 ++++++++-- test/db/extras/ghidra | 24 ++++++++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/RizinTypeFactory.cpp b/src/RizinTypeFactory.cpp index 1333fd83..faf70fe5 100644 --- a/src/RizinTypeFactory.cpp +++ b/src/RizinTypeFactory.cpp @@ -25,6 +25,8 @@ Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::set fields; try { + RzCoreLock core(arch->getCore()); + ut64 offset = 0; TypeStruct *r = getTypeStruct(type->name); void *it; rz_vector_foreach_cpp(&type->struct_data.members, [&](RzTypeStructMember *member) { @@ -33,7 +35,6 @@ Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::settype, nullptr, &stack_types); if(!member_type) { - RzCoreLock core(arch->getCore()); char *tstr = rz_type_as_string(core->analysis->typedb, member->type); arch->addWarning(std::string("Failed to match type ") + (tstr ? tstr : "?") + " of member " + member->name + " in struct " + type->name); @@ -46,10 +47,15 @@ Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::setoffset, + (int4)offset, // Currently, this is 0 most of the time: member->offset, std::string(member->name), member_type }); + + // TODO: right now, we track member offset ourselves + // which means all structs are assumed to be packed. + // This should be changed if there is a clear notion of the offset in rizin at some point. + offset += rz_type_db_get_bitsize(core->analysis->typedb, member->type) / 8; }); if(fields.empty()) { diff --git a/test/db/extras/ghidra b/test/db/extras/ghidra index 27bfb2a5..0c737bb0 100644 --- a/test/db/extras/ghidra +++ b/test/db/extras/ghidra @@ -1942,6 +1942,9 @@ NAME=aeropause32 (many features combined) FILE=bins/dectest32 EXPECT=<ambassador); + sym.PrintAmbassador((uint64_t)*(uint32_t *)&bright->ambassador); return; } EOF @@ -2092,9 +2093,6 @@ afvr rdi s1 "const char *" @ sym.imp.strcmp afvr rsi s2 "const char *" @ sym.imp.strcmp to bins/types.h -# TODO: remove when parsed struct from r2 is correct -# tk struct.Bright.ambassador=enum Ambassador,16,0 -# tk struct.Bright.window=struct Window,8,0 s sym.Aeropause afvr rdi bright "Bright *" @@ -2105,10 +2103,12 @@ EOF RUN NAME=typedef -BROKEN=1 FILE=bins/dectest32 EXPECT=< Date: Mon, 13 Sep 2021 12:30:59 +0200 Subject: [PATCH 13/19] Update Ghidra --- ghidra/ghidra | 2 +- src/RizinTypeFactory.cpp | 8 ++++---- src/RizinTypeFactory.h | 6 +++--- test/db/extras/asm_ghidra | 2 +- test/db/extras/ghidra | 31 +++++++++++++++++++------------ 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/ghidra/ghidra b/ghidra/ghidra index 8d5d5aa8..bc5c5b20 160000 --- a/ghidra/ghidra +++ b/ghidra/ghidra @@ -1 +1 @@ -Subproject commit 8d5d5aa83f7096bc742643486892a858fafca43d +Subproject commit bc5c5b20731bdc44e6165bfbf3e360694e64b4a9 diff --git a/src/RizinTypeFactory.cpp b/src/RizinTypeFactory.cpp index faf70fe5..baedb2ca 100644 --- a/src/RizinTypeFactory.cpp +++ b/src/RizinTypeFactory.cpp @@ -148,18 +148,18 @@ Datatype *RizinTypeFactory::queryRizin(const string &n, std::set &s return r; } -Datatype *RizinTypeFactory::findById(const string &n, uint8 id, std::set &stackTypes) +Datatype *RizinTypeFactory::findById(const string &n, uint8 id, int4 sz, std::set &stackTypes) { - Datatype *r = TypeFactory::findById(n, id); + Datatype *r = TypeFactory::findById(n, id, sz); if(r) return r; return queryRizin(n, stackTypes); } -Datatype *RizinTypeFactory::findById(const string &n, uint8 id) +Datatype *RizinTypeFactory::findById(const string &n, uint8 id, int4 sz) { std::set stackTypes; // to detect recursion - return findById(n, id, stackTypes); + return findById(n, id, sz, stackTypes); } Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std::set *stackTypes) diff --git a/src/RizinTypeFactory.h b/src/RizinTypeFactory.h index 69e50b89..c2846b33 100644 --- a/src/RizinTypeFactory.h +++ b/src/RizinTypeFactory.h @@ -22,10 +22,10 @@ class RizinTypeFactory : public TypeFactory Datatype *queryRizin(const string &n, std::set &stack_types); protected: - Datatype *findById(const string &n, uint8 id) override; - Datatype *findById(const string &n, uint8 id, std::set &stackTypes); + Datatype *findById(const string &n, uint8 id, int4 sz) override; + Datatype *findById(const string &n, uint8 id, int4 sz, std::set &stackTypes); using TypeFactory::findByName; - Datatype *findByName(const string &n, std::set &stackTypes) { return findById(n, 0, stackTypes); } + Datatype *findByName(const string &n, std::set &stackTypes) { return findById(n, 0, 0, stackTypes); } public: RizinTypeFactory(RizinArchitecture *arch); diff --git a/test/db/extras/asm_ghidra b/test/db/extras/asm_ghidra index bda066e5..a1058f91 100644 --- a/test/db/extras/asm_ghidra +++ b/test/db/extras/asm_ghidra @@ -111,7 +111,7 @@ EXPECT=< + @@ -2467,15 +2468,22 @@ CCu base64:Jg== @ 0x804858a - - - - - - - - - + + + + + + + + + + + + + + + + @@ -2484,6 +2492,7 @@ CCu base64:Jg== @ 0x804858a + @@ -2581,7 +2590,6 @@ CCu base64:Jg== @ 0x804858a - @@ -2607,7 +2615,6 @@ CCu base64:Jg== @ 0x804858a - @@ -2731,8 +2738,8 @@ RUN NAME=pdgs FILE== EXPECT=< Date: Mon, 13 Sep 2021 15:03:50 +0200 Subject: [PATCH 14/19] Fix Compiling CLI (#244) --- ghidra/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ghidra/CMakeLists.txt b/ghidra/CMakeLists.txt index 0aa7d865..a24cd57f 100644 --- a/ghidra/CMakeLists.txt +++ b/ghidra/CMakeLists.txt @@ -118,6 +118,7 @@ set(SOURCE_CONSOLE_CXX consolemain.cc interface.cc ifacedecomp.cc + testfunction.cc ifaceterm.cc callgraph.cc raw_arch.cc) From 1b2525c2928c5b43baf4ede2497a1f65d0304622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Mon, 13 Sep 2021 22:37:19 +0200 Subject: [PATCH 15/19] Fix Recursive Typedefs (Fix #239) (#245) --- src/RizinTypeFactory.cpp | 43 +++++++++++++++++++++++++++------------- src/RizinTypeFactory.h | 17 ++++++++++------ test/db/extras/ghidra | 5 ++--- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/RizinTypeFactory.cpp b/src/RizinTypeFactory.cpp index baedb2ca..15e213b3 100644 --- a/src/RizinTypeFactory.cpp +++ b/src/RizinTypeFactory.cpp @@ -18,7 +18,7 @@ RizinTypeFactory::~RizinTypeFactory() { } -Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::set &stack_types) +Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, StackTypes &stack_types, bool prototype) { assert(type->kind == RZ_BASE_TYPE_KIND_STRUCT); @@ -28,6 +28,12 @@ Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, std::setgetCore()); ut64 offset = 0; TypeStruct *r = getTypeStruct(type->name); + if (prototype) { + prototypes.insert(r); + return r; + } else { + prototypes.erase(r); + } void *it; rz_vector_foreach_cpp(&type->struct_data.members, [&](RzTypeStructMember *member) { if(!member->type || !member->name) @@ -100,21 +106,22 @@ Datatype *RizinTypeFactory::addRizinEnum(RzBaseType *type) } } -Datatype *RizinTypeFactory::addRizinTypedef(RzBaseType *type, std::set &stack_types) +Datatype *RizinTypeFactory::addRizinTypedef(RzBaseType *type, StackTypes &stack_types) { assert(type->kind == RZ_BASE_TYPE_KIND_TYPEDEF); if(!type->type) return nullptr; - Datatype *resolved = fromRzType(type->type, nullptr, &stack_types); + Datatype *resolved = fromRzTypeInternal(type->type, nullptr, &stack_types, true, false); // use prototype=true to avoid recursion if(!resolved) return nullptr; Datatype *typedefd = resolved->clone(); setName(typedefd, type->name); // this removes the old name from the nametree setName(resolved, resolved->getName()); // add the old name back + fromRzTypeInternal(type->type, nullptr, &stack_types, false, false); // fully create the type after querying with prototype=true before return typedefd; } -Datatype *RizinTypeFactory::queryRizin(const string &n, std::set &stack_types) +Datatype *RizinTypeFactory::queryRizin(const string &n, StackTypes &stack_types, bool prototype) { if(stack_types.find(n) != stack_types.end()) { @@ -131,7 +138,7 @@ Datatype *RizinTypeFactory::queryRizin(const string &n, std::set &s switch(type->kind) { case RZ_BASE_TYPE_KIND_STRUCT: - r = addRizinStruct(type, stack_types); + r = addRizinStruct(type, stack_types, prototype); break; case RZ_BASE_TYPE_KIND_ENUM: r = addRizinEnum(type); @@ -148,21 +155,24 @@ Datatype *RizinTypeFactory::queryRizin(const string &n, std::set &s return r; } -Datatype *RizinTypeFactory::findById(const string &n, uint8 id, int4 sz, std::set &stackTypes) +Datatype *RizinTypeFactory::findById(const string &n, uint8 id, int4 sz, StackTypes &stack_types, bool prototype) { Datatype *r = TypeFactory::findById(n, id, sz); - if(r) + if(r && (prototype || prototypes.find(r) == prototypes.end())) return r; - return queryRizin(n, stackTypes); + return queryRizin(n, stack_types, prototype); } Datatype *RizinTypeFactory::findById(const string &n, uint8 id, int4 sz) { - std::set stackTypes; // to detect recursion - return findById(n, id, sz, stackTypes); + StackTypes stack_types; // to detect recursion + return findById(n, id, sz, stack_types, false); } -Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std::set *stackTypes) +// prototype means that the type does not have to be completed entirely yet (e.g. struct prototype for typedef) +// refd means that this type is in a pointer of some kind, so we can actually use prototype +// that's because our typedef-likes in ghidra are just clones of the original type, so we must not clone prototypes, only refs. +Datatype *RizinTypeFactory::fromRzTypeInternal(const RzType *ctype, string *error, StackTypes *stack_types, bool prototype, bool refd) { switch(ctype->kind) { @@ -175,7 +185,7 @@ Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std:: return nullptr; } - Datatype *r = stackTypes ? findByName(ctype->identifier.name, *stackTypes) : findByName(ctype->identifier.name); + Datatype *r = stack_types ? findByName(ctype->identifier.name, *stack_types, prototype && refd) : findByName(ctype->identifier.name); if(!r) { if(error) @@ -198,7 +208,7 @@ Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std:: } case RZ_TYPE_KIND_POINTER: { - Datatype *sub = fromRzType(ctype->pointer.type, error, stackTypes); + Datatype *sub = fromRzTypeInternal(ctype->pointer.type, error, stack_types, prototype, true); if(!sub) return nullptr; auto space = arch->getDefaultCodeSpace(); @@ -206,7 +216,7 @@ Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std:: } case RZ_TYPE_KIND_ARRAY: { - Datatype *sub = fromRzType(ctype->array.type, error, stackTypes); + Datatype *sub = fromRzTypeInternal(ctype->array.type, error, stack_types, prototype, false); if(!sub) return nullptr; return this->getTypeArray(ctype->array.count, sub); @@ -218,3 +228,8 @@ Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, std:: } return nullptr; } + +Datatype *RizinTypeFactory::fromRzType(const RzType *ctype, string *error, StackTypes *stack_types) +{ + return fromRzTypeInternal(ctype, error, stack_types, false, false); +} diff --git a/src/RizinTypeFactory.h b/src/RizinTypeFactory.h index c2846b33..bbd3571b 100644 --- a/src/RizinTypeFactory.h +++ b/src/RizinTypeFactory.h @@ -13,25 +13,30 @@ class RizinArchitecture; class RizinTypeFactory : public TypeFactory { + public: + using StackTypes = std::set; + private: RizinArchitecture *arch; + std::set prototypes; // set of types that have not been created fully yet - Datatype *addRizinStruct(RzBaseType *type, std::set &stack_types); + Datatype *addRizinStruct(RzBaseType *type, StackTypes &stack_types, bool prototype); Datatype *addRizinEnum(RzBaseType *type); - Datatype *addRizinTypedef(RzBaseType *type, std::set &stack_types); - Datatype *queryRizin(const string &n, std::set &stack_types); + Datatype *addRizinTypedef(RzBaseType *type, StackTypes &stack_types); + Datatype *queryRizin(const string &n, StackTypes &stack_types, bool prototype); protected: Datatype *findById(const string &n, uint8 id, int4 sz) override; - Datatype *findById(const string &n, uint8 id, int4 sz, std::set &stackTypes); + Datatype *findById(const string &n, uint8 id, int4 sz, StackTypes &stack_types, bool prototype); using TypeFactory::findByName; - Datatype *findByName(const string &n, std::set &stackTypes) { return findById(n, 0, 0, stackTypes); } + Datatype *findByName(const string &n, StackTypes &stack_types, bool prototype) { return findById(n, 0, 0, stack_types, prototype); } + Datatype *fromRzTypeInternal(const RzType *ctype, string *error, StackTypes *stack_types, bool prototype, bool refd); public: RizinTypeFactory(RizinArchitecture *arch); ~RizinTypeFactory() override; - Datatype *fromRzType(const RzType *ctype, string *error = nullptr, std::set *stackTypes = nullptr); + Datatype *fromRzType(const RzType *ctype, string *error = nullptr, StackTypes *stack_types = nullptr); }; #endif //RZ_GHIDRA_RizinTYPEFACTORY_H diff --git a/test/db/extras/ghidra b/test/db/extras/ghidra index e24ef821..675dc991 100644 --- a/test/db/extras/ghidra +++ b/test/db/extras/ghidra @@ -3079,7 +3079,7 @@ EXPECT=<next; sym.imp.free(ptr); - ptr = (LL)pLVar1; + ptr = pLVar1; } return; } EOF -BROKEN=1 RUN NAME=strings From f100c2a7073771b3d986ead31d824573796a005e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Tue, 14 Sep 2021 17:58:05 +0200 Subject: [PATCH 16/19] Support Callables and Atomic Types (Fix #49) (#246) --- src/RizinTypeFactory.cpp | 83 ++++- src/RizinTypeFactory.h | 1 + src/RizinUtils.h | 11 + test/bins/jni-simplified.h | 466 +++++++++++++++++++++++++ test/db/extras/ghidra | 688 +++++++++++++------------------------ 5 files changed, 791 insertions(+), 458 deletions(-) create mode 100644 test/bins/jni-simplified.h diff --git a/src/RizinTypeFactory.cpp b/src/RizinTypeFactory.cpp index 15e213b3..2a09f68b 100644 --- a/src/RizinTypeFactory.cpp +++ b/src/RizinTypeFactory.cpp @@ -63,11 +63,6 @@ Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, StackTypes &stack_t // This should be changed if there is a clear notion of the offset in rizin at some point. offset += rz_type_db_get_bitsize(core->analysis->typedb, member->type) / 8; }); - if(fields.empty()) - { - arch->addWarning(std::string("Struct ") + type->name + " has no members"); - return nullptr; - } setFields(fields, r, 0, 0); return r; } @@ -121,6 +116,39 @@ Datatype *RizinTypeFactory::addRizinTypedef(RzBaseType *type, StackTypes &stack_ return typedefd; } +static type_metatype metatypeOfTypeclass(RzTypeTypeclass tc) +{ + switch(tc) + { + case RZ_TYPE_TYPECLASS_NUM: + case RZ_TYPE_TYPECLASS_INTEGRAL: + case RZ_TYPE_TYPECLASS_INTEGRAL_UNSIGNED: + return TYPE_UINT; + case RZ_TYPE_TYPECLASS_INTEGRAL_SIGNED: + return TYPE_INT; + case RZ_TYPE_TYPECLASS_FLOATING: + return TYPE_FLOAT; + case RZ_TYPE_TYPECLASS_NONE: + return TYPE_VOID; + default: + return TYPE_UNKNOWN; + } +} + +Datatype *RizinTypeFactory::addRizinAtomicType(RzBaseType *type, StackTypes &stack_types) +{ + assert(type->kind == RZ_BASE_TYPE_KIND_ATOMIC); + if(!type->name || type->size < 8) + { + arch->addWarning(std::string("Invalid atomic type ") + (type->name ? type->name : "(null)")); + return nullptr; + } + RzCoreLock core(arch->getCore()); + type_metatype mt = metatypeOfTypeclass(rz_base_type_typeclass(core->analysis->typedb, type)); + // setCoreType(type->name, type->size / 8, mt, false); // TODO: conditionally enable chartp when supported in rizin + return getBase(type->size / 8, mt, type->name); +} + Datatype *RizinTypeFactory::queryRizin(const string &n, StackTypes &stack_types, bool prototype) { if(stack_types.find(n) != stack_types.end()) @@ -146,7 +174,9 @@ Datatype *RizinTypeFactory::queryRizin(const string &n, StackTypes &stack_types, case RZ_BASE_TYPE_KIND_TYPEDEF: r = addRizinTypedef(type, stack_types); break; - // TODO: atomic too? + case RZ_BASE_TYPE_KIND_ATOMIC: + r = addRizinAtomicType(type, stack_types); + break; default: break; } @@ -216,14 +246,51 @@ Datatype *RizinTypeFactory::fromRzTypeInternal(const RzType *ctype, string *erro } case RZ_TYPE_KIND_ARRAY: { - Datatype *sub = fromRzTypeInternal(ctype->array.type, error, stack_types, prototype, false); + Datatype *sub = fromRzTypeInternal(ctype->array.type, error, stack_types, prototype, refd); if(!sub) return nullptr; return this->getTypeArray(ctype->array.count, sub); } case RZ_TYPE_KIND_CALLABLE: { - // TODO! + RzCallable *callable = ctype->callable; + ProtoModel *pm = callable->cc ? arch->protoModelFromRizinCC(callable->cc) : nullptr; + if(!pm) + { + RzCoreLock core(arch->getCore()); + const char *cc = rz_analysis_cc_default(core->analysis); + if(cc) + pm = arch->protoModelFromRizinCC(cc); + } + if(!pm) + { + RzCoreLock core(arch->getCore()); + char *tstr = rz_type_as_string(core->analysis->typedb, ctype); + *error = std::string("Failed to get any calling convention for callable ") + tstr; + rz_mem_free(tstr); + return nullptr; + } + Datatype *outtype = nullptr; + if(callable->ret) + { + outtype = fromRzTypeInternal(callable->ret, error, stack_types, prototype, refd); + if(!outtype) + return nullptr; + } + std::vector intypes; + if(!rz_pvector_foreach_cpp(callable->args, [&](RzCallableArg *arg) { + if(!arg->type) + return false; + Datatype *at = fromRzTypeInternal(arg->type, error, stack_types, prototype, refd); + if(!at) + return false; + intypes.push_back(at); + return true; + })) + { + return nullptr; + } + return this->getTypeCode(pm, outtype, intypes, false); // dotdotdot arg can be used when rizin supports vararg callables } } return nullptr; diff --git a/src/RizinTypeFactory.h b/src/RizinTypeFactory.h index bbd3571b..df3b57b9 100644 --- a/src/RizinTypeFactory.h +++ b/src/RizinTypeFactory.h @@ -23,6 +23,7 @@ class RizinTypeFactory : public TypeFactory Datatype *addRizinStruct(RzBaseType *type, StackTypes &stack_types, bool prototype); Datatype *addRizinEnum(RzBaseType *type); Datatype *addRizinTypedef(RzBaseType *type, StackTypes &stack_types); + Datatype *addRizinAtomicType(RzBaseType *type, StackTypes &stack_types); Datatype *queryRizin(const string &n, StackTypes &stack_types, bool prototype); protected: diff --git a/src/RizinUtils.h b/src/RizinUtils.h index 55de6da0..283a3c65 100644 --- a/src/RizinUtils.h +++ b/src/RizinUtils.h @@ -35,4 +35,15 @@ template void rz_vector_foreach_cpp(RzVector *vec, const } } +template bool rz_pvector_foreach_cpp(RzPVector *vec, const F &func) +{ + void **it; + rz_pvector_foreach(vec, it) + { + if(!func(reinterpret_cast(*it))) + return false; + } + return true; +} + #endif //RZ_GHIDRA_RIZINUTILS_H diff --git a/test/bins/jni-simplified.h b/test/bins/jni-simplified.h new file mode 100644 index 00000000..036e995d --- /dev/null +++ b/test/bins/jni-simplified.h @@ -0,0 +1,466 @@ +typedef __builtin_va_list __gnuc_va_list; +typedef __gnuc_va_list va_list; +typedef unsigned char jboolean; +typedef char jbyte; +typedef unsigned short jchar; +typedef short jshort; +typedef int jint; +typedef long long jlong; +typedef float jfloat; +typedef double jdouble; + + + +typedef jint jsize; +typedef void* jobject; +typedef jobject jclass; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jobjectArray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jobject jthrowable; +typedef jobject jweak; + + + +struct _jfieldID {}; +typedef struct _jfieldID* jfieldID; + +struct _jmethodID {}; +typedef struct _jmethodID* jmethodID; + +struct JNIInvokeInterface; + +typedef struct { + jobject l; +} jvalue; + +typedef enum { + JNIInvalidRefType = 0, + JNILocalRefType = 1, + JNIGlobalRefType = 2, + JNIWeakGlobalRefType = 3 +} jobjectRefType; + +typedef struct { + const char* name; + const char* signature; + void* fnPtr; +} JNINativeMethod; + +struct _JNIEnv; +struct _JavaVM; +typedef const struct JNINativeInterface* C_JNIEnv; + + + + + +typedef const struct JNINativeInterface* JNIEnv; +typedef const struct JNIInvokeInterface* JavaVM; + + + + + +struct JNINativeInterface { + void* reserved0; + void* reserved1; + void* reserved2; + void* reserved3; + + jint (*GetVersion)(JNIEnv *); + + jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, + jsize); + jclass (*FindClass)(JNIEnv*, const char*); + + jmethodID (*FromReflectedMethod)(JNIEnv*, jobject); + jfieldID (*FromReflectedField)(JNIEnv*, jobject); + + jobject (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean); + + jclass (*GetSuperclass)(JNIEnv*, jclass); + jboolean (*IsAssignableFrom)(JNIEnv*, jclass, jclass); + + + jobject (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean); + + jint (*Throw)(JNIEnv*, jthrowable); + jint (*ThrowNew)(JNIEnv *, jclass, const char *); + jthrowable (*ExceptionOccurred)(JNIEnv*); + void (*ExceptionDescribe)(JNIEnv*); + void (*ExceptionClear)(JNIEnv*); + void (*FatalError)(JNIEnv*, const char*); + + jint (*PushLocalFrame)(JNIEnv*, jint); + jobject (*PopLocalFrame)(JNIEnv*, jobject); + + jobject (*NewGlobalRef)(JNIEnv*, jobject); + void (*DeleteGlobalRef)(JNIEnv*, jobject); + void (*DeleteLocalRef)(JNIEnv*, jobject); + jboolean (*IsSameObject)(JNIEnv*, jobject, jobject); + + jobject (*NewLocalRef)(JNIEnv*, jobject); + jint (*EnsureLocalCapacity)(JNIEnv*, jint); + + jobject (*AllocObject)(JNIEnv*, jclass); + jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...); + jobject (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list); + jobject (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*); + + jclass (*GetObjectClass)(JNIEnv*, jobject); + jboolean (*IsInstanceOf)(JNIEnv*, jobject, jclass); + jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); + + jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...); + jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...); + jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...); + jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...); + jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...); + jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); + jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...); + jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...) ; + jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list) ; + jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) ; + jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...) ; + jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list) ; + jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) ; + void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); + void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list); + void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + + jobject (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jobject (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jobject (*CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jboolean (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jbyte (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jbyte (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jbyte (*CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jchar (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jchar (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jchar (*CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jshort (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jshort (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jshort (*CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jint (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jint (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jint (*CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jlong (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jlong (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jlong (*CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jfloat (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...) ; + jfloat (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list) ; + jfloat (*CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*) ; + jdouble (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...) ; + jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list) ; + jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*) ; + void (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + void (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + void (*CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + + jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*); + + jobject (*GetObjectField)(JNIEnv*, jobject, jfieldID); + jboolean (*GetBooleanField)(JNIEnv*, jobject, jfieldID); + jbyte (*GetByteField)(JNIEnv*, jobject, jfieldID); + jchar (*GetCharField)(JNIEnv*, jobject, jfieldID); + jshort (*GetShortField)(JNIEnv*, jobject, jfieldID); + jint (*GetIntField)(JNIEnv*, jobject, jfieldID); + jlong (*GetLongField)(JNIEnv*, jobject, jfieldID); + jfloat (*GetFloatField)(JNIEnv*, jobject, jfieldID) ; + jdouble (*GetDoubleField)(JNIEnv*, jobject, jfieldID) ; + + void (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject); + void (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean); + void (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte); + void (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar); + void (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort); + void (*SetIntField)(JNIEnv*, jobject, jfieldID, jint); + void (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong); + void (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat) ; + void (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble) ; + + jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*); + + jobject (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...); + jobject (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jobject (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jboolean (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...); + jboolean (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID, + va_list); + jboolean (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID, + jvalue*); + jbyte (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...); + jbyte (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jbyte (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jchar (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...); + jchar (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jchar (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jshort (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...); + jshort (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jshort (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jint (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...); + jint (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jint (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jlong (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...); + jlong (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jlong (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jfloat (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...) ; + jfloat (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list) ; + jfloat (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*) ; + jdouble (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...) ; + jdouble (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list) ; + jdouble (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*) ; + void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); + void (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list); + void (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + + jfieldID (*GetStaticFieldID)(JNIEnv*, jclass, const char*, + const char*); + + jobject (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID); + jboolean (*GetStaticBooleanField)(JNIEnv*, jclass, jfieldID); + jbyte (*GetStaticByteField)(JNIEnv*, jclass, jfieldID); + jchar (*GetStaticCharField)(JNIEnv*, jclass, jfieldID); + jshort (*GetStaticShortField)(JNIEnv*, jclass, jfieldID); + jint (*GetStaticIntField)(JNIEnv*, jclass, jfieldID); + jlong (*GetStaticLongField)(JNIEnv*, jclass, jfieldID); + jfloat (*GetStaticFloatField)(JNIEnv*, jclass, jfieldID) ; + jdouble (*GetStaticDoubleField)(JNIEnv*, jclass, jfieldID) ; + + void (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject); + void (*SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean); + void (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte); + void (*SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar); + void (*SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort); + void (*SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint); + void (*SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong); + void (*SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat) ; + void (*SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble) ; + + jstring (*NewString)(JNIEnv*, const jchar*, jsize); + jsize (*GetStringLength)(JNIEnv*, jstring); + const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); + void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); + jstring (*NewStringUTF)(JNIEnv*, const char*); + jsize (*GetStringUTFLength)(JNIEnv*, jstring); + + const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); + void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); + jsize (*GetArrayLength)(JNIEnv*, jarray); + jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject); + jobject (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize); + void (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject); + + jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); + jbyteArray (*NewByteArray)(JNIEnv*, jsize); + jcharArray (*NewCharArray)(JNIEnv*, jsize); + jshortArray (*NewShortArray)(JNIEnv*, jsize); + jintArray (*NewIntArray)(JNIEnv*, jsize); + jlongArray (*NewLongArray)(JNIEnv*, jsize); + jfloatArray (*NewFloatArray)(JNIEnv*, jsize); + jdoubleArray (*NewDoubleArray)(JNIEnv*, jsize); + + jboolean* (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); + jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); + jchar* (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); + jshort* (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); + jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); + jlong* (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); + jfloat* (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); + jdouble* (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*); + + void (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray, + jboolean*, jint); + void (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray, + jbyte*, jint); + void (*ReleaseCharArrayElements)(JNIEnv*, jcharArray, + jchar*, jint); + void (*ReleaseShortArrayElements)(JNIEnv*, jshortArray, + jshort*, jint); + void (*ReleaseIntArrayElements)(JNIEnv*, jintArray, + jint*, jint); + void (*ReleaseLongArrayElements)(JNIEnv*, jlongArray, + jlong*, jint); + void (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray, + jfloat*, jint); + void (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray, + jdouble*, jint); + + void (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray, + jsize, jsize, jboolean*); + void (*GetByteArrayRegion)(JNIEnv*, jbyteArray, + jsize, jsize, jbyte*); + void (*GetCharArrayRegion)(JNIEnv*, jcharArray, + jsize, jsize, jchar*); + void (*GetShortArrayRegion)(JNIEnv*, jshortArray, + jsize, jsize, jshort*); + void (*GetIntArrayRegion)(JNIEnv*, jintArray, + jsize, jsize, jint*); + void (*GetLongArrayRegion)(JNIEnv*, jlongArray, + jsize, jsize, jlong*); + void (*GetFloatArrayRegion)(JNIEnv*, jfloatArray, + jsize, jsize, jfloat*); + void (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray, + jsize, jsize, jdouble*); + + + void (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray, + jsize, jsize, const jboolean*); + void (*SetByteArrayRegion)(JNIEnv*, jbyteArray, + jsize, jsize, const jbyte*); + void (*SetCharArrayRegion)(JNIEnv*, jcharArray, + jsize, jsize, const jchar*); + void (*SetShortArrayRegion)(JNIEnv*, jshortArray, + jsize, jsize, const jshort*); + void (*SetIntArrayRegion)(JNIEnv*, jintArray, + jsize, jsize, const jint*); + void (*SetLongArrayRegion)(JNIEnv*, jlongArray, + jsize, jsize, const jlong*); + void (*SetFloatArrayRegion)(JNIEnv*, jfloatArray, + jsize, jsize, const jfloat*); + void (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray, + jsize, jsize, const jdouble*); + + jint (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*, + jint); + jint (*UnregisterNatives)(JNIEnv*, jclass); + jint (*MonitorEnter)(JNIEnv*, jobject); + jint (*MonitorExit)(JNIEnv*, jobject); + jint (*GetJavaVM)(JNIEnv*, JavaVM**); + + void (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*); + void (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*); + + void* (*GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*); + void (*ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint); + + const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*); + void (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*); + + jweak (*NewWeakGlobalRef)(JNIEnv*, jobject); + void (*DeleteWeakGlobalRef)(JNIEnv*, jweak); + + jboolean (*ExceptionCheck)(JNIEnv*); + + jobject (*NewDirectByteBuffer)(JNIEnv*, void*, jlong); + void* (*GetDirectBufferAddress)(JNIEnv*, jobject); + jlong (*GetDirectBufferCapacity)(JNIEnv*, jobject); + + + jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject); +}; + + + + + + + +struct _JNIEnv { + + const struct JNINativeInterface* functions; +}; + + + + + +struct JNIInvokeInterface { + void* reserved0; + void* reserved1; + void* reserved2; + + jint (*DestroyJavaVM)(JavaVM*); + jint (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*); + jint (*DetachCurrentThread)(JavaVM*); + jint (*GetEnv)(JavaVM*, void**, jint); + jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*); +}; + + + + +struct _JavaVM { + const struct JNIInvokeInterface* functions; +}; + +struct _JavaVMAttachArgs { + jint version; + const char* name; + jobject group; +}; +typedef struct _JavaVMAttachArgs JavaVMAttachArgs; + + + + + +typedef struct _JavaVMOption { + const char* optionString; + void* extraInfo; +} JavaVMOption; + +typedef struct _JavaVMInitArgs { + jint version; + + jint nOptions; + JavaVMOption* options; + jboolean ignoreUnrecognized; +} JavaVMInitArgs; +__attribute__ ((visibility ("default"))) jint JNI_OnLoad(JavaVM* vm, void* reserved); +__attribute__ ((visibility ("default"))) void JNI_OnUnload(JavaVM* vm, void* reserved); diff --git a/test/db/extras/ghidra b/test/db/extras/ghidra index 675dc991..362c36d8 100644 --- a/test/db/extras/ghidra +++ b/test/db/extras/ghidra @@ -285,7 +285,7 @@ NAME=function variable annotations FILE=bins/dectest64 EXPECT=<NewStringUTF)(env, "foo: Test program of JNI.\\n"); + sym.imp.free(0x650); + } + return pvVar2; +} +EOF +RUN From 16ffeccbf6cba8d2922458ae30ef72821070a6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 15 Sep 2021 19:07:21 +0200 Subject: [PATCH 17/19] Add Support for Global Variables (Fix #242) (#248) --- src/RizinScope.cpp | 29 ++++++++++++++++++++++++++ src/RizinScope.h | 2 ++ test/db/extras/ghidra | 48 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/src/RizinScope.cpp b/src/RizinScope.cpp index e41456ae..9e904fd9 100644 --- a/src/RizinScope.cpp +++ b/src/RizinScope.cpp @@ -494,6 +494,27 @@ Symbol *RizinScope::registerFlag(RzFlagItem *flag) const return symbol; } +Symbol *RizinScope::registerGlobalVar(RzAnalysisVarGlobal *glob) const +{ + RzCoreLock core(arch->getCore()); + uint4 attr = Varnode::namelock | Varnode::typelock; + if (!glob->type) + return nullptr; + std::string terr; + Datatype *type = arch->getTypeFactory()->fromRzType(glob->type, &terr); + if(!type) + { + arch->addWarning(std::string("Failed to create type for global variable ") + glob->name + ": " + terr); + return nullptr; + } + SymbolEntry *entry = cache->addSymbol(glob->name, type, Address(arch->getDefaultCodeSpace(), glob->addr), Address()); + if(!entry) + return nullptr; + auto symbol = entry->getSymbol(); + cache->setAttribute(symbol, attr); + return symbol; +} + Symbol *RizinScope::queryRizinAbsolute(ut64 addr, bool contain) const { RzCoreLock core(arch->getCore()); @@ -512,6 +533,14 @@ Symbol *RizinScope::queryRizinAbsolute(ut64 addr, bool contain) const if(fcn) return registerFunction(fcn); + RzAnalysisVarGlobal *glob; + if(contain) + glob = rz_analysis_var_global_get_byaddr_in(core->analysis, addr); + else + glob = rz_analysis_var_global_get_byaddr_at(core->analysis, addr); + if(glob) + return registerGlobalVar(glob); + // TODO: register more things // TODO: correctly handle contain for flags diff --git a/src/RizinScope.h b/src/RizinScope.h index 3b1d5a18..ad34ea23 100644 --- a/src/RizinScope.h +++ b/src/RizinScope.h @@ -15,6 +15,7 @@ class RizinArchitecture; typedef struct rz_analysis_function_t RzAnalysisFunction; typedef struct rz_flag_item_t RzFlagItem; +typedef struct rz_analysis_var_global_t RzAnalysisVarGlobal; class RizinScope : public Scope { @@ -27,6 +28,7 @@ class RizinScope : public Scope FunctionSymbol *registerFunction(RzAnalysisFunction *fcn) const; Symbol *registerFlag(RzFlagItem *flag) const; + Symbol *registerGlobalVar(RzAnalysisVarGlobal *glob) const; Symbol *queryRizinAbsolute(ut64 addr, bool contain) const; Symbol *queryRizin(const Address &addr, bool contain) const; LabSymbol *queryRizinFunctionLabel(const Address &addr) const; diff --git a/test/db/extras/ghidra b/test/db/extras/ghidra index 362c36d8..9e694041 100644 --- a/test/db/extras/ghidra +++ b/test/db/extras/ghidra @@ -281,6 +281,54 @@ pdg EOF RUN +NAME=global variables +FILE=bins/dectest32 +EXPECT=< Date: Thu, 16 Sep 2021 20:06:31 +0200 Subject: [PATCH 18/19] Update Ghidra to catch Heritage crashes (temporary for #235) (#249) --- ghidra/ghidra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ghidra/ghidra b/ghidra/ghidra index bc5c5b20..3eb45fde 160000 --- a/ghidra/ghidra +++ b/ghidra/ghidra @@ -1 +1 @@ -Subproject commit bc5c5b20731bdc44e6165bfbf3e360694e64b4a9 +Subproject commit 3eb45fdeb01a1404c2f92db9a33e04faf0c57800 From c7a50a2e7c0a95cd52b167c9ee0fa1805223f08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Tue, 21 Sep 2021 20:36:46 +0200 Subject: [PATCH 19/19] Fix for RZ_STRING_TYPE_WIDE changes (#251) --- src/RizinScope.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/RizinScope.cpp b/src/RizinScope.cpp index 9e904fd9..b3bead07 100644 --- a/src/RizinScope.cpp +++ b/src/RizinScope.cpp @@ -461,10 +461,12 @@ Symbol *RizinScope::registerFlag(RzFlagItem *flag) const { switch(str->type) { - case RZ_STRING_TYPE_WIDE: + case RZ_STRING_TYPE_WIDE_LE: + case RZ_STRING_TYPE_WIDE_BE: tn = "char16_t"; break; - case RZ_STRING_TYPE_WIDE32: + case RZ_STRING_TYPE_WIDE32_LE: + case RZ_STRING_TYPE_WIDE32_BE: tn = "char32_t"; break; }