├── Android └── readme.txt ├── Core ├── dyn_item.cpp ├── dyn_item.h ├── dyn_section.cpp ├── dyn_section.h ├── elf.h ├── elf_common.h ├── elf_header.cpp ├── elf_header.h ├── elf_section.cpp ├── elf_section.h ├── elf_segment.cpp ├── elf_segment.h └── features.h ├── IDAScript ├── IDADumpMemory.py ├── IDAMemorySearch.py ├── JNI_InitFunctions_BreakPoint.py ├── JNI_InitFunctions_BreakPoint_Ex.py ├── JNI_OnLoad_BreakPoint.py └── JNI_OnLoad_BreakPoint_Ex.py ├── README.md ├── Windows ├── main.cpp ├── xAnSo.sln ├── xAnSo.vcxproj └── xAnSo.vcxproj.filters ├── fix ├── readme.txt ├── section_fix.cpp └── section_fix.h ├── jni.h ├── libmg20pbase.so ├── libmg20pbase.so.fixed ├── libshella-2.10.7.1.so ├── libshella-2.10.7.1_org.so ├── log.cpp ├── log.h ├── util ├── util.cpp └── util.h ├── viewer └── readme.txt └── xAnSo.exe /Android/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/Android/readme.txt -------------------------------------------------------------------------------- /Core/dyn_item.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file dyn_item.cpp 2017\5\11 20:37:00 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "dyn_item.h" 8 | #include "log.h" 9 | #include "util/util.h" 10 | 11 | /******************************************************************************/ 12 | 13 | // ----------------------------------------------------------------------------- 14 | // dyn_item: Public, Constructor 15 | 16 | dyn_item::dyn_item() 17 | { 18 | dyn_item_.d_tag = 0x12345678; 19 | dyn_item_.d_un.d_ptr = 0; 20 | dyn_item_.d_un.d_val = 0; 21 | } 22 | 23 | // ----------------------------------------------------------------------------- 24 | // dyn_item: Public, Destructor 25 | 26 | dyn_item::~dyn_item() 27 | { 28 | 29 | } 30 | 31 | bool dyn_item::from_string(std::string str_content) 32 | { 33 | LOG(DBG, "read dynamic item from string"); 34 | 35 | if (str_content.size() < sizeof(Elf32_Dyn)){ 36 | LOG(ERR, "read dynamic item from string, input string len invalid, len=%d", str_content.size()); 37 | return false; 38 | } 39 | 40 | //copy content 41 | memcpy((char *)&dyn_item_, str_content.c_str(), sizeof(Elf32_Dyn)); 42 | return true; 43 | } 44 | 45 | std::string dyn_item::print() 46 | { 47 | std::string styled_section; 48 | styled_section += ("Tag: " + tag_2_string(dyn_item_.d_tag)); 49 | styled_section += ("Value: " + util::itoa(dyn_item_.d_un.d_val)); 50 | 51 | return styled_section; 52 | } 53 | 54 | std::string dyn_item::tag_2_string(int tag) 55 | { 56 | switch (tag) 57 | { 58 | case DT_NULL: 59 | return "DT_NULL"; 60 | case DT_NEEDED: 61 | return "DT_NEEDED"; 62 | case DT_PLTRELSZ: 63 | return "DT_PLTRELSZ"; 64 | case DT_PLTGOT: 65 | return "DT_PLTGOT"; 66 | case DT_HASH: 67 | return "DT_HASH"; 68 | case DT_STRTAB: 69 | return "DT_STRTAB"; 70 | case DT_SYMTAB: 71 | return "DT_SYMTAB"; 72 | case DT_RELA: 73 | return "DT_RELA"; 74 | case DT_RELASZ: 75 | return "DT_RELASZ"; 76 | case DT_RELAENT: 77 | return "DT_RELAENT"; 78 | case DT_STRSZ: 79 | return "DT_STRSZ"; 80 | case DT_SYMENT: 81 | return "DT_SYMENT"; 82 | case DT_INIT: 83 | return "DT_INIT"; 84 | case DT_FINI: 85 | return "DT_FINI"; 86 | case DT_SONAME: 87 | return "DT_SONAME"; 88 | case DT_RPATH: 89 | return "DT_RPATH"; 90 | case DT_SYMBOLIC: 91 | return "DT_SYMBOLIC"; 92 | case DT_REL: 93 | return "DT_REL"; 94 | case DT_RELSZ: 95 | return "DT_RELSZ"; 96 | case DT_RELENT: 97 | return "DT_RELENT"; 98 | case DT_PLTREL: 99 | return "DT_PLTREL"; 100 | case DT_DEBUG: 101 | return "DT_DEBUG"; 102 | case DT_TEXTREL: 103 | return "DT_TEXTREL"; 104 | case DT_JMPREL: 105 | return "DT_JMPREL"; 106 | case DT_BIND_NOW: 107 | return "DT_BIND_NOW"; 108 | case DT_INIT_ARRAY: 109 | return "DT_INIT_ARRAY"; 110 | case DT_FINI_ARRAY: 111 | return "DT_FINI_ARRAY"; 112 | case DT_INIT_ARRAYSZ: 113 | return "DT_INIT_ARRAYSZ"; 114 | case DT_FINI_ARRAYSZ: 115 | return "DT_FINI_ARRAYSZ"; 116 | case DT_RUNPATH: 117 | return "DT_RUNPATH"; 118 | case DT_FLAGS: 119 | return "DT_FLAGS"; 120 | //case DT_ENCODING: 121 | case DT_PREINIT_ARRAY: 122 | return "DT_PREINIT_ARRAY"; 123 | case DT_PREINIT_ARRAYSZ: 124 | return "DT_PREINIT_ARRAYSZ"; 125 | case DT_NUM: 126 | return "DT_NUM"; 127 | case DT_LOOS: 128 | return "DT_LOOS"; 129 | case DT_HIOS: 130 | return "DT_HIOS"; 131 | case DT_LOPROC: 132 | return "DT_LOPROC"; 133 | case DT_HIPROC: 134 | return "DT_HIPROC"; 135 | case DT_PROCNUM: 136 | return "DT_PROCNUM"; 137 | default: 138 | break; 139 | } 140 | 141 | return "DT_UNKNOWN"; 142 | } 143 | 144 | std::string dyn_item::to_string() 145 | { 146 | return std::string((char *)&dyn_item_, sizeof(Elf32_Dyn)); 147 | } 148 | 149 | /******************************************************************************/ -------------------------------------------------------------------------------- /Core/dyn_item.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file dyn_item.h 2017\5\11 20:36:47 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef DYN_ITEM_5B5FA2C1_1C4D_4AFD_8487_E88884C88742_H__ 8 | #define DYN_ITEM_5B5FA2C1_1C4D_4AFD_8487_E88884C88742_H__ 9 | 10 | #include "elf.h" 11 | #include 12 | /******************************************************************************/ 13 | 14 | /** 15 | * The class dyn_item 16 | * 17 | */ 18 | class dyn_item 19 | { 20 | public: 21 | /** @name Constructors and Destructor*/ 22 | 23 | //@{ 24 | /** 25 | * Constructor 26 | */ 27 | dyn_item(); 28 | /** 29 | * Destructor 30 | */ 31 | ~dyn_item(); 32 | //@} 33 | 34 | public: 35 | 36 | /** 37 | * @fn bool dyn_item::from_string(std::string str_content); 38 | * 39 | * @brief Initializes dynamic item from the given string. 40 | * 41 | * @param str_content - input string 42 | * 43 | * @return parse operation result 44 | */ 45 | bool from_string(std::string str_content); 46 | 47 | /** 48 | * @fn std::string dyn_item::to_string(); 49 | * 50 | * @brief Converts this object to a string. 51 | * 52 | * @return This object as a std::string. 53 | */ 54 | std::string to_string(); 55 | 56 | /** 57 | * @fn std::string dyn_item::print(); 58 | * 59 | * @brief print section content in styled format 60 | * 61 | * @return formated style section content 62 | */ 63 | std::string print(); 64 | 65 | /** 66 | * @fn int dyn_item::size() 67 | * 68 | * @brief get size of dynamic item 69 | * 70 | * @return item size 71 | */ 72 | int size(){ return sizeof(Elf32_Dyn); } 73 | 74 | /** 75 | * @fn int dyn_item::get_tag() 76 | * 77 | * @brief Gets the tag. 78 | * 79 | * @return The tag. 80 | */ 81 | Elf32_Sword get_tag(){ return dyn_item_.d_tag; } 82 | Elf32_Word get_value(){ return dyn_item_.d_un.d_val; } 83 | Elf32_Addr get_addr(){ return dyn_item_.d_un.d_ptr; } 84 | 85 | /** 86 | * @fn bool dyn_item::is_valid() 87 | * 88 | * @brief Query if this object is valid. 0x12345678 means self define invalid value, init in constructor 89 | * 90 | * @return True if valid, false if not. 91 | */ 92 | bool is_valid(){ return dyn_item_.d_tag != 0x12345678; } 93 | 94 | private: 95 | 96 | /** 97 | * @fn std::string dyn_item::tag_2_string(int tag); 98 | * 99 | * @brief convert dynamic item to string 100 | * 101 | * @param tag - tag type 102 | * 103 | * @return tag in string format 104 | */ 105 | std::string tag_2_string(int tag); 106 | 107 | private: 108 | Elf32_Dyn dyn_item_; 109 | }; 110 | /******************************************************************************/ 111 | #endif// DYN_ITEM_5B5FA2C1_1C4D_4AFD_8487_E88884C88742_H__ 112 | -------------------------------------------------------------------------------- /Core/dyn_section.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file dyn_section.cpp 2017\5\11 23:34:00 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "dyn_section.h" 8 | #include "elf_segment.h" 9 | #include "log.h" 10 | #include 11 | 12 | /******************************************************************************/ 13 | 14 | // ----------------------------------------------------------------------------- 15 | // dyn_section: Public, Constructor 16 | 17 | dyn_section::dyn_section() 18 | { 19 | 20 | } 21 | 22 | // ----------------------------------------------------------------------------- 23 | // dyn_section: Public, Destructor 24 | 25 | dyn_section::~dyn_section() 26 | { 27 | 28 | } 29 | 30 | /******************************************************************************/ 31 | bool dyn_section::from_string(std::string str_content) 32 | { 33 | LOG(DBG, "read dyn section from string"); 34 | if (str_content.empty()){ 35 | LOG(ERR, "read dyn items from string, but string empty"); 36 | return false; 37 | } 38 | 39 | for (Elf32_Dyn *dyn = (Elf32_Dyn *)str_content.c_str(); dyn->d_tag != DT_NULL; dyn++){ 40 | LOG(DBG, "read dyn item flag=%d, value=0x%x", dyn->d_tag, dyn->d_un.d_val); 41 | 42 | dyn_item item; 43 | item.from_string(std::string((char *)dyn, sizeof(Elf32_Dyn))); 44 | items_.push_back(item); 45 | } 46 | return true; 47 | } 48 | 49 | std::string dyn_section::to_string() 50 | { 51 | std::string dyn_section_; 52 | for (dyn_item itr : items_){ 53 | dyn_section_.append(itr.to_string()); 54 | } 55 | 56 | LOG(DBG, "dyn_section to string"); 57 | return dyn_section_; 58 | } 59 | 60 | std::string dyn_section::print() 61 | { 62 | std::string styled_section; 63 | for (dyn_item itr : items_){ 64 | styled_section += (itr.print() + "\n"); 65 | } 66 | 67 | LOG(DBG, "print dyn section content"); 68 | return styled_section; 69 | } 70 | 71 | dyn_item dyn_section::find_dyn_by_tag(int tag) 72 | { 73 | dyn_item rs_item; 74 | auto itr = std::find_if(items_.begin(), items_.end(), 75 | [=](dyn_item &item)->bool{ 76 | return (tag == item.get_tag()); 77 | }); 78 | if (itr != items_.end()){ 79 | return *itr; 80 | } 81 | 82 | return rs_item; 83 | } 84 | 85 | void dyn_section::save_section_information(std::string section_content) 86 | { 87 | section_content_ = section_content; 88 | } 89 | 90 | std::string dyn_section::get_section_information() 91 | { 92 | return section_content_; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /Core/dyn_section.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file dyn_section.h 2017\5\11 23:13:59 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef DYN_SECTION_A3C72CD4_8D8B_4985_8C19_1FE84230709F_H__ 8 | #define DYN_SECTION_A3C72CD4_8D8B_4985_8C19_1FE84230709F_H__ 9 | 10 | #include "elf.h" 11 | #include 12 | #include 13 | #include "dyn_item.h" 14 | #include "elf_section.h" 15 | /******************************************************************************/ 16 | 17 | /** 18 | * The class dyn_section 19 | * 20 | */ 21 | class dyn_section 22 | { 23 | public: 24 | /** @name Constructors and Destructor*/ 25 | 26 | //@{ 27 | /** 28 | * Constructor 29 | */ 30 | dyn_section(); 31 | /** 32 | * Destructor 33 | */ 34 | ~dyn_section(); 35 | //@} 36 | 37 | public: 38 | 39 | /** 40 | * @fn bool dyn_section::from_string(std::string str_content); 41 | * 42 | * @brief Initializes dyn section from the given string. 43 | * 44 | * @param str_content - input string 45 | * 46 | * @return True if it succeeds, false if it fails. 47 | */ 48 | bool from_string(std::string str_content); 49 | 50 | /** 51 | * @fn void dyn_section::save_section_information(std::string section_content); 52 | * 53 | * @brief Saves dynamic section information. 54 | * 55 | * @param section_content The section content. 56 | */ 57 | void save_section_information(std::string section_content); 58 | 59 | /** 60 | * @fn elf_section dyn_section::get_section_information(); 61 | * 62 | * @brief Gets the section format of the dynamic section. 63 | * 64 | * @return The section. 65 | */ 66 | std::string get_section_information(); 67 | 68 | /** 69 | * @fn std::string dyn_section::to_string(); 70 | * 71 | * @brief Converts this object to a string. 72 | * 73 | * @return This object as a std::string. 74 | */ 75 | std::string to_string(); 76 | 77 | /** 78 | * @fn std::string dyn_section::print(); 79 | * 80 | * @brief print section main information in styled format 81 | * 82 | * @return styled format content 83 | */ 84 | std::string print(); 85 | 86 | /** 87 | * @fn int dyn_section::size() 88 | * 89 | * @brief get dyn sectoin size 90 | * 91 | * @return section size 92 | */ 93 | int size(){ return items_.size() * sizeof(dyn_item); } 94 | 95 | /** 96 | * @fn int dyn_section::count() 97 | * 98 | * @brief get dyn count in .dynamic section 99 | * 100 | * @return item count 101 | */ 102 | int count(){ return items_.size(); } 103 | 104 | public: 105 | 106 | /** 107 | * @fn dyn_item dyn_section::find_dyn_by_tag(int tag); 108 | * 109 | * @brief Searches for the dynamic item by tag. 110 | * 111 | * @param tag - the input tag to search 112 | * 113 | * @return The found dynamic by tag. 114 | */ 115 | dyn_item find_dyn_by_tag(int tag); 116 | 117 | private: 118 | //items in the .dynamic section 119 | std::vector items_; 120 | 121 | //dynamic section 122 | std::string section_content_; 123 | }; 124 | /******************************************************************************/ 125 | #endif// DYN_SECTION_A3C72CD4_8D8B_4985_8C19_1FE84230709F_H__ 126 | -------------------------------------------------------------------------------- /Core/elf_common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/Core/elf_common.h -------------------------------------------------------------------------------- /Core/elf_header.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file elf_header.cpp 2017\5\11 9:18:00 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "elf_header.h" 8 | #include "log.h" 9 | #include "util/util.h" 10 | #include 11 | 12 | /******************************************************************************/ 13 | 14 | // ----------------------------------------------------------------------------- 15 | // elf_header: Public, Constructor 16 | 17 | elf_header::elf_header() 18 | { 19 | memset(&header_, 0, sizeof(header_)); 20 | } 21 | 22 | // ----------------------------------------------------------------------------- 23 | // elf_header: Public, Destructor 24 | 25 | elf_header::~elf_header() 26 | { 27 | 28 | } 29 | 30 | bool elf_header::from_string(std::string str_content) 31 | { 32 | //check content size 33 | if (str_content.size() < sizeof(Elf32_Ehdr)){ 34 | LOG(ERR, "parse elf_header from string, but input string length invalid, len=%d", str_content.size()); 35 | return false; 36 | } 37 | 38 | //copy header content 39 | memcpy((char *)&header_, str_content.c_str(), sizeof(Elf32_Ehdr)); 40 | 41 | //check if header content is valid 42 | return is_valid(); 43 | } 44 | 45 | static int GetTargetElfMachine() { 46 | #if defined(__arm__) 47 | return EM_ARM; 48 | #elif defined(__aarch64__) 49 | return EM_AARCH64; 50 | #elif defined(__i386__) 51 | return EM_386; 52 | #elif defined(__mips__) 53 | return EM_MIPS; 54 | #elif defined(__x86_64__) 55 | return EM_X86_64; 56 | #endif 57 | 58 | return EM_ARM; 59 | } 60 | 61 | bool elf_header::is_valid() 62 | { 63 | LOG(DBG, "elf header now check is valid..."); 64 | if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) { 65 | LOG(ERR, "elf header magic is invalid"); 66 | return false; 67 | } 68 | 69 | // Try to give a clear diagnostic for ELF class mismatches, since they're 70 | // an easy mistake to make during the 32-bit/64-bit transition period. 71 | int elf_class = header_.e_ident[EI_CLASS]; 72 | if (elf_class != ELFCLASS32) { 73 | if (elf_class == ELFCLASS64) { 74 | LOG(WARN, "elf header is 64-bit instead of 32-bit"); 75 | } 76 | else { 77 | LOG(WARN, "elf header has unknown ELF class: %d", elf_class); 78 | } 79 | return false; 80 | } 81 | 82 | if (header_.e_ident[EI_DATA] != ELFDATA2LSB) { 83 | LOG(ERR, "elf header is not little-endian: %d", header_.e_ident[EI_DATA]); 84 | return false; 85 | } 86 | 87 | if (header_.e_type != ET_DYN) { 88 | LOG(ERR, "elf header has unexpected e_type: %d", header_.e_type); 89 | return false; 90 | } 91 | 92 | if (header_.e_version != EV_CURRENT) { 93 | LOG(ERR, "elf header has unexpected e_version: %d", header_.e_version); 94 | return false; 95 | } 96 | 97 | if (header_.e_machine != GetTargetElfMachine()) { 98 | LOG(ERR, "elf header has unexpected e_machine: %d", header_.e_machine); 99 | return false; 100 | } 101 | 102 | LOG(DBG, "ok, elf header is valid"); 103 | return true; 104 | } 105 | 106 | std::string elf_header::print() 107 | { 108 | std::string styled_header; 109 | styled_header += ("Elf Header Size: " + util::itoa(header_.e_ehsize) + "\n"); 110 | styled_header += ("Type: " + type_2_string(header_.e_type) + "\n"); 111 | styled_header += ("Machine: " + util::itoa(header_.e_machine) + "\n"); 112 | styled_header += ("Version: " + util::itoa(header_.e_version) + "\n"); 113 | styled_header += ("Entry: " + util::itoa(header_.e_entry) + "\n"); 114 | styled_header += ("Program Header Offset: " + util::itoa(header_.e_phoff) + "\n"); 115 | styled_header += ("Program Header Item Size: " + util::itoa(header_.e_phentsize) + "\n"); 116 | styled_header += ("Program Header Count: " + util::itoa(header_.e_phnum) + "\n"); 117 | styled_header += ("Section Header Offset: " + util::itoa(header_.e_shoff) + "\n"); 118 | styled_header += ("Section Header Item Size: " + util::itoa(header_.e_shentsize) + "\n"); 119 | styled_header += ("Section Header Count: " + util::itoa(header_.e_shnum) + "\n"); 120 | styled_header += ("Section Header StringTable Index: " + util::itoa(header_.e_shstrndx) + "\n"); 121 | styled_header += ("Flags: " + util::itoa(header_.e_flags) + "\n"); 122 | 123 | return styled_header; 124 | } 125 | 126 | std::string elf_header::type_2_string(Elf32_Half type) 127 | { 128 | switch (type){ 129 | case ET_NONE: 130 | return "ET_NONE"; 131 | case ET_REL: 132 | return "ET_REL"; 133 | case ET_EXEC: 134 | return "ET_EXEC"; 135 | case ET_DYN: 136 | return "ET_DYN"; 137 | case ET_CORE: 138 | return "ET_CORE"; 139 | case ET_LOPROC: 140 | return "ET_LOPROC"; 141 | case ET_HIPROC: 142 | return "ET_HIPROC"; 143 | default: 144 | return "ET_UNKOWN"; 145 | } 146 | } 147 | 148 | std::string elf_header::to_string() 149 | { 150 | std::string elf_header_string_; 151 | return std::string((const char*)&header_, sizeof(Elf32_Ehdr)); 152 | } 153 | 154 | /******************************************************************************/ -------------------------------------------------------------------------------- /Core/elf_header.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file elf_header.h 2017\5\11 9:17:19 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef ELF_HEADER_A895F373_37CD_4A8E_BD6C_879AA0445273_H__ 8 | #define ELF_HEADER_A895F373_37CD_4A8E_BD6C_879AA0445273_H__ 9 | 10 | #include "elf.h" 11 | #include 12 | /******************************************************************************/ 13 | 14 | /** 15 | * The class elf_header 16 | * 17 | */ 18 | class elf_header 19 | { 20 | public: 21 | /** @name Constructors and Destructor*/ 22 | 23 | //@{ 24 | /** 25 | * Constructor 26 | */ 27 | elf_header(); 28 | /** 29 | * Destructor 30 | */ 31 | ~elf_header(); 32 | //@} 33 | 34 | public: 35 | 36 | /** 37 | * @fn bool elf_header::from_string(const char *str_content); 38 | * 39 | * @brief Initializes elf header from the given string. 40 | * 41 | * @param str_content - string contains the elf header content 42 | * 43 | * @return True if it succeeds, false if it fails. 44 | */ 45 | bool from_string(std::string str_content); 46 | 47 | /** 48 | * @fn std::string elf_header::to_string(); 49 | * 50 | * @brief Converts this object to a string. 51 | * 52 | * @return This object as a std::string. 53 | */ 54 | std::string to_string(); 55 | 56 | 57 | /** 58 | * @fn std::string elf_header::print(); 59 | * 60 | * @brief print the elf header as a styled string 61 | * 62 | * @return formated elf header content string 63 | */ 64 | std::string print(); 65 | 66 | /** 67 | * @fn int elf_header::size() 68 | * 69 | * @brief get elf header size 70 | * 71 | * @return elf header size 72 | */ 73 | int size(){ return sizeof(Elf32_Ehdr); } 74 | 75 | /** 76 | * @fn Elf32_Ehdr elf_header::get_header() 77 | * 78 | * @brief Gets the orignal header content. 79 | * 80 | * @return The header. 81 | */ 82 | Elf32_Ehdr &get_header(){ return header_; }; 83 | private: 84 | 85 | /** 86 | * @fn bool elf_header::is_valid(); 87 | * 88 | * @brief check if this elf header is valid after is loaded by from string 89 | * 90 | * @return True if valid, false if not. 91 | */ 92 | bool is_valid(); 93 | 94 | /** 95 | * @fn std::string elf_header::type_2_string(Elf32_Half type); 96 | * 97 | * @brief convert elf image type from integer type to string format. 98 | * 99 | * @param type The type. 100 | * 101 | * @return elf type in string format. 102 | */ 103 | std::string type_2_string(Elf32_Half type); 104 | private: 105 | Elf32_Ehdr header_; 106 | }; 107 | /******************************************************************************/ 108 | #endif// ELF_HEADER_A895F373_37CD_4A8E_BD6C_879AA0445273_H__ 109 | -------------------------------------------------------------------------------- /Core/elf_section.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file elf_section.cpp 2017\5\11 17:35:33 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "elf_section.h" 8 | #include "log.h" 9 | #include "util/util.h" 10 | 11 | /******************************************************************************/ 12 | 13 | // ----------------------------------------------------------------------------- 14 | // elf_section: Public, Constructor 15 | 16 | elf_section::elf_section() 17 | { 18 | memset(&header_, 0, sizeof(header_)); 19 | } 20 | 21 | // ----------------------------------------------------------------------------- 22 | // elf_section: Public, Destructor 23 | 24 | elf_section::~elf_section() 25 | { 26 | 27 | } 28 | 29 | bool elf_section::from_string(std::string str_content) 30 | { 31 | LOG(DBG, "read elf section header from string"); 32 | 33 | //check input string len is valid 34 | if (str_content.size() < sizeof(Elf32_Shdr)){ 35 | LOG(ERR, "read section header from string, but string len invalid, len = %d", str_content.size()); 36 | return false; 37 | } 38 | 39 | //copy content 40 | memcpy((char *)&header_, str_content.c_str(), sizeof(Elf32_Shdr)); 41 | return true; 42 | } 43 | 44 | std::string elf_section::print() 45 | { 46 | std::string styled_header; 47 | styled_header += ("Name: " + util::itoa(header_.sh_name) + "\n"); 48 | styled_header += ("Type: " + util::itoa(header_.sh_type) + "\n"); 49 | styled_header += ("Flags: " + util::itoa(header_.sh_flags) + "\n"); 50 | styled_header += ("VA: " + util::itoa(header_.sh_addr) + "\n"); 51 | styled_header += ("File Offset: " + util::itoa(header_.sh_offset) + "\n"); 52 | styled_header += ("Size: " + util::itoa(header_.sh_size) + "\n"); 53 | styled_header += ("Link: " + util::itoa(header_.sh_link) + "\n"); 54 | styled_header += ("Info: " + util::itoa(header_.sh_info) + "\n"); 55 | styled_header += ("Align: " + util::itoa(header_.sh_addralign) + "\n"); 56 | styled_header += ("Entry Size: " + util::itoa(header_.sh_entsize) + "\n"); 57 | 58 | return styled_header; 59 | } 60 | 61 | std::string elf_section::to_string() 62 | { 63 | return std::string((const char*)&header_, sizeof(Elf32_Shdr)); 64 | } 65 | 66 | /******************************************************************************/ -------------------------------------------------------------------------------- /Core/elf_section.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file elf_section.h 2017\5\11 17:35:21 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef ELF_SECTION_0586B544_8DB2_4341_B7AC_8FD436EC9F52_H__ 8 | #define ELF_SECTION_0586B544_8DB2_4341_B7AC_8FD436EC9F52_H__ 9 | 10 | #include "elf.h" 11 | #include 12 | /******************************************************************************/ 13 | 14 | /** 15 | * The class elf_section 16 | * 17 | */ 18 | class elf_section 19 | { 20 | public: 21 | /** @name Constructors and Destructor*/ 22 | 23 | //@{ 24 | /** 25 | * Constructor 26 | */ 27 | elf_section(); 28 | /** 29 | * Destructor 30 | */ 31 | ~elf_section(); 32 | //@} 33 | 34 | public: 35 | 36 | /** 37 | * @fn bool elf_section::from_string(std::string str_content); 38 | * 39 | * @brief Initializes this section header from the given string. 40 | * 41 | * @param str_content - input string 42 | * 43 | * @return True if it succeeds, false if it fails. 44 | */ 45 | bool from_string(std::string str_content); 46 | 47 | /** 48 | * @fn std::string elf_section::to_string(); 49 | * 50 | * @brief Converts this header to a string. 51 | * 52 | * @return This header as a std::string. 53 | */ 54 | std::string to_string(); 55 | 56 | /** 57 | * @fn std::string elf_section::print(); 58 | * 59 | * @brief print the section header 60 | * 61 | * @return styled section header string 62 | */ 63 | std::string print(); 64 | 65 | /** 66 | * @fn int elf_section::size() 67 | * 68 | * @brief get section header size 69 | * 70 | * @return header size 71 | */ 72 | int size(){ return sizeof(Elf32_Shdr); } 73 | 74 | /** 75 | * @fn Elf32_Shdr elf_section::&get_header() 76 | * 77 | * @brief Gets the header content reference, so header_ may be modified 78 | * 79 | * @return The header. 80 | */ 81 | Elf32_Shdr &get_header(){ return header_; } 82 | 83 | private: 84 | Elf32_Shdr header_; 85 | }; 86 | /******************************************************************************/ 87 | #endif// ELF_SECTION_0586B544_8DB2_4341_B7AC_8FD436EC9F52_H__ 88 | -------------------------------------------------------------------------------- /Core/elf_segment.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file elf_segment.cpp 2017\5\11 19:06:03 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "elf_segment.h" 8 | #include "log.h" 9 | #include "util/util.h" 10 | 11 | /******************************************************************************/ 12 | 13 | // ----------------------------------------------------------------------------- 14 | // elf_segment: Public, Constructor 15 | 16 | elf_segment::elf_segment() 17 | { 18 | memset(&header_, 0, sizeof(header_)); 19 | } 20 | 21 | // ----------------------------------------------------------------------------- 22 | // elf_segment: Public, Destructor 23 | 24 | elf_segment::~elf_segment() 25 | { 26 | 27 | } 28 | 29 | bool elf_segment::from_string(std::string str_content) 30 | { 31 | LOG(DBG, "read elf program header from string"); 32 | 33 | //check if string contains enough content 34 | if (str_content.size() < sizeof(Elf32_Phdr)){ 35 | LOG(ERR, "read elf program header, but input string len is invalid, len=%d", str_content.size()); 36 | return false; 37 | } 38 | 39 | //copy content 40 | memcpy((char *)&header_, str_content.c_str(), sizeof(Elf32_Phdr)); 41 | return true; 42 | } 43 | 44 | std::string elf_segment::print() 45 | { 46 | std::string styled_header; 47 | styled_header += ("Type: " + util::itoa(header_.p_type) + "\n"); 48 | styled_header += ("Flags: " + util::itoa(header_.p_flags) + "\n"); 49 | styled_header += ("Offset: " + util::itoa(header_.p_offset) + "\n"); 50 | styled_header += ("VA: " + util::itoa(header_.p_vaddr) + "\n"); 51 | styled_header += ("PA: " + util::itoa(header_.p_paddr) + "\n"); 52 | styled_header += ("File Size: " + util::itoa(header_.p_filesz) + "\n"); 53 | styled_header += ("Mem Size: " + util::itoa(header_.p_memsz) + "\n"); 54 | styled_header += ("Align: " + util::itoa(header_.p_align) + "\n"); 55 | 56 | return styled_header; 57 | } 58 | 59 | /******************************************************************************/ -------------------------------------------------------------------------------- /Core/elf_segment.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file elf_segment.h 2017\5\11 19:05:50 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef ELF_SEGMENT_3E338771_FA63_4EA5_901D_3EA3626BFA54_H__ 8 | #define ELF_SEGMENT_3E338771_FA63_4EA5_901D_3EA3626BFA54_H__ 9 | 10 | /******************************************************************************/ 11 | #include "elf.h" 12 | #include 13 | /** 14 | * The class elf_segment 15 | * 16 | */ 17 | class elf_segment 18 | { 19 | public: 20 | /** @name Constructors and Destructor*/ 21 | 22 | //@{ 23 | /** 24 | * Constructor 25 | */ 26 | elf_segment(); 27 | /** 28 | * Destructor 29 | */ 30 | ~elf_segment(); 31 | //@} 32 | 33 | public: 34 | 35 | /** 36 | * @fn bool elf_segment::from_string(std::string str_content); 37 | * 38 | * @brief Initializes program header from the given string 39 | * 40 | * @param str_content - input string 41 | * 42 | * @return True if it succeeds, false if it fails. 43 | */ 44 | bool from_string(std::string str_content); 45 | 46 | /** 47 | * @fn std::string elf_segment::print(); 48 | * 49 | * @brief print the section header in styled format string 50 | * 51 | * @return section content in styled format 52 | */ 53 | std::string print(); 54 | 55 | /** 56 | * @fn int elf_segment::size() 57 | * 58 | * @brief get program header size 59 | * 60 | * @return header size 61 | */ 62 | int size(){ return sizeof(Elf32_Phdr); } 63 | 64 | /** 65 | * @fn Elf32_Phdr elf_segment::get_header() 66 | * 67 | * @brief Gets the header. 68 | * 69 | * @return The header. 70 | */ 71 | Elf32_Phdr get_header(){ return header_; } 72 | 73 | private: 74 | Elf32_Phdr header_; 75 | }; 76 | /******************************************************************************/ 77 | #endif// ELF_SEGMENT_3E338771_FA63_4EA5_901D_3EA3626BFA54_H__ 78 | -------------------------------------------------------------------------------- /Core/features.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _FEATURES_H_ 29 | #define _FEATURES_H_ 30 | 31 | /* certain Linux-specific programs expect a header file 32 | * that defines various features macros 33 | */ 34 | 35 | /* we do include a number of BSD extensions */ 36 | #define _BSD_SOURCE 1 37 | 38 | /* we do include a number of GNU extensions */ 39 | #define _GNU_SOURCE 1 40 | 41 | /* C95 support */ 42 | #undef __USE_ISOC95 43 | #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199409L 44 | # define __USE_ISOC95 1 45 | #endif 46 | 47 | /* C99 support */ 48 | #undef __USE_ISOC99 49 | #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L 50 | # define __USE_ISOC99 1 51 | #endif 52 | 53 | /* Posix support */ 54 | #define __USE_POSIX 1 55 | #define __USE_POSIX2 1 56 | #define __USE_XPG 1 57 | 58 | #endif /* _FEATURES_H_ */ 59 | -------------------------------------------------------------------------------- /IDAScript/IDADumpMemory.py: -------------------------------------------------------------------------------- 1 | 2 | # dump memory from IDA Debugger 3 | # 4 | 5 | import idautils 6 | import idc 7 | import idaapi 8 | import struct 9 | 10 | 11 | def main(ea_start, ea_end, save_file): 12 | print '[*]begin to dump segment' 13 | 14 | handle_f = open(save_file, 'wb') 15 | for byte_addr in range(ea_start, ea_end): 16 | byte_value = idaapi.get_byte(byte_addr) 17 | handle_f.write(struct.pack('B',byte_value)) 18 | 19 | handle_f.close() 20 | hooks = idaapi.DBG_Hooks() 21 | hooks.hook() 22 | 23 | print '[*]script by freakish, enjoy~~' 24 | print '[*]script finish' 25 | 26 | 27 | ea_start = 0xE20 28 | ea_size = 0x7000 29 | 30 | ea_end = ea_start + ea_size 31 | save_file = 'd:/text.so' 32 | 33 | main(ea_start, ea_end, save_file) -------------------------------------------------------------------------------- /IDAScript/IDAMemorySearch.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idc 3 | import idautils 4 | 5 | print '[*]begin to find...' 6 | 7 | rodata_ea_start = 0 8 | local_sections = Segments() 9 | for section in local_sections: 10 | seg_name = SegName(section) 11 | if seg_name != '[anon:libc_malloc]': 12 | continue 13 | 14 | # 准备查找 15 | rodata_ea_start = section 16 | rodata_ea_end = SegEnd(rodata_ea_start) 17 | print('\t[-]begin to search segment:%x' % rodata_ea_start) 18 | for ea_offset in range(rodata_ea_start, rodata_ea_end): 19 | cur_dword = idaapi.get_dword(ea_offset) 20 | if cur_dword != None and cur_dword == 0x1: 21 | print('found target addr=%x' % ea_offset) 22 | 23 | print '[*]script by freakish, enjoy~~' 24 | print '[*]script finish' -------------------------------------------------------------------------------- /IDAScript/JNI_InitFunctions_BreakPoint.py: -------------------------------------------------------------------------------- 1 | import idautils 2 | import idc 3 | import idaapi 4 | 5 | 6 | def main(): 7 | print '[*]begin to find .rodata segment' 8 | 9 | # locate to .rodata segment 10 | rodata_ea_start = 0 11 | local_sections = Segments() 12 | for section in local_sections: 13 | seg_name = SegName(section) 14 | if seg_name == '.rodata': 15 | rodata_ea_start = section 16 | break 17 | 18 | if rodata_ea_start == 0: 19 | print '\t[-]can not locate .rodata segment' 20 | return 21 | 22 | rodata_ea_end = SegEnd(rodata_ea_start) 23 | # search for string "DT_INIT" 24 | 25 | print '\t[-]begin to search DT_INIT' 26 | string_dt_init_ea = 0 27 | for ea_offset in range(rodata_ea_start, rodata_ea_end): 28 | cur_string = GetString(ea_offset) 29 | if cur_string != None and cur_string == 'DT_INIT': 30 | string_dt_init_ea = ea_offset 31 | break 32 | 33 | print '\t[-]found string DT_INIT 0x%08X' % string_dt_init_ea 34 | 35 | # xref to DT_INIT... 36 | refs = XrefsTo(string_dt_init_ea) 37 | useful_ref = 0 38 | for ref in refs: 39 | useful_ref = ref.frm 40 | break 41 | 42 | print '\t[-]try set breakpoint there=>DT_INIT' 43 | AddBpt(useful_ref) 44 | 45 | # xref to DT_INIT_ARRAY 46 | string_dt_init_array_ea = 0 47 | for ea_offset in range(rodata_ea_start, rodata_ea_end): 48 | cur_string = GetString(ea_offset) 49 | if cur_string != None and cur_string == 'DT_INIT_ARRAY': 50 | string_dt_init_array_ea = ea_offset 51 | break 52 | 53 | print '\t[-]found string DT_INIT_ARRAY 0x%08X' % string_dt_init_array_ea 54 | 55 | # xref to DT_INIT_ARRAY... 56 | refs = XrefsTo(string_dt_init_array_ea) 57 | useful_ref = 0 58 | for ref in refs: 59 | useful_ref = ref.frm 60 | break 61 | 62 | print '\t[-]try set breakpoint there=>DT_INIT_ARRAY' 63 | AddBpt(useful_ref) 64 | 65 | # xref to DT_PREINIT_ARRAY 66 | string_dt_pre_init_array_ea = 0 67 | for ea_offset in range(rodata_ea_start, rodata_ea_end): 68 | cur_string = GetString(ea_offset) 69 | if cur_string != None and cur_string == 'DT_PREINIT_ARRAY': 70 | string_dt_pre_init_array_ea = ea_offset 71 | break 72 | 73 | print '\t[-]found string DT_PREINIT_ARRAY 0x%08X' % string_dt_pre_init_array_ea 74 | 75 | # xref to DT_PREINIT_ARRAY... 76 | refs = XrefsTo(string_dt_pre_init_array_ea) 77 | useful_ref = 0 78 | for ref in refs: 79 | useful_ref = ref.frm 80 | break 81 | 82 | print '\t[-]try set breakpoint there=>DT_PREINIT_ARRAY' 83 | AddBpt(useful_ref) 84 | 85 | print '[*]script by freakish, enjoy~~' 86 | print '[*]script finish' 87 | 88 | main() -------------------------------------------------------------------------------- /IDAScript/JNI_InitFunctions_BreakPoint_Ex.py: -------------------------------------------------------------------------------- 1 | import idautils 2 | import idc 3 | import idaapi 4 | 5 | #linker call init and init_array functions 6 | #.text:000026DE 20 46 MOV R0, R4 7 | #.text:000026E0 D4 F8 F0 20 LDR.W R2, [R4,#0xF0] 8 | #.text:000026E4 79 44 ADD R1, PC ; "DT_INIT" 9 | #.text:000026E6 FF F7 A9 FE BL __dl__ZN6soinfo13call_functionEPKcPFvvE 10 | #.text:000026EA 0D 49 LDR R1, =(aDt_init_array - 0x26F6) 11 | #.text:000026EC 00 22 MOVS R2, #0 12 | #.text:000026EE 00 92 STR R2, [SP,#0x18+var_18] 13 | 14 | 15 | #linker call pre_init_array, but in shared library like android so, pre_init_array will not be called 16 | 17 | def main(): 18 | # begin to locate linker module base 19 | 20 | has_art = False 21 | module_base = GetFirstModule() 22 | while module_base != None: 23 | module_name = GetModuleName(module_base) 24 | if module_name.find('linker') >= 0: 25 | has_art = True 26 | break 27 | 28 | module_base = GetNextModule(module_base) 29 | 30 | if has_art == False: 31 | print '[*]unable to find libart.so module base' 32 | return 33 | 34 | module_size = GetModuleSize(module_base) 35 | print '[*]found linker base=>0x%08X, Size=0x%08X' % (module_base, module_size) 36 | 37 | 38 | print("\t[-]begin to search DT_INIT And DT_INIT_ARRAY") 39 | init_func_ea = 0 40 | init_array_ea = 0 41 | for ea_offset in range(module_base, module_base + module_size): 42 | # i don't want to write a huge single line like 'if x and x and x and...', so many ifs apear 43 | 44 | if 0x4620 == idaapi.get_word(ea_offset): 45 | if 0x20F0F8D4 == idaapi.get_long(ea_offset + 2): 46 | if 0x4479 == idaapi.get_word(ea_offset + 6): 47 | if 0xFEA9F7FF == idaapi.get_word(ea_offset + 8): 48 | if 0x490D == idaapi.get_word(ea_offset + 12): 49 | if 0x2200 == idaapi.get_long(ea_offset + 14): 50 | if 0x9200 == idaapi.get_word(ea_offset + 16): 51 | init_func_ea = ea_offset + 8 52 | init_array_ea = ea_offset + 30 53 | break 54 | 55 | print "\t[-]found INIT=>0x%08X INIT_ARRAY=>0x%08X" % (init_func_ea, init_array_ea) 56 | print("\t[-]try set breakpoint there") 57 | AddBpt(init_func_ea) 58 | AddBpt(init_array_ea) 59 | 60 | print("[*]script by freakish, enjoy~~") 61 | print("[*]script finish") 62 | 63 | main() -------------------------------------------------------------------------------- /IDAScript/JNI_OnLoad_BreakPoint.py: -------------------------------------------------------------------------------- 1 | import idautils 2 | import idc 3 | import idaapi 4 | 5 | 6 | def main(): 7 | print '[*]begin to find .rodata segment' 8 | 9 | # locate to .rodata segment 10 | rodata_ea_start = 0 11 | local_sections = Segments() 12 | for section in local_sections: 13 | seg_name = SegName(section) 14 | if seg_name == '.rodata': 15 | rodata_ea_start = section 16 | break 17 | 18 | if rodata_ea_start == 0: 19 | print '\t[-]can not locate .rodata segment' 20 | return 21 | 22 | rodata_ea_end = SegEnd(rodata_ea_start) 23 | # search for string "[Calling JNI_OnLoad in" 24 | 25 | print '\t[-]begin to search JNI_OnLoad' 26 | string_jni_on_load_ea = 0 27 | for ea_offset in range(rodata_ea_start, rodata_ea_end): 28 | cur_string = GetString(ea_offset) 29 | if cur_string != None and cur_string.find('[Calling JNI_OnLoad in')>=0: 30 | string_jni_on_load_ea = ea_offset 31 | break 32 | 33 | print '\t[-]found string JNI_OnLoad 0x%08X' % string_jni_on_load_ea 34 | 35 | # xref to JNI_OnLoad... 36 | refs = XrefsTo(string_jni_on_load_ea) 37 | useful_ref = 0 38 | for ref in refs: 39 | useful_ref = ref.frm 40 | break 41 | 42 | # locate call(fn_jni_on_load) 43 | target_address = 0 44 | 45 | func_items = FuncItems(useful_ref) 46 | for fun_addr in func_items: 47 | if fun_addr >= useful_ref: 48 | op_bytes = idaapi.get_word(fun_addr) 49 | 50 | # call to jni_onload opcode = 0xE494 51 | if 0xE494 == op_bytes: 52 | # calc target address, Thumb-2 instruction, refer about B 53 | target_address = (op_bytes & 0xFFF) << 1 54 | 55 | # extra the sign flag to 32bit wide 56 | if target_address & 0x800 == 0x800: 57 | target_address = target_address | 0xFFFFF000 58 | 59 | # generate the real address 60 | target_address = (target_address + (fun_addr + 4)) & 0xFFFFFFFF 61 | print '\t[-]found jump address:0x%08X, follow it' % target_address 62 | break 63 | 64 | if target_address == 0: 65 | print '[*]no target address to follow, just return' 66 | return 67 | 68 | # relocate target_address func item 69 | func_items = FuncItems(target_address) 70 | 71 | # search BLX R12 instruction 72 | b_can_start_search = False 73 | for fun_addr in func_items: 74 | if fun_addr == target_address: 75 | b_can_start_search = True 76 | continue 77 | 78 | if b_can_start_search == True and 0x47E0 == idaapi.get_word(fun_addr): 79 | print '[*]found call JNI_OnLoad Statement, addr=>0x%08X' % fun_addr) 80 | print '\t[-]try set breakpoint there' 81 | AddBpt(fun_addr) 82 | 83 | print '[*]script by freakish, enjoy~~' 84 | 85 | print '[*]script finish' 86 | 87 | main() -------------------------------------------------------------------------------- /IDAScript/JNI_OnLoad_BreakPoint_Ex.py: -------------------------------------------------------------------------------- 1 | import idautils 2 | import idc 3 | import idaapi 4 | 5 | #libart BLX R12, this statement call jni_onload 6 | #libart.so:F4C80BA2 00 21 MOVS R1, #0 7 | #libart.so:F4C80BA4 30 46 MOV R0, R6 8 | #libart.so:F4C80BA6 E0 47 BLX R12 9 | #libart.so:F4C80BA8 71 68 LDR R1, [R6,#4] 10 | #libart.so:F4C80BAA 84 46 MOV R12, R0 11 | #libart.so:F4C80BAC D1 F8 CC 02 LDR.W R0, [R1,#0x2CC] 12 | #libart.so:F4C80BB0 03 1C MOVS R3, R0 13 | 14 | def main(): 15 | # begin to locate libart.so module base 16 | 17 | has_art = False 18 | module_base = GetFirstModule() 19 | while module_base != None: 20 | module_name = GetModuleName(module_base) 21 | if module_name.find('libart.so') >= 0: 22 | has_art = True 23 | break 24 | 25 | module_base = GetNextModule(module_base) 26 | 27 | if has_art == False: 28 | print '[*]unable to find libart.so module base' 29 | return 30 | 31 | module_size = GetModuleSize(module_base) 32 | print '[*]found libart.so base=>0x%08X, Size=0x%08X' % (module_base, module_size) 33 | 34 | 35 | print("\t[-]begin to search JNI_OnLoad") 36 | blx_r12_ea = 0 37 | for ea_offset in range(module_base, module_base + module_size): 38 | # i don't want to write a huge single line like 'if x and x and x and...', so many ifs apear 39 | 40 | if 0x2100 == idaapi.get_word(ea_offset): 41 | if 0x4630 == idaapi.get_word(ea_offset + 2): 42 | if 0x47E0 == idaapi.get_word(ea_offset + 4): 43 | if 0x6871 == idaapi.get_word(ea_offset + 6): 44 | if 0x4684 == idaapi.get_word(ea_offset + 8): 45 | if 0x02CCF8D1 == idaapi.get_long(ea_offset + 10): 46 | if 0x1C03 == idaapi.get_word(ea_offset + 14): 47 | blx_r12_ea = ea_offset + 4 48 | break 49 | 50 | print "\t[-]found string JNI_OnLoad BLX R12 addr=>0x%X" % blx_r12_ea 51 | print("\t[-]try set breakpoint there") 52 | AddBpt(blx_r12_ea) 53 | 54 | print("[*]script by freakish, enjoy~~") 55 | print("[*]script finish") 56 | 57 | main() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Android So文件浏览修复工具 2 | 3 | #### 项目为什么选择C++ 4 | * 一开始整个项目是用Python写的, 考虑到Python上有很多成熟的库可以直接使用,代码写起来会比较方便,但是真的开始往下写的时候发现,光是各种类型定义就要耗费很多的精力,并且很多逻辑就是从Android的源码中进行代码精简来的, 这个时候直接借鉴Android源码比再翻译成Python要快得多 5 | 6 | #### 项目原则 7 | * 代码风格尽量遵循google style代码风格 8 | * Android系统源码中可以借鉴的代码,尽量直接借鉴 9 | * Core中核心代码要做到平台无关性 10 | 11 | #### So文件浏览 12 | * 显示Elf 头 13 | * 显示Program 头 14 | * 显示Section头 15 | 16 | #### So文件修复 17 | * 完全无Section信息修复 18 | -------------------------------------------------------------------------------- /Windows/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "Core/elf_header.h" 5 | #include "fix/section_fix.h" 6 | 7 | #define MAX_PATH 260 8 | 9 | void print_help(){ 10 | printf("[+]here are all commands:\n"); 11 | printf("\t[-]h --type help commands\n"); 12 | printf("\t[-]build-section --build the so file section with information from the .dynamic segment\n"); 13 | printf("\t[-]quit --quit xAnSo\n"); 14 | } 15 | 16 | void print_hello(){ 17 | printf("[+]what do you want next? type h for help, i am now on your command:\n"); 18 | } 19 | 20 | bool process_cmd(char *cmd){ 21 | if (!strcmp(cmd, "quit")){ 22 | return false; 23 | } 24 | else if (!strcmp(cmd, "h")){ 25 | print_help(); 26 | } 27 | else if (!strcmp(cmd, "build-section")){ 28 | printf("\t[-]input your file name:\n"); 29 | char file_name[MAX_PATH] = { 0 }; 30 | scanf_s("%s", file_name, MAX_PATH); 31 | 32 | //fix section 33 | section_fix fixer_; 34 | if (!fixer_.fix(file_name)){ 35 | printf("\t[-]elf file section build fail\n"); 36 | } 37 | else{ 38 | std::string fixed_name_ = file_name + std::string(".fixed"); 39 | if (!fixer_.save_as(fixed_name_)){ 40 | printf("\t[-]save fixed elf file fail\n"); 41 | } 42 | printf("\t[-]fixed file => %s\n", fixed_name_.c_str()); 43 | printf("\t[-]elf file section build success!\n"); 44 | } 45 | } 46 | 47 | return true; 48 | } 49 | 50 | int main(int argv, char **args) 51 | { 52 | 53 | printf("------------------welcome to xAnSo------------------\n"); 54 | printf("------------------tools for android-----------------\n"); 55 | 56 | while (true) 57 | { 58 | print_hello(); 59 | 60 | char cmd_line[MAX_PATH] = { 0 }; 61 | scanf_s("%s", cmd_line, MAX_PATH); 62 | if (!process_cmd(cmd_line)){ 63 | break; 64 | } 65 | } 66 | 67 | printf("[+]xAnSo exit..."); 68 | return 0; 69 | } -------------------------------------------------------------------------------- /Windows/xAnSo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xAnSo", "xAnSo.vcxproj", "{10343546-DB04-4745-B9D1-CD9027AA2D15}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {10343546-DB04-4745-B9D1-CD9027AA2D15}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {10343546-DB04-4745-B9D1-CD9027AA2D15}.Debug|Win32.Build.0 = Debug|Win32 16 | {10343546-DB04-4745-B9D1-CD9027AA2D15}.Release|Win32.ActiveCfg = Release|Win32 17 | {10343546-DB04-4745-B9D1-CD9027AA2D15}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Windows/xAnSo.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {10343546-DB04-4745-B9D1-CD9027AA2D15} 15 | Win32Proj 16 | xAnSo 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | ../;%(AdditionalIncludeDirectories) 56 | MultiThreadedDebug 57 | 58 | 59 | Console 60 | true 61 | 62 | 63 | 64 | 65 | Level3 66 | 67 | 68 | MaxSpeed 69 | true 70 | true 71 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 72 | MultiThreaded 73 | 74 | 75 | Console 76 | true 77 | true 78 | true 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /Windows/xAnSo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {e9daf14c-b779-41e9-ac3d-b8ef6015d423} 18 | 19 | 20 | {d4197040-30f7-461e-810a-f66c78387502} 21 | 22 | 23 | {0ba25776-38fe-468b-8aac-2bd71f703ab6} 24 | 25 | 26 | {483b616c-0dc0-4933-8d76-608af6db23b6} 27 | 28 | 29 | {d90a35cf-ecb5-44bc-9ee6-1d179ff6cbd1} 30 | 31 | 32 | {b4aa77bd-6936-4f34-8df9-1ad45bc9ade2} 33 | 34 | 35 | {747d0193-2774-42fb-b28d-38752c45d5db} 36 | 37 | 38 | {e3d9fd89-eece-420d-ac60-34c5f62ef0d8} 39 | 40 | 41 | {faf21116-9cc0-4cf1-afc6-26ff913a0471} 42 | 43 | 44 | {43fc9676-126f-4eb8-80f0-305055a3986a} 45 | 46 | 47 | 48 | 49 | 源文件 50 | 51 | 52 | core\ElfHeader 53 | 54 | 55 | log 56 | 57 | 58 | util 59 | 60 | 61 | core\ElfSection 62 | 63 | 64 | core\ElfSegment 65 | 66 | 67 | core\DynSection 68 | 69 | 70 | core\DynSection 71 | 72 | 73 | fix\section_fix 74 | 75 | 76 | 77 | 78 | core 79 | 80 | 81 | core 82 | 83 | 84 | core\ElfHeader 85 | 86 | 87 | log 88 | 89 | 90 | util 91 | 92 | 93 | core\ElfSection 94 | 95 | 96 | core\ElfSegment 97 | 98 | 99 | core\DynSection 100 | 101 | 102 | core\DynSection 103 | 104 | 105 | fix\section_fix 106 | 107 | 108 | -------------------------------------------------------------------------------- /fix/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/fix/readme.txt -------------------------------------------------------------------------------- /fix/section_fix.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file section_fix.cpp 2017\5\12 19:46:41 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "section_fix.h" 8 | #include "log.h" 9 | #include "util/util.h" 10 | #include 11 | #include 12 | 13 | 14 | /******************************************************************************/ 15 | 16 | // ----------------------------------------------------------------------------- 17 | // section_fix: Public, Constructor 18 | 19 | section_fix::section_fix() 20 | { 21 | 22 | } 23 | 24 | // ----------------------------------------------------------------------------- 25 | // section_fix: Public, Destructor 26 | 27 | section_fix::~section_fix() 28 | { 29 | 30 | } 31 | 32 | bool section_fix::fix(std::string src_file) 33 | { 34 | std::string file_content = util::read_file(src_file); 35 | if (file_content.empty()){ 36 | LOG(ERR, "try fix elf section, but file content empty"); 37 | return false; 38 | } 39 | 40 | //save file content 41 | file_content_ = file_content; 42 | 43 | //pre load .dynamic .load segments 44 | if (!pre_load()){ 45 | LOG(ERR, "try fix elf section, but pre load elf file fail"); 46 | return false; 47 | } 48 | 49 | //first create 50 | if (!first_create_sections()){ 51 | LOG(ERR, "try fix elf sectoins, but first create sections fail"); 52 | return false; 53 | } 54 | 55 | //need fix 56 | 57 | return true; 58 | } 59 | 60 | bool section_fix::save_as(std::string dst_file) 61 | { 62 | //0. Serialize created sections as a string 63 | //1. save created sections to the end of the file 64 | //2. adjust elf file header coresponding fields 65 | 66 | std::string section_table; 67 | //0. created the first null section 68 | elf_section null_section; 69 | section_table += null_section.to_string(); 70 | 71 | //1. create sections from .dynamic segments 72 | for (auto itr : vec_created_section_) 73 | { 74 | section_table += itr.to_string(); 75 | } 76 | 77 | // 78 | std::sort(vec_load_.begin(), vec_load_.end(), 79 | [=](elf_segment &item1, elf_segment &item2)->bool{ 80 | return item1.get_header().p_paddr < item2.get_header().p_paddr; 81 | }); 82 | 83 | //2. create .shstrtab section 84 | Elf32_Off sh_str_tab = file_content_.size(); 85 | Elf32_Word sh_str_tab_size = sh_str_.size(); 86 | elf_section sh_str_section; 87 | Elf32_Shdr &header_ = sh_str_section.get_header(); 88 | header_.sh_name = find_string_idx_in_strtab(".shstrtab"); 89 | header_.sh_offset = sh_str_tab; 90 | header_.sh_size = sh_str_tab_size; 91 | elf_segment last_segment = vec_load_[vec_load_.size() - 1]; 92 | header_.sh_addr = header_.sh_offset + (last_segment.get_header().p_paddr - last_segment.get_header().p_offset); 93 | header_.sh_type = SHT_STRTAB; 94 | header_.sh_flags = SHF_ALLOC; 95 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 96 | 97 | section_table += sh_str_section.to_string(); 98 | //3. append shstrtab section content to the end of the file 99 | 100 | file_content_ += sh_str_; 101 | Elf32_Off sh_str_offset = file_content_.size(); 102 | 103 | file_content_ += section_table; 104 | 105 | //4. adjust elf header 106 | elf_header elf_file_header; 107 | if (!elf_file_header.from_string(file_content_)){ 108 | LOG(ERR, "try to save elf file, but header invalid"); 109 | return false; 110 | } 111 | 112 | Elf32_Ehdr &elf_file_header_ = elf_file_header.get_header(); 113 | elf_file_header_.e_shentsize = sizeof(Elf32_Shdr); 114 | elf_file_header_.e_shnum = vec_created_section_.size() + 2; 115 | elf_file_header_.e_shoff = sh_str_offset; 116 | elf_file_header_.e_shstrndx = elf_file_header_.e_shnum - 1; 117 | 118 | //save file 119 | std::ofstream out_file_; 120 | out_file_.open(dst_file, std::ios_base::binary); 121 | if (!out_file_.is_open()){ 122 | LOG(ERR, "try save elf file, but fail, error=%d", errno); 123 | return false; 124 | } 125 | 126 | std::string elf_header_content_ = elf_file_header.to_string(); 127 | out_file_.write(elf_header_content_.c_str(), elf_header_content_.size()); 128 | out_file_.write(file_content_.c_str() + elf_file_header.size(), file_content_.size() - elf_file_header.size()); 129 | LOG(DBG, "save fixed elf file ok"); 130 | return true; 131 | } 132 | 133 | bool section_fix::pre_load() 134 | { 135 | //we load segments whose informations are necessary for the comming operations 136 | // we load PT_LOAD and PT_DYNAMIC segments, which shall exist in an valid elf 137 | 138 | elf_header elf_header_; 139 | if (!elf_header_.from_string(file_content_)){ 140 | LOG(ERR, "try fix elf section, but elf header invalid"); 141 | return false; 142 | } 143 | 144 | Elf32_Ehdr &header_ = elf_header_.get_header(); 145 | Elf32_Off program_header_table = header_.e_phoff; 146 | Elf32_Half program_header_count = header_.e_phnum; 147 | for (int idx = 0; idx < program_header_count; idx++){ 148 | 149 | std::string segment_content = std::string(file_content_.c_str() + program_header_table + idx * sizeof(Elf32_Phdr), sizeof(Elf32_Phdr)); 150 | elf_segment segment_; 151 | segment_.from_string(segment_content); 152 | if (PT_LOAD == segment_.get_header().p_type){ 153 | //found pt_load segment 154 | vec_load_.push_back(segment_); 155 | } 156 | else if (PT_DYNAMIC == segment_.get_header().p_type){ 157 | //found pt_dynamic segment 158 | std::string dynamic_segment_content = std::string(file_content_.c_str() + segment_.get_header().p_offset, segment_.get_header().p_filesz); 159 | dynamic_section_.from_string(dynamic_segment_content); 160 | dynamic_section_.save_section_information(segment_content); 161 | } 162 | } 163 | 164 | return (vec_load_.size() > 0); 165 | } 166 | 167 | bool section_fix::first_create_sections() 168 | { 169 | //first we create sections with informations from the .dynamic segment 170 | // if information in a section in not full, we fix it later 171 | 172 | //#define FILL_SECTION(dyn_tab, dyn_sz, type, flag, name)\ 173 | 174 | //create .synstr 175 | dyn_item dyn_str_tab = dynamic_section_.find_dyn_by_tag(DT_STRTAB); 176 | dyn_item dyn_str_sz = dynamic_section_.find_dyn_by_tag(DT_STRSZ); 177 | if (dyn_str_tab.is_valid() 178 | && dyn_str_sz.is_valid()){ 179 | elf_section str_section_; 180 | Elf32_Shdr &header_ = str_section_.get_header(); 181 | header_.sh_type = SHT_STRTAB; 182 | header_.sh_addr = dyn_str_tab.get_addr(); 183 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 184 | header_.sh_size = dyn_str_sz.get_value(); 185 | header_.sh_flags = SHF_ALLOC; 186 | header_.sh_name = find_string_idx_in_strtab(".dynstr"); 187 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 188 | 189 | vec_created_section_.push_back(str_section_); 190 | LOG(DBG, ".dynstr section created"); 191 | } 192 | 193 | //create .dynsym 194 | dyn_item dyn_sym = dynamic_section_.find_dyn_by_tag(DT_SYMTAB); 195 | dyn_item dyn_sym_entry_size = dynamic_section_.find_dyn_by_tag(DT_SYMENT); 196 | //dyn_item dyn_sym_sz = dynamic_section_.find_dyn_by_tag(DT_SYMTAB); 197 | if (dyn_sym.is_valid()){ 198 | elf_section sym_section_; 199 | Elf32_Shdr &header_ = sym_section_.get_header(); 200 | header_.sh_type = SHT_SYMTAB; 201 | header_.sh_addr = dyn_sym.get_addr(); 202 | header_.sh_entsize = dyn_sym_entry_size.get_value(); 203 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 204 | header_.sh_size = 0; 205 | header_.sh_flags = SHF_ALLOC; 206 | header_.sh_name = find_string_idx_in_strtab(".dynsym"); 207 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 208 | header_.sh_link = 1; //very important, link means symname found base section, and now 1==.dynstr section index, because i put it in the second pos in the created_section_vec 209 | 210 | vec_created_section_.push_back(sym_section_); 211 | LOG(DBG, ".dynsym section created"); 212 | } 213 | 214 | //create .hash 215 | dyn_item dyn_hash = dynamic_section_.find_dyn_by_tag(DT_HASH); 216 | if (dyn_hash.is_valid()){ 217 | elf_section hash_section_; 218 | Elf32_Shdr &header_ = hash_section_.get_header(); 219 | header_.sh_type = SHT_HASH; 220 | header_.sh_name = find_string_idx_in_strtab(".hash"); 221 | header_.sh_addr = dyn_hash.get_addr(); 222 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 223 | 224 | //calc hash size 225 | int *hash_content_ = (int *)(file_content_.c_str() + header_.sh_offset); 226 | header_.sh_size = (hash_content_[0] + hash_content_[1] + 2) * sizeof(int); 227 | 228 | header_.sh_flags = SHF_ALLOC; 229 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 230 | 231 | vec_created_section_.push_back(hash_section_); 232 | LOG(DBG, ".hash section created"); 233 | } 234 | 235 | //create .rel.dyn 236 | dyn_item dyn_rel_dyn = dynamic_section_.find_dyn_by_tag(DT_REL); 237 | dyn_item dyn_rel_dyn_sz = dynamic_section_.find_dyn_by_tag(DT_RELSZ); 238 | dyn_item dyn_rel_dyn_entry_size = dynamic_section_.find_dyn_by_tag(DT_RELENT); 239 | if (dyn_rel_dyn.is_valid() 240 | && dyn_rel_dyn_sz.is_valid()){ 241 | elf_section rel_dyn_section_; 242 | Elf32_Shdr &header_ = rel_dyn_section_.get_header(); 243 | header_.sh_type = SHT_REL; 244 | header_.sh_addr = dyn_rel_dyn.get_addr(); 245 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 246 | header_.sh_size = dyn_rel_dyn_sz.get_value(); 247 | header_.sh_entsize = dyn_rel_dyn_entry_size.get_value(); 248 | header_.sh_flags = SHF_ALLOC; 249 | header_.sh_name = find_string_idx_in_strtab(".rel.dyn"); 250 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 251 | header_.sh_link = 2; 252 | 253 | vec_created_section_.push_back(rel_dyn_section_); 254 | LOG(DBG, ".rel.dyn section created"); 255 | } 256 | 257 | //create .rel.plt 258 | dyn_item dyn_rel_plt = dynamic_section_.find_dyn_by_tag(DT_JMPREL); 259 | dyn_item dyn_rel_plt_sz = dynamic_section_.find_dyn_by_tag(DT_PLTRELSZ); 260 | //dyn_item dyn_rel_plt_entry_size = dynamic_section_.find_dyn_by_tag(DT_P) //?????fixme 261 | if (dyn_rel_plt.is_valid() 262 | && dyn_rel_plt_sz.is_valid()){ 263 | elf_section rel_plt_section_; 264 | Elf32_Shdr &header_ = rel_plt_section_.get_header(); 265 | header_.sh_type = SHT_REL; 266 | header_.sh_addr = dyn_rel_plt.get_addr(); 267 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 268 | header_.sh_size = dyn_rel_plt_sz.get_value(); 269 | header_.sh_entsize = 8; //fixme, get from .dynamic ?? 270 | header_.sh_flags = SHF_ALLOC; 271 | header_.sh_name = find_string_idx_in_strtab(".rel.plt"); 272 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 273 | header_.sh_link = 2; 274 | 275 | vec_created_section_.push_back(rel_plt_section_); 276 | LOG(DBG, ".rel.plt section created"); 277 | } 278 | 279 | //create .plt 280 | Elf32_Addr plt_section_addr_ = 0; 281 | Elf32_Word plt_section_size = 0; 282 | { 283 | //just treat the data behind .rel.plt as .plt section 284 | elf_section plt_section_; 285 | Elf32_Shdr &header_ = plt_section_.get_header(); 286 | header_.sh_type = SHT_PROGBITS; 287 | header_.sh_addr = dyn_rel_plt.get_addr() + dyn_rel_plt_sz.get_value(); 288 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 289 | header_.sh_size = (20 + 12 * (dyn_rel_plt_sz.get_value()) / sizeof(Elf32_Rel)); //please reference to the plt struct 290 | header_.sh_flags = SHF_EXECINSTR | SHF_ALLOC; 291 | header_.sh_name = find_string_idx_in_strtab(".plt"); 292 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 293 | 294 | vec_created_section_.push_back(plt_section_); 295 | LOG(DBG, ".plt section created"); 296 | 297 | //save for .text 298 | plt_section_addr_ = header_.sh_addr; 299 | plt_section_size = header_.sh_size; 300 | } 301 | 302 | //create .text 303 | { 304 | //just treat the data behind .plt as .text section 305 | elf_section text_section_; 306 | Elf32_Shdr &header_ = text_section_.get_header(); 307 | header_.sh_type = SHT_PROGBITS; 308 | header_.sh_name = find_string_idx_in_strtab(".text"); 309 | header_.sh_flags = SHF_EXECINSTR | SHF_ALLOC; 310 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 311 | header_.sh_addr = plt_section_addr_ + plt_section_size; 312 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 313 | header_.sh_size = file_content_.size() - header_.sh_offset; 314 | 315 | vec_created_section_.push_back(text_section_); 316 | LOG(DBG, ".text section created"); 317 | 318 | } 319 | //create .init_array 320 | dyn_item dyn_init_array = dynamic_section_.find_dyn_by_tag(DT_INIT_ARRAY); 321 | dyn_item dyn_init_array_sz = dynamic_section_.find_dyn_by_tag(DT_INIT_ARRAYSZ); 322 | if (dyn_init_array.is_valid() 323 | && dyn_init_array_sz.is_valid()){ 324 | elf_section init_array_section_; 325 | Elf32_Shdr &header_ = init_array_section_.get_header(); 326 | header_.sh_type = SHT_INIT_ARRAY; 327 | header_.sh_addr = dyn_init_array.get_addr(); 328 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 329 | header_.sh_size = dyn_init_array_sz.get_value(); 330 | header_.sh_flags = SHF_ALLOC | SHF_WRITE; 331 | header_.sh_name = find_string_idx_in_strtab(".init_array"); 332 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 333 | 334 | vec_created_section_.push_back(init_array_section_); 335 | LOG(DBG, ".init_array section created"); 336 | } 337 | 338 | //create .fini_array 339 | dyn_item dyn_fini_array = dynamic_section_.find_dyn_by_tag(DT_FINI_ARRAY); 340 | dyn_item dyn_fini_array_sz = dynamic_section_.find_dyn_by_tag(DT_FINI_ARRAYSZ); 341 | if (dyn_fini_array.is_valid() 342 | && dyn_fini_array_sz.is_valid()){ 343 | elf_section fini_array_section_; 344 | Elf32_Shdr &header_ = fini_array_section_.get_header(); 345 | header_.sh_type = SHT_FINI_ARRAY; 346 | header_.sh_addr = dyn_fini_array.get_addr(); 347 | header_.sh_offset = header_.sh_addr - calc_VA_FA_gap(header_.sh_addr); 348 | header_.sh_size = dyn_fini_array_sz.get_value(); 349 | header_.sh_flags = SHF_ALLOC | SHF_WRITE; 350 | header_.sh_name = find_string_idx_in_strtab(".fini_array"); 351 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 352 | 353 | vec_created_section_.push_back(fini_array_section_); 354 | LOG(DBG, ".fini_array section created"); 355 | } 356 | 357 | //create dynmamic section 358 | { 359 | std::string dyn_segment_string_ = dynamic_section_.get_section_information(); 360 | elf_segment dyn_segment_; 361 | dyn_segment_.from_string(dyn_segment_string_); 362 | 363 | elf_section dyn_section_; 364 | Elf32_Shdr &header_ = dyn_section_.get_header(); 365 | header_.sh_name = find_string_idx_in_strtab(".dynamic"); 366 | header_.sh_addr = dyn_segment_.get_header().p_vaddr; 367 | header_.sh_offset = dyn_segment_.get_header().p_offset; 368 | header_.sh_size = dyn_segment_.get_header().p_filesz; 369 | header_.sh_type = SHT_DYNAMIC; 370 | header_.sh_flags = SHF_WRITE; 371 | header_.sh_addralign = header_.sh_addr % 4 ? 1 : 4; 372 | header_.sh_link = 1; 373 | header_.sh_entsize = sizeof(Elf32_Dyn); 374 | 375 | vec_created_section_.push_back(dyn_section_); 376 | LOG(DBG, ".dynamic section created"); 377 | } 378 | 379 | 380 | //fix symtab size 381 | return fix_sym_tab_size() 382 | && fix_sym_item_section_ref(); 383 | } 384 | 385 | int section_fix::calc_VA_FA_gap(Elf32_Addr section_addr) 386 | { 387 | //0. find which load segment is the section belongs 388 | //1. calc the address gap bettwen virtual address and file offset 389 | //2. any section in this load segment shall have the same address gap as the coreponding load segment 390 | 391 | //0. sort the loaded segments 392 | if (!vec_load_.size()){ 393 | LOG(ERR, "try calc virtual addr file offset gap, but PT_LOAD vector empty"); 394 | return 0; 395 | } 396 | 397 | std::sort(vec_load_.begin(), vec_load_.end(), 398 | [=](elf_segment &item1, elf_segment &item2)->bool{ 399 | return item1.get_header().p_paddr < item2.get_header().p_paddr; 400 | }); 401 | 402 | //1. now find it 403 | for (auto itr : vec_load_){ 404 | if (itr.get_header().p_paddr <= section_addr 405 | && itr.get_header().p_paddr + itr.get_header().p_memsz > section_addr){ 406 | //got it 407 | return (itr.get_header().p_paddr - itr.get_header().p_offset); 408 | } 409 | } 410 | 411 | LOG(ERR, "try calc virtual addr file offset gap, but section not in any PT_LOAD segment"); 412 | return 0; 413 | } 414 | 415 | int section_fix::find_string_idx_in_strtab(std::string str) 416 | { 417 | if (sh_str_.empty()){ 418 | //prepare the section header string 419 | std::string null_seperator("\0", 1); 420 | sh_str_ += null_seperator; //idx = 0 421 | sh_str_ += (".interp" + null_seperator); //idx = 1 422 | sh_str_ += (".note.gnu.build-i" + null_seperator); 423 | sh_str_ += (".dynsym" + null_seperator); 424 | sh_str_ += (".dynstr" + null_seperator); 425 | sh_str_ += (".hash" + null_seperator); 426 | sh_str_ += (".gnu.version" + null_seperator); 427 | sh_str_ += (".gnu.version_d" + null_seperator); 428 | sh_str_ += (".gnu.version_r" + null_seperator); 429 | sh_str_ += (".rel.dyn" + null_seperator); 430 | sh_str_ += (".rel.plt" + null_seperator); 431 | sh_str_ += (".text" + null_seperator); 432 | sh_str_ += (".ARM.extab" + null_seperator); 433 | sh_str_ += (".ARM.exidx" + null_seperator); 434 | sh_str_ += (".rodata" + null_seperator); 435 | sh_str_ += (".fini_array" + null_seperator); 436 | sh_str_ += (".init_array" + null_seperator); 437 | sh_str_ += (".dynamic" + null_seperator); 438 | sh_str_ += (".got" + null_seperator); 439 | sh_str_ += (".data" + null_seperator); 440 | sh_str_ += (".bss" + null_seperator); 441 | sh_str_ += (".comment" + null_seperator); 442 | sh_str_ += (".note.gnu.gold-ve" + null_seperator); 443 | sh_str_ += (".ARM.attributes" + null_seperator); 444 | sh_str_ += (".dynamic" + null_seperator); 445 | sh_str_ += (".shstrtab" + null_seperator); 446 | } 447 | 448 | std::string::size_type idx = sh_str_.find(str); 449 | if (std::string::npos != idx){ 450 | return (int)idx; 451 | } 452 | 453 | LOG(ERR, "try to find string index in section header string table, but can't find it"); 454 | return -1; 455 | } 456 | 457 | bool section_fix::fix_sym_tab_size() 458 | { 459 | //0. find the end of the .symtab with sym "_end" 460 | std::vector::iterator dym_section_itr_ = std::find_if(vec_created_section_.begin(), vec_created_section_.end(), 461 | [=](elf_section &item)->bool{ 462 | return (SHT_SYMTAB == item.get_header().sh_type); 463 | }); 464 | 465 | std::vector::iterator dyn_str_section_itr_ = std::find_if(vec_created_section_.begin(), vec_created_section_.end(), 466 | [=](elf_section &item)->bool{ 467 | return (SHT_STRTAB == item.get_header().sh_type); 468 | }); 469 | 470 | if (dym_section_itr_ != vec_created_section_.end() 471 | && dyn_str_section_itr_ != vec_created_section_.end()){ 472 | //search symtab until to the symbol _end 473 | 474 | std::string dyn_string(file_content_.c_str() + dyn_str_section_itr_->get_header().sh_offset, dyn_str_section_itr_->get_header().sh_size); 475 | 476 | int search_cnt = 0; //max search count = 10000 477 | Elf32_Sym *sym_start_ = (Elf32_Sym *)(file_content_.c_str() + dym_section_itr_->get_header().sh_offset); 478 | sym_start_++; 479 | do 480 | { 481 | try 482 | { 483 | Elf32_Word sym_name_off_ = sym_start_->st_name; 484 | //if (!sym_name_off_){ 485 | // //found the end 486 | // break; 487 | //} 488 | 489 | if (sym_name_off_ < dyn_string.size()){ 490 | std::string syn_name = dyn_string.c_str() + sym_name_off_; 491 | if (syn_name.empty()){ 492 | //found the end 493 | break; 494 | } 495 | } 496 | 497 | } 498 | catch (...) 499 | { 500 | LOG(ERR, "try search sym table end, but exception occur, give up"); 501 | } 502 | 503 | search_cnt++; 504 | if (search_cnt > 10000){ 505 | LOG(ERR, "try search sym table end, but now try count > 10000, give up"); 506 | break; 507 | } 508 | } while (sym_start_++); 509 | 510 | if (search_cnt > 10000){ 511 | return false; 512 | } 513 | 514 | dym_section_itr_->get_header().sh_size = (search_cnt + 1) * sizeof(Elf32_Sym); 515 | 516 | LOG(DBG, "found %d symbols", search_cnt); 517 | return true; 518 | } 519 | 520 | return false; 521 | } 522 | 523 | bool section_fix::fix_sym_item_section_ref() 524 | { 525 | //0. find the end of the .symtab with sym "_end" 526 | std::vector::iterator dym_section_itr_ = std::find_if(vec_created_section_.begin(), vec_created_section_.end(), 527 | [=](elf_section &item)->bool{ 528 | return (SHT_SYMTAB == item.get_header().sh_type); 529 | }); 530 | 531 | std::vector::iterator dyn_str_section_itr_ = std::find_if(vec_created_section_.begin(), vec_created_section_.end(), 532 | [=](elf_section &item)->bool{ 533 | return (SHT_STRTAB == item.get_header().sh_type); 534 | }); 535 | 536 | if (dym_section_itr_ != vec_created_section_.end() 537 | && dyn_str_section_itr_ != vec_created_section_.end()){ 538 | //search symtab until to the symbol _end 539 | 540 | std::string dyn_string(file_content_.c_str() + dyn_str_section_itr_->get_header().sh_offset, dyn_str_section_itr_->get_header().sh_size); 541 | 542 | int search_cnt = 0; //max search count = 10000 543 | Elf32_Sym *sym_start_ = (Elf32_Sym *)(file_content_.c_str() + dym_section_itr_->get_header().sh_offset); 544 | do 545 | { 546 | try 547 | { 548 | Elf32_Word sym_name_off_ = sym_start_->st_name; 549 | if (sym_name_off_ < dyn_string.size()){ 550 | std::string syn_name = dyn_string.c_str() + sym_name_off_; 551 | sym_start_->st_shndx = calc_addr_section_idx(sym_start_->st_value); 552 | struct bit_info{ 553 | unsigned char sym_info_type : 4; 554 | unsigned char sym_info_bind : 4; 555 | }; 556 | bit_info *sym_info_ = (bit_info *)&sym_start_->st_info; 557 | if (sym_info_->sym_info_type > 4){ // max = STI_FILE = 4 558 | sym_info_->sym_info_type = 2; // STI_FUNC = 2 559 | } 560 | if (sym_info_->sym_info_bind > 2){ // max = STB_WEAK 561 | sym_info_->sym_info_bind = 1; //STB_GLOBAL = 2 562 | } 563 | 564 | if (syn_name.find("_end") != std::string::npos){ 565 | //found the end 566 | break; 567 | } 568 | } 569 | 570 | } 571 | catch (...) 572 | { 573 | LOG(ERR, "try search sym table end, but exception occur, give up"); 574 | } 575 | 576 | search_cnt++; 577 | if (search_cnt > 10000){ 578 | LOG(ERR, "try search sym table end, but now try count > 10000, give up"); 579 | break; 580 | } 581 | } while (sym_start_++); 582 | return true; 583 | } 584 | 585 | return false; 586 | } 587 | 588 | int section_fix::calc_addr_section_idx(Elf32_Off addr) 589 | { 590 | return vec_created_section_.size() + 1; 591 | 592 | std::sort(vec_created_section_.begin(), vec_created_section_.end(), 593 | [=](elf_section &item1, elf_section &item2)->bool{ 594 | return item1.get_header().sh_addr < item2.get_header().sh_addr; 595 | }); 596 | 597 | for (int i = 0; i < vec_created_section_.size(); i ++){ 598 | elf_section section_ = vec_created_section_[i]; 599 | if (addr >= section_.get_header().sh_addr 600 | && addr < section_.get_header().sh_addr + section_.get_header().sh_size){ 601 | return i; 602 | } 603 | } 604 | return 0; 605 | } 606 | 607 | /******************************************************************************/ -------------------------------------------------------------------------------- /fix/section_fix.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file section_fix.h 2017\5\12 19:46:24 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef SECTION_FIX_CF78F56C_58E1_4F6D_B103_CA85BDF6C2B8_H__ 8 | #define SECTION_FIX_CF78F56C_58E1_4F6D_B103_CA85BDF6C2B8_H__ 9 | 10 | /******************************************************************************/ 11 | #include "Core/elf_header.h" 12 | #include "Core/elf_segment.h" 13 | #include "Core/dyn_section.h" 14 | #include "Core/elf_section.h" 15 | 16 | #include 17 | #include 18 | /** 19 | * The class section_fix 20 | * 21 | */ 22 | class section_fix 23 | { 24 | public: 25 | /** @name Constructors and Destructor*/ 26 | 27 | //@{ 28 | /** 29 | * Constructor 30 | */ 31 | section_fix(); 32 | /** 33 | * Destructor 34 | */ 35 | ~section_fix(); 36 | //@} 37 | 38 | public: 39 | 40 | /** 41 | * @fn bool section_fix::fix(std::string file); 42 | * 43 | * @brief Fixes the given elf file corrupt sections 44 | * 45 | * @param src_file - The elf file. 46 | * 47 | * @return True if it succeeds, false if it fails. 48 | */ 49 | bool fix(std::string src_file); 50 | 51 | /** 52 | * @fn bool section_fix::save_as(std::string file); 53 | * 54 | * @brief Saves the fix result to another file 55 | * 56 | * @param dst_file The file. 57 | * 58 | * @return True if it succeeds, false if it fails. 59 | */ 60 | bool save_as(std::string dst_file); 61 | 62 | private: 63 | 64 | /** 65 | * @fn bool section_fix::pre_load(); 66 | * 67 | * @brief pre load dynamic sections and pt_load sections 68 | * 69 | * @return True if it succeeds, false if it fails. 70 | */ 71 | bool pre_load(); 72 | 73 | /** 74 | * @fn bool section_fix::first_create_sections(); 75 | * 76 | * @brief just create sections with information from .dynamic section, then we fix it 77 | * 78 | * @return True if it succeeds, false if it fails. 79 | */ 80 | bool first_create_sections(); 81 | 82 | /** 83 | * @fn bool section_fix::fix_sym_tab_size(); 84 | * 85 | * @brief fix symtab size by search the symtab content until to the _end symbol 86 | * 87 | * @return True if it succeeds, false if it fails. 88 | */ 89 | bool fix_sym_tab_size(); 90 | 91 | /** 92 | * @fn bool section_fix::fix_sym_item_section_ref(); 93 | * 94 | * @brief adjust sym item section ref 95 | * 96 | * @return True if it succeeds, false if it fails. 97 | */ 98 | bool fix_sym_item_section_ref(); 99 | 100 | /** 101 | * @fn int section_fix::calc_offset_section_idx(Elf32_Off offset); 102 | * 103 | * @brief Calculates which section is the offset should be. 104 | * 105 | * @param offset The offset. 106 | * 107 | * @return The calculated offset section index. 108 | */ 109 | int calc_addr_section_idx(Elf32_Off offset); 110 | 111 | /** 112 | * @fn int section_fix::calc_VA_FA_gap(Elf32_Addr section_addr); 113 | * 114 | * @brief Calculates the address gap betwwen virtual address and file offset 115 | * 116 | * @param section_addr The section address. 117 | * 118 | * @return The calculated variable arguments fa gap. 119 | */ 120 | int calc_VA_FA_gap(Elf32_Addr section_addr); 121 | 122 | /** 123 | * @fn int section_fix::find_string_idx_in_strtab(std::string str); 124 | * 125 | * @brief Searches for the first string index in strtab. 126 | * 127 | * @param str The string. 128 | * 129 | * @return The found string index in strtab. 130 | */ 131 | int find_string_idx_in_strtab(std::string str); 132 | private: 133 | std::string file_content_; //whole file content 134 | 135 | private: 136 | //find pt_load, pt_dynamic 137 | std::vector vec_load_; //save pt_load segements 138 | dyn_section dynamic_section_; //save .dynamic section 139 | 140 | //created sections 141 | std::vector vec_created_section_; 142 | 143 | //string used to create .shstrtab 144 | std::string sh_str_; 145 | }; 146 | /******************************************************************************/ 147 | #endif// SECTION_FIX_CF78F56C_58E1_4F6D_B103_CA85BDF6C2B8_H__ 148 | -------------------------------------------------------------------------------- /jni.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * JNI specification, as defined by Sun: 19 | * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html 20 | * 21 | * Everything here is expected to be VM-neutral. 22 | */ 23 | 24 | #ifndef JNI_H_ 25 | #define JNI_H_ 26 | 27 | //#include 28 | //#include 29 | 30 | /* 31 | * Primitive types that match up with Java equivalents. 32 | */ 33 | #ifdef HAVE_INTTYPES_H 34 | # include /* C99 */ 35 | typedef uint8_t jboolean; /* unsigned 8 bits */ 36 | typedef int8_t jbyte; /* signed 8 bits */ 37 | typedef uint16_t jchar; /* unsigned 16 bits */ 38 | typedef int16_t jshort; /* signed 16 bits */ 39 | typedef int32_t jint; /* signed 32 bits */ 40 | typedef int64_t jlong; /* signed 64 bits */ 41 | typedef float jfloat; /* 32-bit IEEE 754 */ 42 | typedef double jdouble; /* 64-bit IEEE 754 */ 43 | #else 44 | typedef unsigned char jboolean; /* unsigned 8 bits */ 45 | typedef signed char jbyte; /* signed 8 bits */ 46 | typedef unsigned short jchar; /* unsigned 16 bits */ 47 | typedef short jshort; /* signed 16 bits */ 48 | typedef int jint; /* signed 32 bits */ 49 | typedef long long jlong; /* signed 64 bits */ 50 | typedef float jfloat; /* 32-bit IEEE 754 */ 51 | typedef double jdouble; /* 64-bit IEEE 754 */ 52 | #endif 53 | 54 | /* "cardinal indices and sizes" */ 55 | typedef jint jsize; 56 | 57 | #ifdef __cplusplus 58 | /* 59 | * Reference types, in C++ 60 | */ 61 | class _jobject {}; 62 | class _jclass : public _jobject {}; 63 | class _jstring : public _jobject {}; 64 | class _jarray : public _jobject {}; 65 | class _jobjectArray : public _jarray {}; 66 | class _jbooleanArray : public _jarray {}; 67 | class _jbyteArray : public _jarray {}; 68 | class _jcharArray : public _jarray {}; 69 | class _jshortArray : public _jarray {}; 70 | class _jintArray : public _jarray {}; 71 | class _jlongArray : public _jarray {}; 72 | class _jfloatArray : public _jarray {}; 73 | class _jdoubleArray : public _jarray {}; 74 | class _jthrowable : public _jobject {}; 75 | 76 | typedef _jobject* jobject; 77 | typedef _jclass* jclass; 78 | typedef _jstring* jstring; 79 | typedef _jarray* jarray; 80 | typedef _jobjectArray* jobjectArray; 81 | typedef _jbooleanArray* jbooleanArray; 82 | typedef _jbyteArray* jbyteArray; 83 | typedef _jcharArray* jcharArray; 84 | typedef _jshortArray* jshortArray; 85 | typedef _jintArray* jintArray; 86 | typedef _jlongArray* jlongArray; 87 | typedef _jfloatArray* jfloatArray; 88 | typedef _jdoubleArray* jdoubleArray; 89 | typedef _jthrowable* jthrowable; 90 | typedef _jobject* jweak; 91 | 92 | 93 | #else /* not __cplusplus */ 94 | 95 | /* 96 | * Reference types, in C. 97 | */ 98 | typedef void* jobject; 99 | typedef jobject jclass; 100 | typedef jobject jstring; 101 | typedef jobject jarray; 102 | typedef jarray jobjectArray; 103 | typedef jarray jbooleanArray; 104 | typedef jarray jbyteArray; 105 | typedef jarray jcharArray; 106 | typedef jarray jshortArray; 107 | typedef jarray jintArray; 108 | typedef jarray jlongArray; 109 | typedef jarray jfloatArray; 110 | typedef jarray jdoubleArray; 111 | typedef jobject jthrowable; 112 | typedef jobject jweak; 113 | 114 | #endif /* not __cplusplus */ 115 | 116 | struct _jfieldID; /* opaque structure */ 117 | typedef struct _jfieldID* jfieldID; /* field IDs */ 118 | 119 | struct _jmethodID; /* opaque structure */ 120 | typedef struct _jmethodID* jmethodID; /* method IDs */ 121 | 122 | struct JNIInvokeInterface; 123 | 124 | typedef union jvalue { 125 | jboolean z; 126 | jbyte b; 127 | jchar c; 128 | jshort s; 129 | jint i; 130 | jlong j; 131 | jfloat f; 132 | jdouble d; 133 | jobject l; 134 | } jvalue; 135 | 136 | typedef enum jobjectRefType { 137 | JNIInvalidRefType = 0, 138 | JNILocalRefType = 1, 139 | JNIGlobalRefType = 2, 140 | JNIWeakGlobalRefType = 3 141 | } jobjectRefType; 142 | 143 | typedef struct { 144 | const char* name; 145 | const char* signature; 146 | void* fnPtr; 147 | } JNINativeMethod; 148 | 149 | struct _JNIEnv; 150 | struct _JavaVM; 151 | typedef const struct JNINativeInterface* C_JNIEnv; 152 | 153 | #if defined(__cplusplus) 154 | typedef _JNIEnv JNIEnv; 155 | typedef _JavaVM JavaVM; 156 | #else 157 | typedef const struct JNINativeInterface* JNIEnv; 158 | typedef const struct JNIInvokeInterface* JavaVM; 159 | #endif 160 | 161 | /* 162 | * Table of interface function pointers. 163 | */ 164 | struct JNINativeInterface { 165 | void* reserved0; 166 | void* reserved1; 167 | void* reserved2; 168 | void* reserved3; 169 | 170 | jint (*GetVersion)(JNIEnv *); 171 | 172 | jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, 173 | jsize); 174 | jclass (*FindClass)(JNIEnv*, const char*); 175 | 176 | jmethodID (*FromReflectedMethod)(JNIEnv*, jobject); 177 | jfieldID (*FromReflectedField)(JNIEnv*, jobject); 178 | /* spec doesn't show jboolean parameter */ 179 | jobject (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean); 180 | 181 | jclass (*GetSuperclass)(JNIEnv*, jclass); 182 | jboolean (*IsAssignableFrom)(JNIEnv*, jclass, jclass); 183 | 184 | /* spec doesn't show jboolean parameter */ 185 | jobject (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean); 186 | 187 | jint (*Throw)(JNIEnv*, jthrowable); 188 | jint (*ThrowNew)(JNIEnv *, jclass, const char *); 189 | jthrowable (*ExceptionOccurred)(JNIEnv*); 190 | void (*ExceptionDescribe)(JNIEnv*); 191 | void (*ExceptionClear)(JNIEnv*); 192 | void (*FatalError)(JNIEnv*, const char*); 193 | 194 | jint (*PushLocalFrame)(JNIEnv*, jint); 195 | jobject (*PopLocalFrame)(JNIEnv*, jobject); 196 | 197 | jobject (*NewGlobalRef)(JNIEnv*, jobject); 198 | void (*DeleteGlobalRef)(JNIEnv*, jobject); 199 | void (*DeleteLocalRef)(JNIEnv*, jobject); 200 | jboolean (*IsSameObject)(JNIEnv*, jobject, jobject); 201 | 202 | jobject (*NewLocalRef)(JNIEnv*, jobject); 203 | jint (*EnsureLocalCapacity)(JNIEnv*, jint); 204 | 205 | jobject (*AllocObject)(JNIEnv*, jclass); 206 | jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...); 207 | jobject (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list); 208 | jobject (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*); 209 | 210 | jclass (*GetObjectClass)(JNIEnv*, jobject); 211 | jboolean (*IsInstanceOf)(JNIEnv*, jobject, jclass); 212 | jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); 213 | 214 | jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...); 215 | jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list); 216 | jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 217 | jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...); 218 | jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list); 219 | jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 220 | jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...); 221 | jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list); 222 | jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 223 | jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...); 224 | jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list); 225 | jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 226 | jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...); 227 | jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list); 228 | jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 229 | jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); 230 | jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list); 231 | jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 232 | jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...); 233 | jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list); 234 | jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 235 | jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...); 236 | jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list); 237 | jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 238 | jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...); 239 | jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list); 240 | jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 241 | void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); 242 | void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list); 243 | void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); 244 | 245 | jobject (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass, 246 | jmethodID, ...); 247 | jobject (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass, 248 | jmethodID, va_list); 249 | jobject (*CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass, 250 | jmethodID, jvalue*); 251 | jboolean (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass, 252 | jmethodID, ...); 253 | jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass, 254 | jmethodID, va_list); 255 | jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass, 256 | jmethodID, jvalue*); 257 | jbyte (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass, 258 | jmethodID, ...); 259 | jbyte (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass, 260 | jmethodID, va_list); 261 | jbyte (*CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass, 262 | jmethodID, jvalue*); 263 | jchar (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass, 264 | jmethodID, ...); 265 | jchar (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass, 266 | jmethodID, va_list); 267 | jchar (*CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass, 268 | jmethodID, jvalue*); 269 | jshort (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass, 270 | jmethodID, ...); 271 | jshort (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass, 272 | jmethodID, va_list); 273 | jshort (*CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass, 274 | jmethodID, jvalue*); 275 | jint (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass, 276 | jmethodID, ...); 277 | jint (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass, 278 | jmethodID, va_list); 279 | jint (*CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass, 280 | jmethodID, jvalue*); 281 | jlong (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass, 282 | jmethodID, ...); 283 | jlong (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass, 284 | jmethodID, va_list); 285 | jlong (*CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass, 286 | jmethodID, jvalue*); 287 | jfloat (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass, 288 | jmethodID, ...); 289 | jfloat (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass, 290 | jmethodID, va_list); 291 | jfloat (*CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass, 292 | jmethodID, jvalue*); 293 | jdouble (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass, 294 | jmethodID, ...); 295 | jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass, 296 | jmethodID, va_list); 297 | jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass, 298 | jmethodID, jvalue*); 299 | void (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass, 300 | jmethodID, ...); 301 | void (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass, 302 | jmethodID, va_list); 303 | void (*CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass, 304 | jmethodID, jvalue*); 305 | 306 | jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*); 307 | 308 | jobject (*GetObjectField)(JNIEnv*, jobject, jfieldID); 309 | jboolean (*GetBooleanField)(JNIEnv*, jobject, jfieldID); 310 | jbyte (*GetByteField)(JNIEnv*, jobject, jfieldID); 311 | jchar (*GetCharField)(JNIEnv*, jobject, jfieldID); 312 | jshort (*GetShortField)(JNIEnv*, jobject, jfieldID); 313 | jint (*GetIntField)(JNIEnv*, jobject, jfieldID); 314 | jlong (*GetLongField)(JNIEnv*, jobject, jfieldID); 315 | jfloat (*GetFloatField)(JNIEnv*, jobject, jfieldID); 316 | jdouble (*GetDoubleField)(JNIEnv*, jobject, jfieldID); 317 | 318 | void (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject); 319 | void (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean); 320 | void (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte); 321 | void (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar); 322 | void (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort); 323 | void (*SetIntField)(JNIEnv*, jobject, jfieldID, jint); 324 | void (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong); 325 | void (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat); 326 | void (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble); 327 | 328 | jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*); 329 | 330 | jobject (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...); 331 | jobject (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list); 332 | jobject (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 333 | jboolean (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...); 334 | jboolean (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID, 335 | va_list); 336 | jboolean (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID, 337 | jvalue*); 338 | jbyte (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...); 339 | jbyte (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list); 340 | jbyte (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 341 | jchar (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...); 342 | jchar (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list); 343 | jchar (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 344 | jshort (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...); 345 | jshort (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list); 346 | jshort (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 347 | jint (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...); 348 | jint (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list); 349 | jint (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 350 | jlong (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...); 351 | jlong (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list); 352 | jlong (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 353 | jfloat (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...); 354 | jfloat (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list); 355 | jfloat (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 356 | jdouble (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...); 357 | jdouble (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list); 358 | jdouble (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 359 | void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); 360 | void (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list); 361 | void (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); 362 | 363 | jfieldID (*GetStaticFieldID)(JNIEnv*, jclass, const char*, 364 | const char*); 365 | 366 | jobject (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID); 367 | jboolean (*GetStaticBooleanField)(JNIEnv*, jclass, jfieldID); 368 | jbyte (*GetStaticByteField)(JNIEnv*, jclass, jfieldID); 369 | jchar (*GetStaticCharField)(JNIEnv*, jclass, jfieldID); 370 | jshort (*GetStaticShortField)(JNIEnv*, jclass, jfieldID); 371 | jint (*GetStaticIntField)(JNIEnv*, jclass, jfieldID); 372 | jlong (*GetStaticLongField)(JNIEnv*, jclass, jfieldID); 373 | jfloat (*GetStaticFloatField)(JNIEnv*, jclass, jfieldID); 374 | jdouble (*GetStaticDoubleField)(JNIEnv*, jclass, jfieldID); 375 | 376 | void (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject); 377 | void (*SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean); 378 | void (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte); 379 | void (*SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar); 380 | void (*SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort); 381 | void (*SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint); 382 | void (*SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong); 383 | void (*SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat); 384 | void (*SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble); 385 | 386 | jstring (*NewString)(JNIEnv*, const jchar*, jsize); 387 | jsize (*GetStringLength)(JNIEnv*, jstring); 388 | const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); 389 | void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); 390 | jstring (*NewStringUTF)(JNIEnv*, const char*); 391 | jsize (*GetStringUTFLength)(JNIEnv*, jstring); 392 | /* JNI spec says this returns const jbyte*, but that's inconsistent */ 393 | const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); 394 | void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); 395 | jsize (*GetArrayLength)(JNIEnv*, jarray); 396 | jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject); 397 | jobject (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize); 398 | void (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject); 399 | 400 | jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); 401 | jbyteArray (*NewByteArray)(JNIEnv*, jsize); 402 | jcharArray (*NewCharArray)(JNIEnv*, jsize); 403 | jshortArray (*NewShortArray)(JNIEnv*, jsize); 404 | jintArray (*NewIntArray)(JNIEnv*, jsize); 405 | jlongArray (*NewLongArray)(JNIEnv*, jsize); 406 | jfloatArray (*NewFloatArray)(JNIEnv*, jsize); 407 | jdoubleArray (*NewDoubleArray)(JNIEnv*, jsize); 408 | 409 | jboolean* (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); 410 | jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); 411 | jchar* (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); 412 | jshort* (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); 413 | jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); 414 | jlong* (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); 415 | jfloat* (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); 416 | jdouble* (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*); 417 | 418 | void (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray, 419 | jboolean*, jint); 420 | void (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray, 421 | jbyte*, jint); 422 | void (*ReleaseCharArrayElements)(JNIEnv*, jcharArray, 423 | jchar*, jint); 424 | void (*ReleaseShortArrayElements)(JNIEnv*, jshortArray, 425 | jshort*, jint); 426 | void (*ReleaseIntArrayElements)(JNIEnv*, jintArray, 427 | jint*, jint); 428 | void (*ReleaseLongArrayElements)(JNIEnv*, jlongArray, 429 | jlong*, jint); 430 | void (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray, 431 | jfloat*, jint); 432 | void (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray, 433 | jdouble*, jint); 434 | 435 | void (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray, 436 | jsize, jsize, jboolean*); 437 | void (*GetByteArrayRegion)(JNIEnv*, jbyteArray, 438 | jsize, jsize, jbyte*); 439 | void (*GetCharArrayRegion)(JNIEnv*, jcharArray, 440 | jsize, jsize, jchar*); 441 | void (*GetShortArrayRegion)(JNIEnv*, jshortArray, 442 | jsize, jsize, jshort*); 443 | void (*GetIntArrayRegion)(JNIEnv*, jintArray, 444 | jsize, jsize, jint*); 445 | void (*GetLongArrayRegion)(JNIEnv*, jlongArray, 446 | jsize, jsize, jlong*); 447 | void (*GetFloatArrayRegion)(JNIEnv*, jfloatArray, 448 | jsize, jsize, jfloat*); 449 | void (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray, 450 | jsize, jsize, jdouble*); 451 | 452 | /* spec shows these without const; some jni.h do, some don't */ 453 | void (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray, 454 | jsize, jsize, const jboolean*); 455 | void (*SetByteArrayRegion)(JNIEnv*, jbyteArray, 456 | jsize, jsize, const jbyte*); 457 | void (*SetCharArrayRegion)(JNIEnv*, jcharArray, 458 | jsize, jsize, const jchar*); 459 | void (*SetShortArrayRegion)(JNIEnv*, jshortArray, 460 | jsize, jsize, const jshort*); 461 | void (*SetIntArrayRegion)(JNIEnv*, jintArray, 462 | jsize, jsize, const jint*); 463 | void (*SetLongArrayRegion)(JNIEnv*, jlongArray, 464 | jsize, jsize, const jlong*); 465 | void (*SetFloatArrayRegion)(JNIEnv*, jfloatArray, 466 | jsize, jsize, const jfloat*); 467 | void (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray, 468 | jsize, jsize, const jdouble*); 469 | 470 | jint (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*, 471 | jint); 472 | jint (*UnregisterNatives)(JNIEnv*, jclass); 473 | jint (*MonitorEnter)(JNIEnv*, jobject); 474 | jint (*MonitorExit)(JNIEnv*, jobject); 475 | jint (*GetJavaVM)(JNIEnv*, JavaVM**); 476 | 477 | void (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*); 478 | void (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*); 479 | 480 | void* (*GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*); 481 | void (*ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint); 482 | 483 | const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*); 484 | void (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*); 485 | 486 | jweak (*NewWeakGlobalRef)(JNIEnv*, jobject); 487 | void (*DeleteWeakGlobalRef)(JNIEnv*, jweak); 488 | 489 | jboolean (*ExceptionCheck)(JNIEnv*); 490 | 491 | jobject (*NewDirectByteBuffer)(JNIEnv*, void*, jlong); 492 | void* (*GetDirectBufferAddress)(JNIEnv*, jobject); 493 | jlong (*GetDirectBufferCapacity)(JNIEnv*, jobject); 494 | 495 | /* added in JNI 1.6 */ 496 | jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject); 497 | }; 498 | 499 | /* 500 | * C++ object wrapper. 501 | * 502 | * This is usually overlaid on a C struct whose first element is a 503 | * JNINativeInterface*. We rely somewhat on compiler behavior. 504 | */ 505 | struct _JNIEnv { 506 | /* do not rename this; it does not seem to be entirely opaque */ 507 | const struct JNINativeInterface* functions; 508 | 509 | #if defined(__cplusplus) 510 | 511 | jint GetVersion() 512 | { return functions->GetVersion(this); } 513 | 514 | jclass DefineClass(const char *name, jobject loader, const jbyte* buf, 515 | jsize bufLen) 516 | { return functions->DefineClass(this, name, loader, buf, bufLen); } 517 | 518 | jclass FindClass(const char* name) 519 | { return functions->FindClass(this, name); } 520 | 521 | jmethodID FromReflectedMethod(jobject method) 522 | { return functions->FromReflectedMethod(this, method); } 523 | 524 | jfieldID FromReflectedField(jobject field) 525 | { return functions->FromReflectedField(this, field); } 526 | 527 | jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) 528 | { return functions->ToReflectedMethod(this, cls, methodID, isStatic); } 529 | 530 | jclass GetSuperclass(jclass clazz) 531 | { return functions->GetSuperclass(this, clazz); } 532 | 533 | jboolean IsAssignableFrom(jclass clazz1, jclass clazz2) 534 | { return functions->IsAssignableFrom(this, clazz1, clazz2); } 535 | 536 | jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) 537 | { return functions->ToReflectedField(this, cls, fieldID, isStatic); } 538 | 539 | jint Throw(jthrowable obj) 540 | { return functions->Throw(this, obj); } 541 | 542 | jint ThrowNew(jclass clazz, const char* message) 543 | { return functions->ThrowNew(this, clazz, message); } 544 | 545 | jthrowable ExceptionOccurred() 546 | { return functions->ExceptionOccurred(this); } 547 | 548 | void ExceptionDescribe() 549 | { functions->ExceptionDescribe(this); } 550 | 551 | void ExceptionClear() 552 | { functions->ExceptionClear(this); } 553 | 554 | void FatalError(const char* msg) 555 | { functions->FatalError(this, msg); } 556 | 557 | jint PushLocalFrame(jint capacity) 558 | { return functions->PushLocalFrame(this, capacity); } 559 | 560 | jobject PopLocalFrame(jobject result) 561 | { return functions->PopLocalFrame(this, result); } 562 | 563 | jobject NewGlobalRef(jobject obj) 564 | { return functions->NewGlobalRef(this, obj); } 565 | 566 | void DeleteGlobalRef(jobject globalRef) 567 | { functions->DeleteGlobalRef(this, globalRef); } 568 | 569 | void DeleteLocalRef(jobject localRef) 570 | { functions->DeleteLocalRef(this, localRef); } 571 | 572 | jboolean IsSameObject(jobject ref1, jobject ref2) 573 | { return functions->IsSameObject(this, ref1, ref2); } 574 | 575 | jobject NewLocalRef(jobject ref) 576 | { return functions->NewLocalRef(this, ref); } 577 | 578 | jint EnsureLocalCapacity(jint capacity) 579 | { return functions->EnsureLocalCapacity(this, capacity); } 580 | 581 | jobject AllocObject(jclass clazz) 582 | { return functions->AllocObject(this, clazz); } 583 | 584 | jobject NewObject(jclass clazz, jmethodID methodID, ...) 585 | { 586 | va_list args; 587 | va_start(args, methodID); 588 | jobject result = functions->NewObjectV(this, clazz, methodID, args); 589 | va_end(args); 590 | return result; 591 | } 592 | 593 | jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args) 594 | { return functions->NewObjectV(this, clazz, methodID, args); } 595 | 596 | jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue* args) 597 | { return functions->NewObjectA(this, clazz, methodID, args); } 598 | 599 | jclass GetObjectClass(jobject obj) 600 | { return functions->GetObjectClass(this, obj); } 601 | 602 | jboolean IsInstanceOf(jobject obj, jclass clazz) 603 | { return functions->IsInstanceOf(this, obj, clazz); } 604 | 605 | jmethodID GetMethodID(jclass clazz, const char* name, const char* sig) 606 | { return functions->GetMethodID(this, clazz, name, sig); } 607 | 608 | #define CALL_TYPE_METHOD(_jtype, _jname) \ 609 | \ 610 | _jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...) \ 611 | { \ 612 | _jtype result; \ 613 | va_list args; \ 614 | va_start(args, methodID); \ 615 | result = functions->Call##_jname##MethodV(this, obj, methodID, \ 616 | args); \ 617 | va_end(args); \ 618 | return result; \ 619 | } 620 | #define CALL_TYPE_METHODV(_jtype, _jname) \ 621 | \ 622 | _jtype Call##_jname##MethodV(jobject obj, jmethodID methodID, \ 623 | va_list args) \ 624 | { return functions->Call##_jname##MethodV(this, obj, methodID, args); } 625 | #define CALL_TYPE_METHODA(_jtype, _jname) \ 626 | \ 627 | _jtype Call##_jname##MethodA(jobject obj, jmethodID methodID, \ 628 | jvalue* args) \ 629 | { return functions->Call##_jname##MethodA(this, obj, methodID, args); } 630 | 631 | #define CALL_TYPE(_jtype, _jname) \ 632 | CALL_TYPE_METHOD(_jtype, _jname) \ 633 | CALL_TYPE_METHODV(_jtype, _jname) \ 634 | CALL_TYPE_METHODA(_jtype, _jname) 635 | 636 | CALL_TYPE(jobject, Object) 637 | CALL_TYPE(jboolean, Boolean) 638 | CALL_TYPE(jbyte, Byte) 639 | CALL_TYPE(jchar, Char) 640 | CALL_TYPE(jshort, Short) 641 | CALL_TYPE(jint, Int) 642 | CALL_TYPE(jlong, Long) 643 | CALL_TYPE(jfloat, Float) 644 | CALL_TYPE(jdouble, Double) 645 | 646 | void CallVoidMethod(jobject obj, jmethodID methodID, ...) 647 | { 648 | va_list args; 649 | va_start(args, methodID); 650 | functions->CallVoidMethodV(this, obj, methodID, args); 651 | va_end(args); 652 | } 653 | void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args) 654 | { functions->CallVoidMethodV(this, obj, methodID, args); } 655 | void CallVoidMethodA(jobject obj, jmethodID methodID, jvalue* args) 656 | { functions->CallVoidMethodA(this, obj, methodID, args); } 657 | 658 | #define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \ 659 | \ 660 | _jtype CallNonvirtual##_jname##Method(jobject obj, jclass clazz, \ 661 | jmethodID methodID, ...) \ 662 | { \ 663 | _jtype result; \ 664 | va_list args; \ 665 | va_start(args, methodID); \ 666 | result = functions->CallNonvirtual##_jname##MethodV(this, obj, \ 667 | clazz, methodID, args); \ 668 | va_end(args); \ 669 | return result; \ 670 | } 671 | #define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \ 672 | \ 673 | _jtype CallNonvirtual##_jname##MethodV(jobject obj, jclass clazz, \ 674 | jmethodID methodID, va_list args) \ 675 | { return functions->CallNonvirtual##_jname##MethodV(this, obj, clazz, \ 676 | methodID, args); } 677 | #define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname) \ 678 | \ 679 | _jtype CallNonvirtual##_jname##MethodA(jobject obj, jclass clazz, \ 680 | jmethodID methodID, jvalue* args) \ 681 | { return functions->CallNonvirtual##_jname##MethodA(this, obj, clazz, \ 682 | methodID, args); } 683 | 684 | #define CALL_NONVIRT_TYPE(_jtype, _jname) \ 685 | CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \ 686 | CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \ 687 | CALL_NONVIRT_TYPE_METHODA(_jtype, _jname) 688 | 689 | CALL_NONVIRT_TYPE(jobject, Object) 690 | CALL_NONVIRT_TYPE(jboolean, Boolean) 691 | CALL_NONVIRT_TYPE(jbyte, Byte) 692 | CALL_NONVIRT_TYPE(jchar, Char) 693 | CALL_NONVIRT_TYPE(jshort, Short) 694 | CALL_NONVIRT_TYPE(jint, Int) 695 | CALL_NONVIRT_TYPE(jlong, Long) 696 | CALL_NONVIRT_TYPE(jfloat, Float) 697 | CALL_NONVIRT_TYPE(jdouble, Double) 698 | 699 | void CallNonvirtualVoidMethod(jobject obj, jclass clazz, 700 | jmethodID methodID, ...) 701 | { 702 | va_list args; 703 | va_start(args, methodID); 704 | functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); 705 | va_end(args); 706 | } 707 | void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, 708 | jmethodID methodID, va_list args) 709 | { functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); } 710 | void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, 711 | jmethodID methodID, jvalue* args) 712 | { functions->CallNonvirtualVoidMethodA(this, obj, clazz, methodID, args); } 713 | 714 | jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) 715 | { return functions->GetFieldID(this, clazz, name, sig); } 716 | 717 | jobject GetObjectField(jobject obj, jfieldID fieldID) 718 | { return functions->GetObjectField(this, obj, fieldID); } 719 | jboolean GetBooleanField(jobject obj, jfieldID fieldID) 720 | { return functions->GetBooleanField(this, obj, fieldID); } 721 | jbyte GetByteField(jobject obj, jfieldID fieldID) 722 | { return functions->GetByteField(this, obj, fieldID); } 723 | jchar GetCharField(jobject obj, jfieldID fieldID) 724 | { return functions->GetCharField(this, obj, fieldID); } 725 | jshort GetShortField(jobject obj, jfieldID fieldID) 726 | { return functions->GetShortField(this, obj, fieldID); } 727 | jint GetIntField(jobject obj, jfieldID fieldID) 728 | { return functions->GetIntField(this, obj, fieldID); } 729 | jlong GetLongField(jobject obj, jfieldID fieldID) 730 | { return functions->GetLongField(this, obj, fieldID); } 731 | 732 | jfloat GetFloatField(jobject obj, jfieldID fieldID) 733 | { return functions->GetFloatField(this, obj, fieldID); } 734 | 735 | jdouble GetDoubleField(jobject obj, jfieldID fieldID) 736 | { return functions->GetDoubleField(this, obj, fieldID); } 737 | 738 | void SetObjectField(jobject obj, jfieldID fieldID, jobject value) 739 | { functions->SetObjectField(this, obj, fieldID, value); } 740 | void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value) 741 | { functions->SetBooleanField(this, obj, fieldID, value); } 742 | void SetByteField(jobject obj, jfieldID fieldID, jbyte value) 743 | { functions->SetByteField(this, obj, fieldID, value); } 744 | void SetCharField(jobject obj, jfieldID fieldID, jchar value) 745 | { functions->SetCharField(this, obj, fieldID, value); } 746 | void SetShortField(jobject obj, jfieldID fieldID, jshort value) 747 | { functions->SetShortField(this, obj, fieldID, value); } 748 | void SetIntField(jobject obj, jfieldID fieldID, jint value) 749 | { functions->SetIntField(this, obj, fieldID, value); } 750 | void SetLongField(jobject obj, jfieldID fieldID, jlong value) 751 | { functions->SetLongField(this, obj, fieldID, value); } 752 | 753 | void SetFloatField(jobject obj, jfieldID fieldID, jfloat value) 754 | { functions->SetFloatField(this, obj, fieldID, value); } 755 | 756 | void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value) 757 | { functions->SetDoubleField(this, obj, fieldID, value); } 758 | 759 | jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig) 760 | { return functions->GetStaticMethodID(this, clazz, name, sig); } 761 | 762 | #define CALL_STATIC_TYPE_METHOD(_jtype, _jname) \ 763 | \ 764 | _jtype CallStatic##_jname##Method(jclass clazz, jmethodID methodID, \ 765 | ...) \ 766 | { \ 767 | _jtype result; \ 768 | va_list args; \ 769 | va_start(args, methodID); \ 770 | result = functions->CallStatic##_jname##MethodV(this, clazz, \ 771 | methodID, args); \ 772 | va_end(args); \ 773 | return result; \ 774 | } 775 | #define CALL_STATIC_TYPE_METHODV(_jtype, _jname) \ 776 | \ 777 | _jtype CallStatic##_jname##MethodV(jclass clazz, jmethodID methodID, \ 778 | va_list args) \ 779 | { return functions->CallStatic##_jname##MethodV(this, clazz, methodID, \ 780 | args); } 781 | #define CALL_STATIC_TYPE_METHODA(_jtype, _jname) \ 782 | \ 783 | _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID, \ 784 | jvalue* args) \ 785 | { return functions->CallStatic##_jname##MethodA(this, clazz, methodID, \ 786 | args); } 787 | 788 | #define CALL_STATIC_TYPE(_jtype, _jname) \ 789 | CALL_STATIC_TYPE_METHOD(_jtype, _jname) \ 790 | CALL_STATIC_TYPE_METHODV(_jtype, _jname) \ 791 | CALL_STATIC_TYPE_METHODA(_jtype, _jname) 792 | 793 | CALL_STATIC_TYPE(jobject, Object) 794 | CALL_STATIC_TYPE(jboolean, Boolean) 795 | CALL_STATIC_TYPE(jbyte, Byte) 796 | CALL_STATIC_TYPE(jchar, Char) 797 | CALL_STATIC_TYPE(jshort, Short) 798 | CALL_STATIC_TYPE(jint, Int) 799 | CALL_STATIC_TYPE(jlong, Long) 800 | CALL_STATIC_TYPE(jfloat, Float) 801 | CALL_STATIC_TYPE(jdouble, Double) 802 | 803 | void CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...) 804 | { 805 | va_list args; 806 | va_start(args, methodID); 807 | functions->CallStaticVoidMethodV(this, clazz, methodID, args); 808 | va_end(args); 809 | } 810 | void CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args) 811 | { functions->CallStaticVoidMethodV(this, clazz, methodID, args); } 812 | void CallStaticVoidMethodA(jclass clazz, jmethodID methodID, jvalue* args) 813 | { functions->CallStaticVoidMethodA(this, clazz, methodID, args); } 814 | 815 | jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig) 816 | { return functions->GetStaticFieldID(this, clazz, name, sig); } 817 | 818 | jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) 819 | { return functions->GetStaticObjectField(this, clazz, fieldID); } 820 | jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) 821 | { return functions->GetStaticBooleanField(this, clazz, fieldID); } 822 | jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) 823 | { return functions->GetStaticByteField(this, clazz, fieldID); } 824 | jchar GetStaticCharField(jclass clazz, jfieldID fieldID) 825 | { return functions->GetStaticCharField(this, clazz, fieldID); } 826 | jshort GetStaticShortField(jclass clazz, jfieldID fieldID) 827 | { return functions->GetStaticShortField(this, clazz, fieldID); } 828 | jint GetStaticIntField(jclass clazz, jfieldID fieldID) 829 | { return functions->GetStaticIntField(this, clazz, fieldID); } 830 | jlong GetStaticLongField(jclass clazz, jfieldID fieldID) 831 | { return functions->GetStaticLongField(this, clazz, fieldID); } 832 | 833 | jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) 834 | { return functions->GetStaticFloatField(this, clazz, fieldID); } 835 | 836 | jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) 837 | { return functions->GetStaticDoubleField(this, clazz, fieldID); } 838 | 839 | void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value) 840 | { functions->SetStaticObjectField(this, clazz, fieldID, value); } 841 | void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value) 842 | { functions->SetStaticBooleanField(this, clazz, fieldID, value); } 843 | void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value) 844 | { functions->SetStaticByteField(this, clazz, fieldID, value); } 845 | void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value) 846 | { functions->SetStaticCharField(this, clazz, fieldID, value); } 847 | void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value) 848 | { functions->SetStaticShortField(this, clazz, fieldID, value); } 849 | void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value) 850 | { functions->SetStaticIntField(this, clazz, fieldID, value); } 851 | void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value) 852 | { functions->SetStaticLongField(this, clazz, fieldID, value); } 853 | 854 | void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value) 855 | { functions->SetStaticFloatField(this, clazz, fieldID, value); } 856 | 857 | void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value) 858 | { functions->SetStaticDoubleField(this, clazz, fieldID, value); } 859 | 860 | jstring NewString(const jchar* unicodeChars, jsize len) 861 | { return functions->NewString(this, unicodeChars, len); } 862 | 863 | jsize GetStringLength(jstring string) 864 | { return functions->GetStringLength(this, string); } 865 | 866 | const jchar* GetStringChars(jstring string, jboolean* isCopy) 867 | { return functions->GetStringChars(this, string, isCopy); } 868 | 869 | void ReleaseStringChars(jstring string, const jchar* chars) 870 | { functions->ReleaseStringChars(this, string, chars); } 871 | 872 | jstring NewStringUTF(const char* bytes) 873 | { return functions->NewStringUTF(this, bytes); } 874 | 875 | jsize GetStringUTFLength(jstring string) 876 | { return functions->GetStringUTFLength(this, string); } 877 | 878 | const char* GetStringUTFChars(jstring string, jboolean* isCopy) 879 | { return functions->GetStringUTFChars(this, string, isCopy); } 880 | 881 | void ReleaseStringUTFChars(jstring string, const char* utf) 882 | { functions->ReleaseStringUTFChars(this, string, utf); } 883 | 884 | jsize GetArrayLength(jarray array) 885 | { return functions->GetArrayLength(this, array); } 886 | 887 | jobjectArray NewObjectArray(jsize length, jclass elementClass, 888 | jobject initialElement) 889 | { return functions->NewObjectArray(this, length, elementClass, 890 | initialElement); } 891 | 892 | jobject GetObjectArrayElement(jobjectArray array, jsize index) 893 | { return functions->GetObjectArrayElement(this, array, index); } 894 | 895 | void SetObjectArrayElement(jobjectArray array, jsize index, jobject value) 896 | { functions->SetObjectArrayElement(this, array, index, value); } 897 | 898 | jbooleanArray NewBooleanArray(jsize length) 899 | { return functions->NewBooleanArray(this, length); } 900 | jbyteArray NewByteArray(jsize length) 901 | { return functions->NewByteArray(this, length); } 902 | jcharArray NewCharArray(jsize length) 903 | { return functions->NewCharArray(this, length); } 904 | jshortArray NewShortArray(jsize length) 905 | { return functions->NewShortArray(this, length); } 906 | jintArray NewIntArray(jsize length) 907 | { return functions->NewIntArray(this, length); } 908 | jlongArray NewLongArray(jsize length) 909 | { return functions->NewLongArray(this, length); } 910 | jfloatArray NewFloatArray(jsize length) 911 | { return functions->NewFloatArray(this, length); } 912 | jdoubleArray NewDoubleArray(jsize length) 913 | { return functions->NewDoubleArray(this, length); } 914 | 915 | jboolean* GetBooleanArrayElements(jbooleanArray array, jboolean* isCopy) 916 | { return functions->GetBooleanArrayElements(this, array, isCopy); } 917 | jbyte* GetByteArrayElements(jbyteArray array, jboolean* isCopy) 918 | { return functions->GetByteArrayElements(this, array, isCopy); } 919 | jchar* GetCharArrayElements(jcharArray array, jboolean* isCopy) 920 | { return functions->GetCharArrayElements(this, array, isCopy); } 921 | jshort* GetShortArrayElements(jshortArray array, jboolean* isCopy) 922 | { return functions->GetShortArrayElements(this, array, isCopy); } 923 | jint* GetIntArrayElements(jintArray array, jboolean* isCopy) 924 | { return functions->GetIntArrayElements(this, array, isCopy); } 925 | jlong* GetLongArrayElements(jlongArray array, jboolean* isCopy) 926 | { return functions->GetLongArrayElements(this, array, isCopy); } 927 | jfloat* GetFloatArrayElements(jfloatArray array, jboolean* isCopy) 928 | { return functions->GetFloatArrayElements(this, array, isCopy); } 929 | jdouble* GetDoubleArrayElements(jdoubleArray array, jboolean* isCopy) 930 | { return functions->GetDoubleArrayElements(this, array, isCopy); } 931 | 932 | void ReleaseBooleanArrayElements(jbooleanArray array, jboolean* elems, 933 | jint mode) 934 | { functions->ReleaseBooleanArrayElements(this, array, elems, mode); } 935 | void ReleaseByteArrayElements(jbyteArray array, jbyte* elems, 936 | jint mode) 937 | { functions->ReleaseByteArrayElements(this, array, elems, mode); } 938 | void ReleaseCharArrayElements(jcharArray array, jchar* elems, 939 | jint mode) 940 | { functions->ReleaseCharArrayElements(this, array, elems, mode); } 941 | void ReleaseShortArrayElements(jshortArray array, jshort* elems, 942 | jint mode) 943 | { functions->ReleaseShortArrayElements(this, array, elems, mode); } 944 | void ReleaseIntArrayElements(jintArray array, jint* elems, 945 | jint mode) 946 | { functions->ReleaseIntArrayElements(this, array, elems, mode); } 947 | void ReleaseLongArrayElements(jlongArray array, jlong* elems, 948 | jint mode) 949 | { functions->ReleaseLongArrayElements(this, array, elems, mode); } 950 | void ReleaseFloatArrayElements(jfloatArray array, jfloat* elems, 951 | jint mode) 952 | { functions->ReleaseFloatArrayElements(this, array, elems, mode); } 953 | void ReleaseDoubleArrayElements(jdoubleArray array, jdouble* elems, 954 | jint mode) 955 | { functions->ReleaseDoubleArrayElements(this, array, elems, mode); } 956 | 957 | void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, 958 | jboolean* buf) 959 | { functions->GetBooleanArrayRegion(this, array, start, len, buf); } 960 | void GetByteArrayRegion(jbyteArray array, jsize start, jsize len, 961 | jbyte* buf) 962 | { functions->GetByteArrayRegion(this, array, start, len, buf); } 963 | void GetCharArrayRegion(jcharArray array, jsize start, jsize len, 964 | jchar* buf) 965 | { functions->GetCharArrayRegion(this, array, start, len, buf); } 966 | void GetShortArrayRegion(jshortArray array, jsize start, jsize len, 967 | jshort* buf) 968 | { functions->GetShortArrayRegion(this, array, start, len, buf); } 969 | void GetIntArrayRegion(jintArray array, jsize start, jsize len, 970 | jint* buf) 971 | { functions->GetIntArrayRegion(this, array, start, len, buf); } 972 | void GetLongArrayRegion(jlongArray array, jsize start, jsize len, 973 | jlong* buf) 974 | { functions->GetLongArrayRegion(this, array, start, len, buf); } 975 | void GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, 976 | jfloat* buf) 977 | { functions->GetFloatArrayRegion(this, array, start, len, buf); } 978 | void GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, 979 | jdouble* buf) 980 | { functions->GetDoubleArrayRegion(this, array, start, len, buf); } 981 | 982 | void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, 983 | const jboolean* buf) 984 | { functions->SetBooleanArrayRegion(this, array, start, len, buf); } 985 | void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, 986 | const jbyte* buf) 987 | { functions->SetByteArrayRegion(this, array, start, len, buf); } 988 | void SetCharArrayRegion(jcharArray array, jsize start, jsize len, 989 | const jchar* buf) 990 | { functions->SetCharArrayRegion(this, array, start, len, buf); } 991 | void SetShortArrayRegion(jshortArray array, jsize start, jsize len, 992 | const jshort* buf) 993 | { functions->SetShortArrayRegion(this, array, start, len, buf); } 994 | void SetIntArrayRegion(jintArray array, jsize start, jsize len, 995 | const jint* buf) 996 | { functions->SetIntArrayRegion(this, array, start, len, buf); } 997 | void SetLongArrayRegion(jlongArray array, jsize start, jsize len, 998 | const jlong* buf) 999 | { functions->SetLongArrayRegion(this, array, start, len, buf); } 1000 | void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, 1001 | const jfloat* buf) 1002 | { functions->SetFloatArrayRegion(this, array, start, len, buf); } 1003 | void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, 1004 | const jdouble* buf) 1005 | { functions->SetDoubleArrayRegion(this, array, start, len, buf); } 1006 | 1007 | jint RegisterNatives(jclass clazz, const JNINativeMethod* methods, 1008 | jint nMethods) 1009 | { return functions->RegisterNatives(this, clazz, methods, nMethods); } 1010 | 1011 | jint UnregisterNatives(jclass clazz) 1012 | { return functions->UnregisterNatives(this, clazz); } 1013 | 1014 | jint MonitorEnter(jobject obj) 1015 | { return functions->MonitorEnter(this, obj); } 1016 | 1017 | jint MonitorExit(jobject obj) 1018 | { return functions->MonitorExit(this, obj); } 1019 | 1020 | jint GetJavaVM(JavaVM** vm) 1021 | { return functions->GetJavaVM(this, vm); } 1022 | 1023 | void GetStringRegion(jstring str, jsize start, jsize len, jchar* buf) 1024 | { functions->GetStringRegion(this, str, start, len, buf); } 1025 | 1026 | void GetStringUTFRegion(jstring str, jsize start, jsize len, char* buf) 1027 | { return functions->GetStringUTFRegion(this, str, start, len, buf); } 1028 | 1029 | void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) 1030 | { return functions->GetPrimitiveArrayCritical(this, array, isCopy); } 1031 | 1032 | void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode) 1033 | { functions->ReleasePrimitiveArrayCritical(this, array, carray, mode); } 1034 | 1035 | const jchar* GetStringCritical(jstring string, jboolean* isCopy) 1036 | { return functions->GetStringCritical(this, string, isCopy); } 1037 | 1038 | void ReleaseStringCritical(jstring string, const jchar* carray) 1039 | { functions->ReleaseStringCritical(this, string, carray); } 1040 | 1041 | jweak NewWeakGlobalRef(jobject obj) 1042 | { return functions->NewWeakGlobalRef(this, obj); } 1043 | 1044 | void DeleteWeakGlobalRef(jweak obj) 1045 | { functions->DeleteWeakGlobalRef(this, obj); } 1046 | 1047 | jboolean ExceptionCheck() 1048 | { return functions->ExceptionCheck(this); } 1049 | 1050 | jobject NewDirectByteBuffer(void* address, jlong capacity) 1051 | { return functions->NewDirectByteBuffer(this, address, capacity); } 1052 | 1053 | void* GetDirectBufferAddress(jobject buf) 1054 | { return functions->GetDirectBufferAddress(this, buf); } 1055 | 1056 | jlong GetDirectBufferCapacity(jobject buf) 1057 | { return functions->GetDirectBufferCapacity(this, buf); } 1058 | 1059 | /* added in JNI 1.6 */ 1060 | jobjectRefType GetObjectRefType(jobject obj) 1061 | { return functions->GetObjectRefType(this, obj); } 1062 | #endif /*__cplusplus*/ 1063 | }; 1064 | 1065 | 1066 | /* 1067 | * JNI invocation interface. 1068 | */ 1069 | struct JNIInvokeInterface { 1070 | void* reserved0; 1071 | void* reserved1; 1072 | void* reserved2; 1073 | 1074 | jint (*DestroyJavaVM)(JavaVM*); 1075 | jint (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*); 1076 | jint (*DetachCurrentThread)(JavaVM*); 1077 | jint (*GetEnv)(JavaVM*, void**, jint); 1078 | jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*); 1079 | }; 1080 | 1081 | /* 1082 | * C++ version. 1083 | */ 1084 | struct _JavaVM { 1085 | const struct JNIInvokeInterface* functions; 1086 | 1087 | #if defined(__cplusplus) 1088 | jint DestroyJavaVM() 1089 | { return functions->DestroyJavaVM(this); } 1090 | jint AttachCurrentThread(JNIEnv** p_env, void* thr_args) 1091 | { return functions->AttachCurrentThread(this, p_env, thr_args); } 1092 | jint DetachCurrentThread() 1093 | { return functions->DetachCurrentThread(this); } 1094 | jint GetEnv(void** env, jint version) 1095 | { return functions->GetEnv(this, env, version); } 1096 | jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args) 1097 | { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); } 1098 | #endif /*__cplusplus*/ 1099 | }; 1100 | 1101 | struct JavaVMAttachArgs { 1102 | jint version; /* must be >= JNI_VERSION_1_2 */ 1103 | const char* name; /* NULL or name of thread as modified UTF-8 str */ 1104 | jobject group; /* global ref of a ThreadGroup object, or NULL */ 1105 | }; 1106 | typedef struct JavaVMAttachArgs JavaVMAttachArgs; 1107 | 1108 | /* 1109 | * JNI 1.2+ initialization. (As of 1.6, the pre-1.2 structures are no 1110 | * longer supported.) 1111 | */ 1112 | typedef struct JavaVMOption { 1113 | const char* optionString; 1114 | void* extraInfo; 1115 | } JavaVMOption; 1116 | 1117 | typedef struct JavaVMInitArgs { 1118 | jint version; /* use JNI_VERSION_1_2 or later */ 1119 | 1120 | jint nOptions; 1121 | JavaVMOption* options; 1122 | jboolean ignoreUnrecognized; 1123 | } JavaVMInitArgs; 1124 | 1125 | #ifdef __cplusplus 1126 | extern "C" { 1127 | #endif 1128 | /* 1129 | * VM initialization functions. 1130 | * 1131 | * Note these are the only symbols exported for JNI by the VM. 1132 | */ 1133 | #if 0 /* In practice, these are not exported by the NDK so don't declare them */ 1134 | jint JNI_GetDefaultJavaVMInitArgs(void*); 1135 | jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*); 1136 | jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*); 1137 | #endif 1138 | 1139 | #define JNIIMPORT 1140 | #define JNIEXPORT //__attribute__ ((visibility ("default"))) 1141 | #define JNICALL 1142 | 1143 | /* 1144 | * Prototypes for functions exported by loadable shared libs. These are 1145 | * called by JNI, not provided by JNI. 1146 | */ 1147 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved); 1148 | JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved); 1149 | 1150 | #ifdef __cplusplus 1151 | } 1152 | #endif 1153 | 1154 | 1155 | /* 1156 | * Manifest constants. 1157 | */ 1158 | #define JNI_FALSE 0 1159 | #define JNI_TRUE 1 1160 | 1161 | #define JNI_VERSION_1_1 0x00010001 1162 | #define JNI_VERSION_1_2 0x00010002 1163 | #define JNI_VERSION_1_4 0x00010004 1164 | #define JNI_VERSION_1_6 0x00010006 1165 | 1166 | #define JNI_OK (0) /* no error */ 1167 | #define JNI_ERR (-1) /* generic error */ 1168 | #define JNI_EDETACHED (-2) /* thread detached from the VM */ 1169 | #define JNI_EVERSION (-3) /* JNI version error */ 1170 | 1171 | #define JNI_COMMIT 1 /* copy content, do not free buffer */ 1172 | #define JNI_ABORT 2 /* free buffer w/o copying back */ 1173 | 1174 | #endif /* JNI_H_ */ 1175 | -------------------------------------------------------------------------------- /libmg20pbase.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/libmg20pbase.so -------------------------------------------------------------------------------- /libmg20pbase.so.fixed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/libmg20pbase.so.fixed -------------------------------------------------------------------------------- /libshella-2.10.7.1.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/libshella-2.10.7.1.so -------------------------------------------------------------------------------- /libshella-2.10.7.1_org.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/libshella-2.10.7.1_org.so -------------------------------------------------------------------------------- /log.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file log.cpp 2017\5\11 15:24:27 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "log.h" 8 | void LOG(const char *level, const char *log_format, ...){ 9 | printf("[%s]", level); 10 | va_list var_arg; 11 | va_start(var_arg, log_format); 12 | 13 | //todo print content 14 | printf(log_format, *var_arg); 15 | printf("\n"); 16 | 17 | va_end(var_arg); 18 | } 19 | 20 | /******************************************************************************/ -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file log.h 2017\5\11 14:17:38 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef LOG_8EC8D1A7_8377_42DC_9AB1_7775907F16EB_H__ 8 | #define LOG_8EC8D1A7_8377_42DC_9AB1_7775907F16EB_H__ 9 | 10 | #include 11 | #include 12 | 13 | //common log 14 | #define INFO "INFO" 15 | #define ERR "ERROR" 16 | #define DBG "DEBUG" 17 | #define WARN "WARNING" 18 | 19 | void LOG(const char *level, const char *log_format, ...); 20 | 21 | #endif// LOG_8EC8D1A7_8377_42DC_9AB1_7775907F16EB_H__ 22 | -------------------------------------------------------------------------------- /util/util.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file util.cpp 2017\5\11 17:01:27 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #include "util.h" 8 | #include 9 | 10 | /******************************************************************************/ 11 | 12 | 13 | /******************************************************************************/ 14 | 15 | std::string util::itoa(int i, int rdx) 16 | { 17 | char _rs[100] = {0}; 18 | ::_itoa_s(i, _rs, rdx); 19 | 20 | return std::string(_rs); 21 | } 22 | 23 | std::string util::read_file(std::string file) 24 | { 25 | std::string file_content; 26 | 27 | char *file_content_buf = nullptr; 28 | try{ 29 | std::ifstream file_; 30 | file_.open(file, std::ios_base::binary); 31 | if (!file_.is_open()) 32 | { 33 | return file_content; 34 | } 35 | file_.seekg(0, std::ios::end); 36 | std::streamoff file_size = file_.tellg(); 37 | file_.seekg(0); 38 | file_content_buf = new char[(unsigned int)file_size]; 39 | file_.read(file_content_buf, file_size); 40 | file_content = std::string(file_content_buf, (unsigned int)file_size); 41 | file_.close(); 42 | delete[]file_content_buf; 43 | file_content_buf = nullptr; 44 | } 45 | catch (...){ 46 | if (!file_content_buf){ 47 | delete[]file_content_buf; 48 | } 49 | } 50 | return file_content; 51 | } 52 | -------------------------------------------------------------------------------- /util/util.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file util.h 2017\5\11 17:00:57 $ 3 | * @author df 4 | * @brief 5 | ******************************************************************************/ 6 | 7 | #ifndef UTIL_795B7F31_9DAF_41E1_9DE4_37B5C1D81364_H__ 8 | #define UTIL_795B7F31_9DAF_41E1_9DE4_37B5C1D81364_H__ 9 | 10 | #include 11 | /******************************************************************************/ 12 | 13 | /** 14 | * The class util 15 | * 16 | */ 17 | class util 18 | { 19 | public: 20 | static std::string itoa(int i, int rdx = 10); 21 | static std::string read_file(std::string file); 22 | }; 23 | /******************************************************************************/ 24 | #endif// UTIL_795B7F31_9DAF_41E1_9DE4_37B5C1D81364_H__ 25 | -------------------------------------------------------------------------------- /viewer/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/viewer/readme.txt -------------------------------------------------------------------------------- /xAnSo.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freakishfox/xAnSo/2f2b6bcff52aba995ad4280d41a588f7cd40a781/xAnSo.exe --------------------------------------------------------------------------------