diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 6a51ceff..67989f50 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -13,7 +13,7 @@ environment: CC: clang HOST_CC: clang sources: - - https://github.com/rizinorg/rizin#stable + - https://github.com/rizinorg/rizin - https://github.com/rizinorg/rz-ghidra - https://github.com/rizinorg/rizin-testbins tasks: diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml index 8366634c..6f3142e1 100644 --- a/.builds/openbsd.yml +++ b/.builds/openbsd.yml @@ -11,7 +11,7 @@ environment: CXX: clang++ CC: clang sources: - - https://github.com/rizinorg/rizin#stable + - https://github.com/rizinorg/rizin - https://github.com/rizinorg/rz-ghidra - https://github.com/rizinorg/rizin-testbins tasks: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b196c8a2..fc1119fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,6 @@ jobs: with: repository: rizinorg/rizin path: rizin - ref: stable - name: Extract rizin version shell: pwsh run: echo "##[set-output name=branch;]$( python sys\\version.py )" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1efb1557..f6951851 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -44,7 +44,7 @@ jobs: pip install meson - name: Prepare Rizin and Cutter run: | - git clone --recursive --depth 1 -b stable https://github.com/rizinorg/rizin + git clone --recursive --depth 1 https://github.com/rizinorg/rizin cd rizin meson build ninja -C build diff --git a/.travis.yml b/.travis.yml index 19d0c64c..6eeb68a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,7 @@ env: install: - pip3 install meson - - git clone --depth 1 -b stable https://github.com/rizinorg/rizin + - git clone --depth 1 https://github.com/rizinorg/rizin - cd rizin && mkdir build && cd build - meson --prefix="$INSTALL_PREFIX" .. - ninja 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/cmake/FindRizin.cmake b/cmake/FindRizin.cmake index 5ffdb600..12f20800 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/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) diff --git a/ghidra/ghidra b/ghidra/ghidra index 8d5d5aa8..3eb45fde 160000 --- a/ghidra/ghidra +++ b/ghidra/ghidra @@ -1 +1 @@ -Subproject commit 8d5d5aa83f7096bc742643486892a858fafca43d +Subproject commit 3eb45fdeb01a1404c2f92db9a33e04faf0c57800 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@ diff --git a/scripts/Dockerfile.arch b/scripts/Dockerfile.arch index 46b9ff18..29d2b978 100644 --- a/scripts/Dockerfile.arch +++ b/scripts/Dockerfile.arch @@ -5,7 +5,7 @@ RUN pacman --noconfirm -Syu RUN pacman --noconfirm -S git gcc make cmake pkg-config flex bison meson ninja qt5-base RUN cd /root && \ - git clone --recurse-submodules --depth 1 -b stable https://github.com/rizinorg/rizin && \ + git clone --recurse-submodules --depth 1 https://github.com/rizinorg/rizin && \ cd rizin && \ meson build --prefix=/usr && \ ninja -C build && \ diff --git a/scripts/Dockerfile.buster b/scripts/Dockerfile.buster index ea8f550c..375d6194 100644 --- a/scripts/Dockerfile.buster +++ b/scripts/Dockerfile.buster @@ -6,7 +6,7 @@ RUN apt-get -y install git g++ cmake pkg-config flex bison python3 python3-pip n pip3 install meson RUN cd /root && \ - git clone --recurse-submodules --depth 1 https://github.com/rizinorg/rizin -b stable && \ + git clone --recurse-submodules --depth 1 https://github.com/rizinorg/rizin && \ cd rizin && \ meson build --prefix=/usr && \ ninja -C build && \ diff --git a/src/RizinScope.cpp b/src/RizinScope.cpp index 08ffcc83..b3bead07 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; @@ -459,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; } @@ -492,6 +496,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()); @@ -510,6 +535,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 3da85d9a..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; @@ -54,17 +56,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 885053e0..2a09f68b 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,33 +12,39 @@ RizinTypeFactory::RizinTypeFactory(RizinArchitecture *arch) : TypeFactory(arch), arch(arch) { - ctype = rz_parse_ctype_new(); - if(!ctype) - throw LowlevelError("Failed to create RParseCType"); } RizinTypeFactory::~RizinTypeFactory() { - rz_parse_ctype_free(ctype); } -Datatype *RizinTypeFactory::addRizinStruct(RzAnalysisBaseType *type, std::set &stack_types) +Datatype *RizinTypeFactory::addRizinStruct(RzBaseType *type, StackTypes &stack_types, bool prototype) { - assert(type->kind == RZ_ANALYSIS_BASE_TYPE_KIND_STRUCT); + assert(type->kind == RZ_BASE_TYPE_KIND_STRUCT); std::vector fields; try { + RzCoreLock core(arch->getCore()); + 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, [&](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); + 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 + 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; } @@ -47,16 +53,16 @@ Datatype *RizinTypeFactory::addRizinStruct(RzAnalysisBaseType *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()) - { - arch->addWarning(std::string("Struct ") + type->name + " has no members"); - return nullptr; - } setFields(fields, r, 0, 0); return r; } @@ -67,13 +73,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,21 +101,55 @@ Datatype *RizinTypeFactory::addRizinEnum(RzAnalysisBaseType *type) } } -Datatype *RizinTypeFactory::addRizinTypedef(RzAnalysisBaseType *type, std::set &stack_types) +Datatype *RizinTypeFactory::addRizinTypedef(RzBaseType *type, StackTypes &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); + 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) +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()) { @@ -120,89 +160,75 @@ 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); goto beach; - } switch(type->kind) { - case RZ_ANALYSIS_BASE_TYPE_KIND_STRUCT: - r = addRizinStruct(type, stack_types); + case RZ_BASE_TYPE_KIND_STRUCT: + r = addRizinStruct(type, stack_types, prototype); 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? + case RZ_BASE_TYPE_KIND_ATOMIC: + r = addRizinAtomicType(type, stack_types); + break; default: break; } - rz_analysis_base_type_free(type); beach: stack_types.erase(n); return r; } -Datatype *RizinTypeFactory::findById(const string &n, uint8 id, std::set &stackTypes) +Datatype *RizinTypeFactory::findById(const string &n, uint8 id, int4 sz, StackTypes &stack_types, bool prototype) { - Datatype *r = TypeFactory::findById(n, id); - if(r) + Datatype *r = TypeFactory::findById(n, id, sz); + 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) +Datatype *RizinTypeFactory::findById(const string &n, uint8 id, int4 sz) { - std::set stackTypes; // to detect recursion - return findById(n, id, stackTypes); + StackTypes stack_types; // to detect recursion + return findById(n, id, sz, stack_types, false); } -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); - if(error) - *error = error_cstr ? error_cstr : ""; - if(!type) - return nullptr; - - Datatype *r = fromCType(type, error, stackTypes); - rz_parse_ctype_type_free(type); - return r; -} - -Datatype *RizinTypeFactory::fromCType(const RParseCTypeType *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) { - case RZ_PARSE_CTYPE_TYPE_KIND_IDENTIFIER: + case RZ_TYPE_KIND_IDENTIFIER: { - if(ctype->identifier.kind == RZ_PARSE_CTYPE_IDENTIFIER_KIND_UNION) + if(ctype->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_UNION) { if(error) *error = "Union types not supported in Decompiler"; 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) *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_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_IDENTIFIER_KIND_ENUM && !r->isEnumType()) { if(error) *error = "Type identifier " + std::string(ctype->identifier.name) + " is not the name of an enum"; @@ -210,21 +236,67 @@ Datatype *RizinTypeFactory::fromCType(const RParseCTypeType *ctype, string *erro } return r; } - case RZ_PARSE_CTYPE_TYPE_KIND_POINTER: + case RZ_TYPE_KIND_POINTER: { - Datatype *sub = fromCType(ctype->pointer.type, error, stackTypes); + Datatype *sub = fromRzTypeInternal(ctype->pointer.type, error, stack_types, prototype, true); if(!sub) return nullptr; auto space = arch->getDefaultCodeSpace(); return this->getTypePointer(space->getAddrSize(), sub, space->getWordSize()); } - case RZ_PARSE_CTYPE_TYPE_KIND_ARRAY: + case RZ_TYPE_KIND_ARRAY: { - Datatype *sub = fromCType(ctype->array.type, error, stackTypes); + 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: + { + 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; } + +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 91a78869..df3b57b9 100644 --- a/src/RizinTypeFactory.h +++ b/src/RizinTypeFactory.h @@ -5,35 +5,39 @@ #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_ast_parser_t RzASTParser; +typedef struct rz_type_t RzType; +typedef struct rz_base_type_t RzBaseType; class RizinArchitecture; class RizinTypeFactory : public TypeFactory { + public: + using StackTypes = std::set; + private: RizinArchitecture *arch; - RParseCType *ctype; + std::set prototypes; // set of types that have not been created fully yet - Datatype *addRizinStruct(RzAnalysisBaseType *type, std::set &stack_types); - Datatype *addRizinEnum(RzAnalysisBaseType *type); - Datatype *addRizinTypedef(RzAnalysisBaseType *type, std::set &stack_types); - Datatype *queryRizin(const string &n, std::set &stack_types); + 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: - 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, StackTypes &stack_types, bool prototype); using TypeFactory::findByName; - Datatype *findByName(const string &n, std::set &stackTypes) { return findById(n, 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 *fromCString(const string &str, string *error = nullptr, std::set *stackTypes = nullptr); - Datatype *fromCType(const RParseCTypeType *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/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/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" 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 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/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 1665052e..e00ea6be 100644 --- a/test/db/extras/analysis_ghidra +++ b/test/db/extras/analysis_ghidra @@ -197,7 +197,7 @@ EOF RUN NAME=v850cmp -FILE=- +FILE== EXPECT=<ambassador); + sym.PrintAmbassador((uint64_t)*(uint32_t *)&bright->ambassador); return; } EOF @@ -2089,9 +1909,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 -k analysis/types/struct.Bright.ambassador=enum Ambassador,16,0 -k analysis/types/struct.Bright.window=struct Window,8,0 s sym.Aeropause afvr rdi bright "Bright *" @@ -2334,7 +2151,7 @@ EXPECT=< + @@ -2455,15 +2273,24 @@ CCu base64:Jg== @ 0x804858a - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -2472,6 +2299,7 @@ CCu base64:Jg== @ 0x804858a + @@ -2569,7 +2397,6 @@ CCu base64:Jg== @ 0x804858a - @@ -2595,7 +2422,6 @@ CCu base64:Jg== @ 0x804858a - @@ -2717,10 +2543,10 @@ EOF RUN NAME=pdgs -FILE=- +FILE== EXPECT=<next; sym.imp.free(ptr); - ptr = (LL)pLVar1; + ptr = pLVar1; } return; } @@ -3105,8 +2931,6 @@ EOF EXPECT=<NewStringUTF)(env, "foo: Test program of JNI.\\n"); + sym.imp.free(0x650); + } + return pvVar2; +} +EOF +RUN