├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── README.md ├── deps └── zlib │ ├── crc32.h │ ├── deflate.h │ ├── gzguts.h │ ├── inffast.h │ ├── inffixed.h │ ├── inflate.h │ ├── inftrees.h │ ├── trees.h │ ├── zconf.h │ ├── zlib.h │ └── zutil.h ├── dexgraph-reverse-engineering.pdf ├── include ├── Dexdump │ └── OpCodeNames.h ├── TreeConstructor │ ├── FmtDot.h │ ├── FmtEdg.h │ ├── OpcodeType.h │ ├── PackedSwitchPayload.h │ ├── SparseSwitchPayload.h │ ├── TCHelper.h │ └── TCNode.h ├── libdex │ ├── CmdUtils.h │ ├── DexCatch.h │ ├── DexClass.h │ ├── DexDataMap.h │ ├── DexFile.h │ ├── DexProto.h │ ├── InstrUtils.h │ ├── Leb128.h │ ├── OpCode.h │ ├── OptInvocation.h │ ├── SysUtil.h │ ├── ZipArchive.h │ └── sha1.h ├── other │ ├── inttypes.h │ └── typeof.h └── vm │ ├── Common.h │ └── DalvikVersion.h └── src ├── Dexdump └── OpCodenames.cpp ├── TreeConstructor ├── FmtDot.cpp ├── FmtEdg.cpp ├── OpcodeType.cpp ├── TCHelper.cpp └── TCNode.cpp ├── dexdump └── DexDump.cpp └── libdex ├── CmdUtils.cpp ├── DexCatch.cpp ├── DexClass.cpp ├── DexDataMap.cpp ├── DexFile.cpp ├── DexInlines.cpp ├── DexProto.cpp ├── DexSwapVerify.cpp ├── InstrUtils.cpp ├── Leb128.cpp ├── OptInvocation.cpp ├── SysUtil.cpp ├── ZipArchive.cpp └── sha1.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | # Debug folder 32 | debug/ 33 | release/ 34 | 35 | # Others 36 | .ycm_extra_conf.py 37 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.9) 2 | project (dexgraph) 3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 4 | 5 | include_directories( 6 | include 7 | deps/zlib/ 8 | ) 9 | 10 | set ( HEADERS 11 | include/dexdump/OpCodeNames.h 12 | include/libdex/CmdUtils.h 13 | include/libdex/DexCatch.h 14 | include/libdex/DexClass.h 15 | include/libdex/DexDataMap.h 16 | include/libdex/DexFile.h 17 | include/libdex/DexProto.h 18 | include/libdex/InstrUtils.h 19 | include/libdex/Leb128.h 20 | include/libdex/OptInvocation.h 21 | include/libdex/SysUtil.h 22 | include/libdex/ZipArchive.h 23 | include/libdex/sha1.h 24 | include/other/inttypes.h 25 | include/other/typeof.h 26 | include/TreeConstructor/FmtEdg.h 27 | include/TreeConstructor/FmtDot.h 28 | include/TreeConstructor/PackedSwitchPayload.h 29 | include/TreeConstructor/SparseSwitchPayload.h 30 | include/TreeConstructor/OpcodeType.h 31 | include/TreeConstructor/TCNode.h 32 | include/TreeConstructor/TCHelper.h 33 | include/vm/Common.h 34 | include/vm/DalvikVersion.h 35 | ) 36 | 37 | set( SOURCES 38 | src/dexdump/DexDump.cpp 39 | src/dexdump/OpCodenames.cpp 40 | src/libdex/CmdUtils.cpp 41 | src/libdex/DexCatch.cpp 42 | src/libdex/DexClass.cpp 43 | src/libdex/DexDataMap.cpp 44 | src/libdex/DexFile.cpp 45 | src/libdex/DexInlines.cpp 46 | src/libdex/DexProto.cpp 47 | src/libdex/DexSwapVerify.cpp 48 | src/libdex/InstrUtils.cpp 49 | src/libdex/Leb128.cpp 50 | src/libdex/OptInvocation.cpp 51 | src/libdex/sha1.cpp 52 | src/libdex/SysUtil.cpp 53 | src/libdex/ZipArchive.cpp 54 | src/TreeConstructor/FmtEdg.cpp 55 | src/TreeConstructor/FmtDot.cpp 56 | src/TreeConstructor/OpcodeType.cpp 57 | src/TreeConstructor/TCNode.cpp 58 | src/TreeConstructor/TCHelper.cpp 59 | ) 60 | 61 | add_executable(dexgraph ${SOURCES} ${HEADERS}) 62 | 63 | find_package(ZLIB) 64 | target_include_directories(dexgraph PUBLIC ${ZLIB_INCLUDE_DIR}) 65 | target_link_libraries (dexgraph ${ZLIB_LIBRARY}) 66 | 67 | 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DexGraph 2 | Modified DexDump to build control flow graph from classes.dex 3 | 4 | A white paper for this project is available in the project root, [here](https://github.com/ChiminhTT/DexGraph/blob/master/dexgraph-reverse-engineering.pdf) 5 | 6 | ## Dependencies 7 | Dependencies are statically linked, hence they have to be built from sources. 8 | Dexgraph dependencies are: 9 | - zlib 10 | 11 | ### Building the dependencies 12 | #### zlib 13 | - Download sources [here](http://www.zlib.net/zlib-1.2.11.tar.gz) (zlib version 1.2.11) 14 | - Inside src folder, call: ```./configure --static``` 15 | - ```make``` 16 | - libz.a should now be available. Move it into **Dexgraph/deps/zlib/** 17 | 18 | ## Run 19 | Enter the following command: 20 | 21 | ```dexdump -D $PATH_TO_DEX_CLASSES``` 22 | 23 | The edg file will be at binary root. 24 | 25 | The dot output is dumped to stdout. You can pipe it to a file. 26 | -------------------------------------------------------------------------------- /deps/zlib/deflate.h: -------------------------------------------------------------------------------- 1 | /* deflate.h -- internal compression state 2 | * Copyright (C) 1995-2016 Jean-loup Gailly 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* @(#) $Id$ */ 12 | 13 | #ifndef DEFLATE_H 14 | #define DEFLATE_H 15 | 16 | #include "zutil.h" 17 | 18 | /* define NO_GZIP when compiling if you want to disable gzip header and 19 | trailer creation by deflate(). NO_GZIP would be used to avoid linking in 20 | the crc code when it is not needed. For shared libraries, gzip encoding 21 | should be left enabled. */ 22 | #ifndef NO_GZIP 23 | # define GZIP 24 | #endif 25 | 26 | /* =========================================================================== 27 | * Internal compression state. 28 | */ 29 | 30 | #define LENGTH_CODES 29 31 | /* number of length codes, not counting the special END_BLOCK code */ 32 | 33 | #define LITERALS 256 34 | /* number of literal bytes 0..255 */ 35 | 36 | #define L_CODES (LITERALS+1+LENGTH_CODES) 37 | /* number of Literal or Length codes, including the END_BLOCK code */ 38 | 39 | #define D_CODES 30 40 | /* number of distance codes */ 41 | 42 | #define BL_CODES 19 43 | /* number of codes used to transfer the bit lengths */ 44 | 45 | #define HEAP_SIZE (2*L_CODES+1) 46 | /* maximum heap size */ 47 | 48 | #define MAX_BITS 15 49 | /* All codes must not exceed MAX_BITS bits */ 50 | 51 | #define Buf_size 16 52 | /* size of bit buffer in bi_buf */ 53 | 54 | #define INIT_STATE 42 /* zlib header -> BUSY_STATE */ 55 | #ifdef GZIP 56 | # define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ 57 | #endif 58 | #define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ 59 | #define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ 60 | #define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ 61 | #define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ 62 | #define BUSY_STATE 113 /* deflate -> FINISH_STATE */ 63 | #define FINISH_STATE 666 /* stream complete */ 64 | /* Stream status */ 65 | 66 | 67 | /* Data structure describing a single value and its code string. */ 68 | typedef struct ct_data_s { 69 | union { 70 | ush freq; /* frequency count */ 71 | ush code; /* bit string */ 72 | } fc; 73 | union { 74 | ush dad; /* father node in Huffman tree */ 75 | ush len; /* length of bit string */ 76 | } dl; 77 | } FAR ct_data; 78 | 79 | #define Freq fc.freq 80 | #define Code fc.code 81 | #define Dad dl.dad 82 | #define Len dl.len 83 | 84 | typedef struct static_tree_desc_s static_tree_desc; 85 | 86 | typedef struct tree_desc_s { 87 | ct_data *dyn_tree; /* the dynamic tree */ 88 | int max_code; /* largest code with non zero frequency */ 89 | const static_tree_desc *stat_desc; /* the corresponding static tree */ 90 | } FAR tree_desc; 91 | 92 | typedef ush Pos; 93 | typedef Pos FAR Posf; 94 | typedef unsigned IPos; 95 | 96 | /* A Pos is an index in the character window. We use short instead of int to 97 | * save space in the various tables. IPos is used only for parameter passing. 98 | */ 99 | 100 | typedef struct internal_state { 101 | z_streamp strm; /* pointer back to this zlib stream */ 102 | int status; /* as the name implies */ 103 | Bytef *pending_buf; /* output still pending */ 104 | ulg pending_buf_size; /* size of pending_buf */ 105 | Bytef *pending_out; /* next pending byte to output to the stream */ 106 | ulg pending; /* nb of bytes in the pending buffer */ 107 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ 108 | gz_headerp gzhead; /* gzip header information to write */ 109 | ulg gzindex; /* where in extra, name, or comment */ 110 | Byte method; /* can only be DEFLATED */ 111 | int last_flush; /* value of flush param for previous deflate call */ 112 | 113 | /* used by deflate.c: */ 114 | 115 | uInt w_size; /* LZ77 window size (32K by default) */ 116 | uInt w_bits; /* log2(w_size) (8..16) */ 117 | uInt w_mask; /* w_size - 1 */ 118 | 119 | Bytef *window; 120 | /* Sliding window. Input bytes are read into the second half of the window, 121 | * and move to the first half later to keep a dictionary of at least wSize 122 | * bytes. With this organization, matches are limited to a distance of 123 | * wSize-MAX_MATCH bytes, but this ensures that IO is always 124 | * performed with a length multiple of the block size. Also, it limits 125 | * the window size to 64K, which is quite useful on MSDOS. 126 | * To do: use the user input buffer as sliding window. 127 | */ 128 | 129 | ulg window_size; 130 | /* Actual size of window: 2*wSize, except when the user input buffer 131 | * is directly used as sliding window. 132 | */ 133 | 134 | Posf *prev; 135 | /* Link to older string with same hash index. To limit the size of this 136 | * array to 64K, this link is maintained only for the last 32K strings. 137 | * An index in this array is thus a window index modulo 32K. 138 | */ 139 | 140 | Posf *head; /* Heads of the hash chains or NIL. */ 141 | 142 | uInt ins_h; /* hash index of string to be inserted */ 143 | uInt hash_size; /* number of elements in hash table */ 144 | uInt hash_bits; /* log2(hash_size) */ 145 | uInt hash_mask; /* hash_size-1 */ 146 | 147 | uInt hash_shift; 148 | /* Number of bits by which ins_h must be shifted at each input 149 | * step. It must be such that after MIN_MATCH steps, the oldest 150 | * byte no longer takes part in the hash key, that is: 151 | * hash_shift * MIN_MATCH >= hash_bits 152 | */ 153 | 154 | long block_start; 155 | /* Window position at the beginning of the current output block. Gets 156 | * negative when the window is moved backwards. 157 | */ 158 | 159 | uInt match_length; /* length of best match */ 160 | IPos prev_match; /* previous match */ 161 | int match_available; /* set if previous match exists */ 162 | uInt strstart; /* start of string to insert */ 163 | uInt match_start; /* start of matching string */ 164 | uInt lookahead; /* number of valid bytes ahead in window */ 165 | 166 | uInt prev_length; 167 | /* Length of the best match at previous step. Matches not greater than this 168 | * are discarded. This is used in the lazy match evaluation. 169 | */ 170 | 171 | uInt max_chain_length; 172 | /* To speed up deflation, hash chains are never searched beyond this 173 | * length. A higher limit improves compression ratio but degrades the 174 | * speed. 175 | */ 176 | 177 | uInt max_lazy_match; 178 | /* Attempt to find a better match only when the current match is strictly 179 | * smaller than this value. This mechanism is used only for compression 180 | * levels >= 4. 181 | */ 182 | # define max_insert_length max_lazy_match 183 | /* Insert new strings in the hash table only if the match length is not 184 | * greater than this length. This saves time but degrades compression. 185 | * max_insert_length is used only for compression levels <= 3. 186 | */ 187 | 188 | int level; /* compression level (1..9) */ 189 | int strategy; /* favor or force Huffman coding*/ 190 | 191 | uInt good_match; 192 | /* Use a faster search when the previous match is longer than this */ 193 | 194 | int nice_match; /* Stop searching when current match exceeds this */ 195 | 196 | /* used by trees.c: */ 197 | /* Didn't use ct_data typedef below to suppress compiler warning */ 198 | struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ 199 | struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ 200 | struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ 201 | 202 | struct tree_desc_s l_desc; /* desc. for literal tree */ 203 | struct tree_desc_s d_desc; /* desc. for distance tree */ 204 | struct tree_desc_s bl_desc; /* desc. for bit length tree */ 205 | 206 | ush bl_count[MAX_BITS+1]; 207 | /* number of codes at each bit length for an optimal tree */ 208 | 209 | int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ 210 | int heap_len; /* number of elements in the heap */ 211 | int heap_max; /* element of largest frequency */ 212 | /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. 213 | * The same heap array is used to build all trees. 214 | */ 215 | 216 | uch depth[2*L_CODES+1]; 217 | /* Depth of each subtree used as tie breaker for trees of equal frequency 218 | */ 219 | 220 | uchf *l_buf; /* buffer for literals or lengths */ 221 | 222 | uInt lit_bufsize; 223 | /* Size of match buffer for literals/lengths. There are 4 reasons for 224 | * limiting lit_bufsize to 64K: 225 | * - frequencies can be kept in 16 bit counters 226 | * - if compression is not successful for the first block, all input 227 | * data is still in the window so we can still emit a stored block even 228 | * when input comes from standard input. (This can also be done for 229 | * all blocks if lit_bufsize is not greater than 32K.) 230 | * - if compression is not successful for a file smaller than 64K, we can 231 | * even emit a stored file instead of a stored block (saving 5 bytes). 232 | * This is applicable only for zip (not gzip or zlib). 233 | * - creating new Huffman trees less frequently may not provide fast 234 | * adaptation to changes in the input data statistics. (Take for 235 | * example a binary file with poorly compressible code followed by 236 | * a highly compressible string table.) Smaller buffer sizes give 237 | * fast adaptation but have of course the overhead of transmitting 238 | * trees more frequently. 239 | * - I can't count above 4 240 | */ 241 | 242 | uInt last_lit; /* running index in l_buf */ 243 | 244 | ushf *d_buf; 245 | /* Buffer for distances. To simplify the code, d_buf and l_buf have 246 | * the same number of elements. To use different lengths, an extra flag 247 | * array would be necessary. 248 | */ 249 | 250 | ulg opt_len; /* bit length of current block with optimal trees */ 251 | ulg static_len; /* bit length of current block with static trees */ 252 | uInt matches; /* number of string matches in current block */ 253 | uInt insert; /* bytes at end of window left to insert */ 254 | 255 | #ifdef ZLIB_DEBUG 256 | ulg compressed_len; /* total bit length of compressed file mod 2^32 */ 257 | ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ 258 | #endif 259 | 260 | ush bi_buf; 261 | /* Output buffer. bits are inserted starting at the bottom (least 262 | * significant bits). 263 | */ 264 | int bi_valid; 265 | /* Number of valid bits in bi_buf. All bits above the last valid bit 266 | * are always zero. 267 | */ 268 | 269 | ulg high_water; 270 | /* High water mark offset in window for initialized bytes -- bytes above 271 | * this are set to zero in order to avoid memory check warnings when 272 | * longest match routines access bytes past the input. This is then 273 | * updated to the new high water mark. 274 | */ 275 | 276 | } FAR deflate_state; 277 | 278 | /* Output a byte on the stream. 279 | * IN assertion: there is enough room in pending_buf. 280 | */ 281 | #define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} 282 | 283 | 284 | #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) 285 | /* Minimum amount of lookahead, except at the end of the input file. 286 | * See deflate.c for comments about the MIN_MATCH+1. 287 | */ 288 | 289 | #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) 290 | /* In order to simplify the code, particularly on 16 bit machines, match 291 | * distances are limited to MAX_DIST instead of WSIZE. 292 | */ 293 | 294 | #define WIN_INIT MAX_MATCH 295 | /* Number of bytes after end of data in window to initialize in order to avoid 296 | memory checker errors from longest match routines */ 297 | 298 | /* in trees.c */ 299 | void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); 300 | int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); 301 | void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, 302 | ulg stored_len, int last)); 303 | void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); 304 | void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); 305 | void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, 306 | ulg stored_len, int last)); 307 | 308 | #define d_code(dist) \ 309 | ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) 310 | /* Mapping from a distance to a distance code. dist is the distance - 1 and 311 | * must not have side effects. _dist_code[256] and _dist_code[257] are never 312 | * used. 313 | */ 314 | 315 | #ifndef ZLIB_DEBUG 316 | /* Inline versions of _tr_tally for speed: */ 317 | 318 | #if defined(GEN_TREES_H) || !defined(STDC) 319 | extern uch ZLIB_INTERNAL _length_code[]; 320 | extern uch ZLIB_INTERNAL _dist_code[]; 321 | #else 322 | extern const uch ZLIB_INTERNAL _length_code[]; 323 | extern const uch ZLIB_INTERNAL _dist_code[]; 324 | #endif 325 | 326 | # define _tr_tally_lit(s, c, flush) \ 327 | { uch cc = (c); \ 328 | s->d_buf[s->last_lit] = 0; \ 329 | s->l_buf[s->last_lit++] = cc; \ 330 | s->dyn_ltree[cc].Freq++; \ 331 | flush = (s->last_lit == s->lit_bufsize-1); \ 332 | } 333 | # define _tr_tally_dist(s, distance, length, flush) \ 334 | { uch len = (uch)(length); \ 335 | ush dist = (ush)(distance); \ 336 | s->d_buf[s->last_lit] = dist; \ 337 | s->l_buf[s->last_lit++] = len; \ 338 | dist--; \ 339 | s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ 340 | s->dyn_dtree[d_code(dist)].Freq++; \ 341 | flush = (s->last_lit == s->lit_bufsize-1); \ 342 | } 343 | #else 344 | # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) 345 | # define _tr_tally_dist(s, distance, length, flush) \ 346 | flush = _tr_tally(s, distance, length) 347 | #endif 348 | 349 | #endif /* DEFLATE_H */ 350 | -------------------------------------------------------------------------------- /deps/zlib/gzguts.h: -------------------------------------------------------------------------------- 1 | /* gzguts.h -- zlib internal header definitions for gz* operations 2 | * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | #ifdef _LARGEFILE64_SOURCE 7 | # ifndef _LARGEFILE_SOURCE 8 | # define _LARGEFILE_SOURCE 1 9 | # endif 10 | # ifdef _FILE_OFFSET_BITS 11 | # undef _FILE_OFFSET_BITS 12 | # endif 13 | #endif 14 | 15 | #ifdef HAVE_HIDDEN 16 | # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) 17 | #else 18 | # define ZLIB_INTERNAL 19 | #endif 20 | 21 | #include 22 | #include "zlib.h" 23 | #ifdef STDC 24 | # include 25 | # include 26 | # include 27 | #endif 28 | 29 | #ifndef _POSIX_SOURCE 30 | # define _POSIX_SOURCE 31 | #endif 32 | #include 33 | 34 | #ifdef _WIN32 35 | # include 36 | #endif 37 | 38 | #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) 39 | # include 40 | #endif 41 | 42 | #if defined(_WIN32) || defined(__CYGWIN__) 43 | # define WIDECHAR 44 | #endif 45 | 46 | #ifdef WINAPI_FAMILY 47 | # define open _open 48 | # define read _read 49 | # define write _write 50 | # define close _close 51 | #endif 52 | 53 | #ifdef NO_DEFLATE /* for compatibility with old definition */ 54 | # define NO_GZCOMPRESS 55 | #endif 56 | 57 | #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) 58 | # ifndef HAVE_VSNPRINTF 59 | # define HAVE_VSNPRINTF 60 | # endif 61 | #endif 62 | 63 | #if defined(__CYGWIN__) 64 | # ifndef HAVE_VSNPRINTF 65 | # define HAVE_VSNPRINTF 66 | # endif 67 | #endif 68 | 69 | #if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) 70 | # ifndef HAVE_VSNPRINTF 71 | # define HAVE_VSNPRINTF 72 | # endif 73 | #endif 74 | 75 | #ifndef HAVE_VSNPRINTF 76 | # ifdef MSDOS 77 | /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), 78 | but for now we just assume it doesn't. */ 79 | # define NO_vsnprintf 80 | # endif 81 | # ifdef __TURBOC__ 82 | # define NO_vsnprintf 83 | # endif 84 | # ifdef WIN32 85 | /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ 86 | # if !defined(vsnprintf) && !defined(NO_vsnprintf) 87 | # if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) 88 | # define vsnprintf _vsnprintf 89 | # endif 90 | # endif 91 | # endif 92 | # ifdef __SASC 93 | # define NO_vsnprintf 94 | # endif 95 | # ifdef VMS 96 | # define NO_vsnprintf 97 | # endif 98 | # ifdef __OS400__ 99 | # define NO_vsnprintf 100 | # endif 101 | # ifdef __MVS__ 102 | # define NO_vsnprintf 103 | # endif 104 | #endif 105 | 106 | /* unlike snprintf (which is required in C99), _snprintf does not guarantee 107 | null termination of the result -- however this is only used in gzlib.c where 108 | the result is assured to fit in the space provided */ 109 | #if defined(_MSC_VER) && _MSC_VER < 1900 110 | # define snprintf _snprintf 111 | #endif 112 | 113 | #ifndef local 114 | # define local static 115 | #endif 116 | /* since "static" is used to mean two completely different things in C, we 117 | define "local" for the non-static meaning of "static", for readability 118 | (compile with -Dlocal if your debugger can't find static symbols) */ 119 | 120 | /* gz* functions always use library allocation functions */ 121 | #ifndef STDC 122 | extern voidp malloc OF((uInt size)); 123 | extern void free OF((voidpf ptr)); 124 | #endif 125 | 126 | /* get errno and strerror definition */ 127 | #if defined UNDER_CE 128 | # include 129 | # define zstrerror() gz_strwinerror((DWORD)GetLastError()) 130 | #else 131 | # ifndef NO_STRERROR 132 | # include 133 | # define zstrerror() strerror(errno) 134 | # else 135 | # define zstrerror() "stdio error (consult errno)" 136 | # endif 137 | #endif 138 | 139 | /* provide prototypes for these when building zlib without LFS */ 140 | #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 141 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); 142 | ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); 143 | ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); 144 | ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); 145 | #endif 146 | 147 | /* default memLevel */ 148 | #if MAX_MEM_LEVEL >= 8 149 | # define DEF_MEM_LEVEL 8 150 | #else 151 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL 152 | #endif 153 | 154 | /* default i/o buffer size -- double this for output when reading (this and 155 | twice this must be able to fit in an unsigned type) */ 156 | #define GZBUFSIZE 8192 157 | 158 | /* gzip modes, also provide a little integrity check on the passed structure */ 159 | #define GZ_NONE 0 160 | #define GZ_READ 7247 161 | #define GZ_WRITE 31153 162 | #define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ 163 | 164 | /* values for gz_state how */ 165 | #define LOOK 0 /* look for a gzip header */ 166 | #define COPY 1 /* copy input directly */ 167 | #define GZIP 2 /* decompress a gzip stream */ 168 | 169 | /* internal gzip file state data structure */ 170 | typedef struct { 171 | /* exposed contents for gzgetc() macro */ 172 | struct gzFile_s x; /* "x" for exposed */ 173 | /* x.have: number of bytes available at x.next */ 174 | /* x.next: next output data to deliver or write */ 175 | /* x.pos: current position in uncompressed data */ 176 | /* used for both reading and writing */ 177 | int mode; /* see gzip modes above */ 178 | int fd; /* file descriptor */ 179 | char *path; /* path or fd for error messages */ 180 | unsigned size; /* buffer size, zero if not allocated yet */ 181 | unsigned want; /* requested buffer size, default is GZBUFSIZE */ 182 | unsigned char *in; /* input buffer (double-sized when writing) */ 183 | unsigned char *out; /* output buffer (double-sized when reading) */ 184 | int direct; /* 0 if processing gzip, 1 if transparent */ 185 | /* just for reading */ 186 | int how; /* 0: get header, 1: copy, 2: decompress */ 187 | z_off64_t start; /* where the gzip data started, for rewinding */ 188 | int eof; /* true if end of input file reached */ 189 | int past; /* true if read requested past end */ 190 | /* just for writing */ 191 | int level; /* compression level */ 192 | int strategy; /* compression strategy */ 193 | /* seek request */ 194 | z_off64_t skip; /* amount to skip (already rewound if backwards) */ 195 | int seek; /* true if seek request pending */ 196 | /* error information */ 197 | int err; /* error code */ 198 | char *msg; /* error message */ 199 | /* zlib inflate or deflate stream */ 200 | z_stream strm; /* stream structure in-place (not a pointer) */ 201 | } gz_state; 202 | typedef gz_state FAR *gz_statep; 203 | 204 | /* shared functions */ 205 | void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); 206 | #if defined UNDER_CE 207 | char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); 208 | #endif 209 | 210 | /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t 211 | value -- needed when comparing unsigned to z_off64_t, which is signed 212 | (possible z_off64_t types off_t, off64_t, and long are all signed) */ 213 | #ifdef INT_MAX 214 | # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) 215 | #else 216 | unsigned ZLIB_INTERNAL gz_intmax OF((void)); 217 | # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) 218 | #endif 219 | -------------------------------------------------------------------------------- /deps/zlib/inffast.h: -------------------------------------------------------------------------------- 1 | /* inffast.h -- header to use inffast.c 2 | * Copyright (C) 1995-2003, 2010 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); 12 | -------------------------------------------------------------------------------- /deps/zlib/inffixed.h: -------------------------------------------------------------------------------- 1 | /* inffixed.h -- table for decoding fixed codes 2 | * Generated automatically by makefixed(). 3 | */ 4 | 5 | /* WARNING: this file should *not* be used by applications. 6 | It is part of the implementation of this library and is 7 | subject to change. Applications should only use zlib.h. 8 | */ 9 | 10 | static const code lenfix[512] = { 11 | {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, 12 | {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, 13 | {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, 14 | {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, 15 | {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, 16 | {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, 17 | {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, 18 | {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, 19 | {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, 20 | {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, 21 | {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, 22 | {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, 23 | {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, 24 | {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, 25 | {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, 26 | {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, 27 | {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, 28 | {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, 29 | {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, 30 | {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, 31 | {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, 32 | {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, 33 | {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, 34 | {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, 35 | {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, 36 | {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, 37 | {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, 38 | {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, 39 | {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, 40 | {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, 41 | {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, 42 | {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, 43 | {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, 44 | {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, 45 | {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, 46 | {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, 47 | {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, 48 | {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, 49 | {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, 50 | {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, 51 | {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, 52 | {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, 53 | {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, 54 | {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, 55 | {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, 56 | {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, 57 | {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, 58 | {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, 59 | {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, 60 | {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, 61 | {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, 62 | {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, 63 | {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, 64 | {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, 65 | {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, 66 | {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, 67 | {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, 68 | {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, 69 | {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, 70 | {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, 71 | {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, 72 | {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, 73 | {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, 74 | {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, 75 | {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, 76 | {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, 77 | {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, 78 | {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, 79 | {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, 80 | {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, 81 | {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, 82 | {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, 83 | {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, 84 | {0,9,255} 85 | }; 86 | 87 | static const code distfix[32] = { 88 | {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, 89 | {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, 90 | {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, 91 | {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, 92 | {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, 93 | {22,5,193},{64,5,0} 94 | }; 95 | -------------------------------------------------------------------------------- /deps/zlib/inflate.h: -------------------------------------------------------------------------------- 1 | /* inflate.h -- internal inflate state definition 2 | * Copyright (C) 1995-2016 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* define NO_GZIP when compiling if you want to disable gzip header and 12 | trailer decoding by inflate(). NO_GZIP would be used to avoid linking in 13 | the crc code when it is not needed. For shared libraries, gzip decoding 14 | should be left enabled. */ 15 | #ifndef NO_GZIP 16 | # define GUNZIP 17 | #endif 18 | 19 | /* Possible inflate modes between inflate() calls */ 20 | typedef enum { 21 | HEAD = 16180, /* i: waiting for magic header */ 22 | FLAGS, /* i: waiting for method and flags (gzip) */ 23 | TIME, /* i: waiting for modification time (gzip) */ 24 | OS, /* i: waiting for extra flags and operating system (gzip) */ 25 | EXLEN, /* i: waiting for extra length (gzip) */ 26 | EXTRA, /* i: waiting for extra bytes (gzip) */ 27 | NAME, /* i: waiting for end of file name (gzip) */ 28 | COMMENT, /* i: waiting for end of comment (gzip) */ 29 | HCRC, /* i: waiting for header crc (gzip) */ 30 | DICTID, /* i: waiting for dictionary check value */ 31 | DICT, /* waiting for inflateSetDictionary() call */ 32 | TYPE, /* i: waiting for type bits, including last-flag bit */ 33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ 34 | STORED, /* i: waiting for stored size (length and complement) */ 35 | COPY_, /* i/o: same as COPY below, but only first time in */ 36 | COPY, /* i/o: waiting for input or output to copy stored block */ 37 | TABLE, /* i: waiting for dynamic block table lengths */ 38 | LENLENS, /* i: waiting for code length code lengths */ 39 | CODELENS, /* i: waiting for length/lit and distance code lengths */ 40 | LEN_, /* i: same as LEN below, but only first time in */ 41 | LEN, /* i: waiting for length/lit/eob code */ 42 | LENEXT, /* i: waiting for length extra bits */ 43 | DIST, /* i: waiting for distance code */ 44 | DISTEXT, /* i: waiting for distance extra bits */ 45 | MATCH, /* o: waiting for output space to copy string */ 46 | LIT, /* o: waiting for output space to write literal */ 47 | CHECK, /* i: waiting for 32-bit check value */ 48 | LENGTH, /* i: waiting for 32-bit length (gzip) */ 49 | DONE, /* finished check, done -- remain here until reset */ 50 | BAD, /* got a data error -- remain here until reset */ 51 | MEM, /* got an inflate() memory error -- remain here until reset */ 52 | SYNC /* looking for synchronization bytes to restart inflate() */ 53 | } inflate_mode; 54 | 55 | /* 56 | State transitions between above modes - 57 | 58 | (most modes can go to BAD or MEM on error -- not shown for clarity) 59 | 60 | Process header: 61 | HEAD -> (gzip) or (zlib) or (raw) 62 | (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> 63 | HCRC -> TYPE 64 | (zlib) -> DICTID or TYPE 65 | DICTID -> DICT -> TYPE 66 | (raw) -> TYPEDO 67 | Read deflate blocks: 68 | TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK 69 | STORED -> COPY_ -> COPY -> TYPE 70 | TABLE -> LENLENS -> CODELENS -> LEN_ 71 | LEN_ -> LEN 72 | Read deflate codes in fixed or dynamic block: 73 | LEN -> LENEXT or LIT or TYPE 74 | LENEXT -> DIST -> DISTEXT -> MATCH -> LEN 75 | LIT -> LEN 76 | Process trailer: 77 | CHECK -> LENGTH -> DONE 78 | */ 79 | 80 | /* State maintained between inflate() calls -- approximately 7K bytes, not 81 | including the allocated sliding window, which is up to 32K bytes. */ 82 | struct inflate_state { 83 | z_streamp strm; /* pointer back to this zlib stream */ 84 | inflate_mode mode; /* current inflate mode */ 85 | int last; /* true if processing last block */ 86 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip, 87 | bit 2 true to validate check value */ 88 | int havedict; /* true if dictionary provided */ 89 | int flags; /* gzip header method and flags (0 if zlib) */ 90 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ 91 | unsigned long check; /* protected copy of check value */ 92 | unsigned long total; /* protected copy of output count */ 93 | gz_headerp head; /* where to save gzip header information */ 94 | /* sliding window */ 95 | unsigned wbits; /* log base 2 of requested window size */ 96 | unsigned wsize; /* window size or zero if not using window */ 97 | unsigned whave; /* valid bytes in the window */ 98 | unsigned wnext; /* window write index */ 99 | unsigned char FAR *window; /* allocated sliding window, if needed */ 100 | /* bit accumulator */ 101 | unsigned long hold; /* input bit accumulator */ 102 | unsigned bits; /* number of bits in "in" */ 103 | /* for string and stored block copying */ 104 | unsigned length; /* literal or length of data to copy */ 105 | unsigned offset; /* distance back to copy string from */ 106 | /* for table and code decoding */ 107 | unsigned extra; /* extra bits needed */ 108 | /* fixed and dynamic code tables */ 109 | code const FAR *lencode; /* starting table for length/literal codes */ 110 | code const FAR *distcode; /* starting table for distance codes */ 111 | unsigned lenbits; /* index bits for lencode */ 112 | unsigned distbits; /* index bits for distcode */ 113 | /* dynamic table building */ 114 | unsigned ncode; /* number of code length code lengths */ 115 | unsigned nlen; /* number of length code lengths */ 116 | unsigned ndist; /* number of distance code lengths */ 117 | unsigned have; /* number of code lengths in lens[] */ 118 | code FAR *next; /* next available space in codes[] */ 119 | unsigned short lens[320]; /* temporary storage for code lengths */ 120 | unsigned short work[288]; /* work area for code table building */ 121 | code codes[ENOUGH]; /* space for code tables */ 122 | int sane; /* if false, allow invalid distance too far */ 123 | int back; /* bits back of last unprocessed length/lit */ 124 | unsigned was; /* initial length of match */ 125 | }; 126 | -------------------------------------------------------------------------------- /deps/zlib/inftrees.h: -------------------------------------------------------------------------------- 1 | /* inftrees.h -- header to use inftrees.c 2 | * Copyright (C) 1995-2005, 2010 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* Structure for decoding tables. Each entry provides either the 12 | information needed to do the operation requested by the code that 13 | indexed that table entry, or it provides a pointer to another 14 | table that indexes more bits of the code. op indicates whether 15 | the entry is a pointer to another table, a literal, a length or 16 | distance, an end-of-block, or an invalid code. For a table 17 | pointer, the low four bits of op is the number of index bits of 18 | that table. For a length or distance, the low four bits of op 19 | is the number of extra bits to get after the code. bits is 20 | the number of bits in this code or part of the code to drop off 21 | of the bit buffer. val is the actual byte to output in the case 22 | of a literal, the base length or distance, or the offset from 23 | the current table to the next table. Each entry is four bytes. */ 24 | typedef struct { 25 | unsigned char op; /* operation, extra bits, table bits */ 26 | unsigned char bits; /* bits in this part of the code */ 27 | unsigned short val; /* offset in table or code value */ 28 | } code; 29 | 30 | /* op values as set by inflate_table(): 31 | 00000000 - literal 32 | 0000tttt - table link, tttt != 0 is the number of table index bits 33 | 0001eeee - length or distance, eeee is the number of extra bits 34 | 01100000 - end of block 35 | 01000000 - invalid code 36 | */ 37 | 38 | /* Maximum size of the dynamic table. The maximum number of code structures is 39 | 1444, which is the sum of 852 for literal/length codes and 592 for distance 40 | codes. These values were found by exhaustive searches using the program 41 | examples/enough.c found in the zlib distribtution. The arguments to that 42 | program are the number of symbols, the initial root table size, and the 43 | maximum bit length of a code. "enough 286 9 15" for literal/length codes 44 | returns returns 852, and "enough 30 6 15" for distance codes returns 592. 45 | The initial root table size (9 or 6) is found in the fifth argument of the 46 | inflate_table() calls in inflate.c and infback.c. If the root table size is 47 | changed, then these maximum sizes would be need to be recalculated and 48 | updated. */ 49 | #define ENOUGH_LENS 852 50 | #define ENOUGH_DISTS 592 51 | #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) 52 | 53 | /* Type of code to build for inflate_table() */ 54 | typedef enum { 55 | CODES, 56 | LENS, 57 | DISTS 58 | } codetype; 59 | 60 | int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, 61 | unsigned codes, code FAR * FAR *table, 62 | unsigned FAR *bits, unsigned short FAR *work)); 63 | -------------------------------------------------------------------------------- /deps/zlib/trees.h: -------------------------------------------------------------------------------- 1 | /* header created automatically with -DGEN_TREES_H */ 2 | 3 | local const ct_data static_ltree[L_CODES+2] = { 4 | {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, 5 | {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, 6 | {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, 7 | {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, 8 | {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, 9 | {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, 10 | {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, 11 | {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, 12 | {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, 13 | {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, 14 | {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, 15 | {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, 16 | {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, 17 | {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, 18 | {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, 19 | {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, 20 | {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, 21 | {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, 22 | {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, 23 | {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, 24 | {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, 25 | {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, 26 | {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, 27 | {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, 28 | {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, 29 | {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, 30 | {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, 31 | {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, 32 | {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, 33 | {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, 34 | {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, 35 | {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, 36 | {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, 37 | {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, 38 | {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, 39 | {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, 40 | {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, 41 | {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, 42 | {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, 43 | {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, 44 | {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, 45 | {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, 46 | {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, 47 | {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, 48 | {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, 49 | {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, 50 | {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, 51 | {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, 52 | {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, 53 | {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, 54 | {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, 55 | {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, 56 | {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, 57 | {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, 58 | {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, 59 | {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, 60 | {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, 61 | {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} 62 | }; 63 | 64 | local const ct_data static_dtree[D_CODES] = { 65 | {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, 66 | {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, 67 | {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, 68 | {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, 69 | {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, 70 | {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} 71 | }; 72 | 73 | const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { 74 | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 75 | 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 76 | 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 77 | 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 78 | 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 79 | 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 80 | 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 81 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 82 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 83 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 84 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 85 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 86 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 87 | 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 88 | 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 89 | 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 90 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 91 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 92 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 93 | 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 94 | 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 95 | 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 96 | 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 97 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 98 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 99 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 100 | }; 101 | 102 | const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { 103 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 104 | 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 105 | 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 106 | 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 107 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 108 | 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 109 | 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 110 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 111 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 112 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 113 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 114 | 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 115 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 116 | }; 117 | 118 | local const int base_length[LENGTH_CODES] = { 119 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 120 | 64, 80, 96, 112, 128, 160, 192, 224, 0 121 | }; 122 | 123 | local const int base_dist[D_CODES] = { 124 | 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 125 | 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 126 | 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 127 | }; 128 | 129 | -------------------------------------------------------------------------------- /deps/zlib/zutil.h: -------------------------------------------------------------------------------- 1 | /* zutil.h -- internal interface and configuration of the compression library 2 | * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* @(#) $Id$ */ 12 | 13 | #ifndef ZUTIL_H 14 | #define ZUTIL_H 15 | 16 | #ifdef HAVE_HIDDEN 17 | # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) 18 | #else 19 | # define ZLIB_INTERNAL 20 | #endif 21 | 22 | #include "zlib.h" 23 | 24 | #if defined(STDC) && !defined(Z_SOLO) 25 | # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) 26 | # include 27 | # endif 28 | # include 29 | # include 30 | #endif 31 | 32 | #ifdef Z_SOLO 33 | typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ 34 | #endif 35 | 36 | #ifndef local 37 | # define local static 38 | #endif 39 | /* since "static" is used to mean two completely different things in C, we 40 | define "local" for the non-static meaning of "static", for readability 41 | (compile with -Dlocal if your debugger can't find static symbols) */ 42 | 43 | typedef unsigned char uch; 44 | typedef uch FAR uchf; 45 | typedef unsigned short ush; 46 | typedef ush FAR ushf; 47 | typedef unsigned long ulg; 48 | 49 | extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ 50 | /* (size given to avoid silly warnings with Visual C++) */ 51 | 52 | #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] 53 | 54 | #define ERR_RETURN(strm,err) \ 55 | return (strm->msg = ERR_MSG(err), (err)) 56 | /* To be used only when the state is known to be valid */ 57 | 58 | /* common constants */ 59 | 60 | #ifndef DEF_WBITS 61 | # define DEF_WBITS MAX_WBITS 62 | #endif 63 | /* default windowBits for decompression. MAX_WBITS is for compression only */ 64 | 65 | #if MAX_MEM_LEVEL >= 8 66 | # define DEF_MEM_LEVEL 8 67 | #else 68 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL 69 | #endif 70 | /* default memLevel */ 71 | 72 | #define STORED_BLOCK 0 73 | #define STATIC_TREES 1 74 | #define DYN_TREES 2 75 | /* The three kinds of block type */ 76 | 77 | #define MIN_MATCH 3 78 | #define MAX_MATCH 258 79 | /* The minimum and maximum match lengths */ 80 | 81 | #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ 82 | 83 | /* target dependencies */ 84 | 85 | #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) 86 | # define OS_CODE 0x00 87 | # ifndef Z_SOLO 88 | # if defined(__TURBOC__) || defined(__BORLANDC__) 89 | # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) 90 | /* Allow compilation with ANSI keywords only enabled */ 91 | void _Cdecl farfree( void *block ); 92 | void *_Cdecl farmalloc( unsigned long nbytes ); 93 | # else 94 | # include 95 | # endif 96 | # else /* MSC or DJGPP */ 97 | # include 98 | # endif 99 | # endif 100 | #endif 101 | 102 | #ifdef AMIGA 103 | # define OS_CODE 1 104 | #endif 105 | 106 | #if defined(VAXC) || defined(VMS) 107 | # define OS_CODE 2 108 | # define F_OPEN(name, mode) \ 109 | fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") 110 | #endif 111 | 112 | #ifdef __370__ 113 | # if __TARGET_LIB__ < 0x20000000 114 | # define OS_CODE 4 115 | # elif __TARGET_LIB__ < 0x40000000 116 | # define OS_CODE 11 117 | # else 118 | # define OS_CODE 8 119 | # endif 120 | #endif 121 | 122 | #if defined(ATARI) || defined(atarist) 123 | # define OS_CODE 5 124 | #endif 125 | 126 | #ifdef OS2 127 | # define OS_CODE 6 128 | # if defined(M_I86) && !defined(Z_SOLO) 129 | # include 130 | # endif 131 | #endif 132 | 133 | #if defined(MACOS) || defined(TARGET_OS_MAC) 134 | # define OS_CODE 7 135 | # ifndef Z_SOLO 136 | # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 137 | # include /* for fdopen */ 138 | # else 139 | # ifndef fdopen 140 | # define fdopen(fd,mode) NULL /* No fdopen() */ 141 | # endif 142 | # endif 143 | # endif 144 | #endif 145 | 146 | #ifdef __acorn 147 | # define OS_CODE 13 148 | #endif 149 | 150 | #if defined(WIN32) && !defined(__CYGWIN__) 151 | # define OS_CODE 10 152 | #endif 153 | 154 | #ifdef _BEOS_ 155 | # define OS_CODE 16 156 | #endif 157 | 158 | #ifdef __TOS_OS400__ 159 | # define OS_CODE 18 160 | #endif 161 | 162 | #ifdef __APPLE__ 163 | # define OS_CODE 19 164 | #endif 165 | 166 | #if defined(_BEOS_) || defined(RISCOS) 167 | # define fdopen(fd,mode) NULL /* No fdopen() */ 168 | #endif 169 | 170 | #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX 171 | # if defined(_WIN32_WCE) 172 | # define fdopen(fd,mode) NULL /* No fdopen() */ 173 | # ifndef _PTRDIFF_T_DEFINED 174 | typedef int ptrdiff_t; 175 | # define _PTRDIFF_T_DEFINED 176 | # endif 177 | # else 178 | # define fdopen(fd,type) _fdopen(fd,type) 179 | # endif 180 | #endif 181 | 182 | #if defined(__BORLANDC__) && !defined(MSDOS) 183 | #pragma warn -8004 184 | #pragma warn -8008 185 | #pragma warn -8066 186 | #endif 187 | 188 | /* provide prototypes for these when building zlib without LFS */ 189 | #if !defined(_WIN32) && \ 190 | (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) 191 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); 192 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); 193 | #endif 194 | 195 | /* common defaults */ 196 | 197 | #ifndef OS_CODE 198 | # define OS_CODE 3 /* assume Unix */ 199 | #endif 200 | 201 | #ifndef F_OPEN 202 | # define F_OPEN(name, mode) fopen((name), (mode)) 203 | #endif 204 | 205 | /* functions */ 206 | 207 | #if defined(pyr) || defined(Z_SOLO) 208 | # define NO_MEMCPY 209 | #endif 210 | #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) 211 | /* Use our own functions for small and medium model with MSC <= 5.0. 212 | * You may have to use the same strategy for Borland C (untested). 213 | * The __SC__ check is for Symantec. 214 | */ 215 | # define NO_MEMCPY 216 | #endif 217 | #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) 218 | # define HAVE_MEMCPY 219 | #endif 220 | #ifdef HAVE_MEMCPY 221 | # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ 222 | # define zmemcpy _fmemcpy 223 | # define zmemcmp _fmemcmp 224 | # define zmemzero(dest, len) _fmemset(dest, 0, len) 225 | # else 226 | # define zmemcpy memcpy 227 | # define zmemcmp memcmp 228 | # define zmemzero(dest, len) memset(dest, 0, len) 229 | # endif 230 | #else 231 | void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); 232 | int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); 233 | void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); 234 | #endif 235 | 236 | /* Diagnostic functions */ 237 | #ifdef ZLIB_DEBUG 238 | # include 239 | extern int ZLIB_INTERNAL z_verbose; 240 | extern void ZLIB_INTERNAL z_error OF((char *m)); 241 | # define Assert(cond,msg) {if(!(cond)) z_error(msg);} 242 | # define Trace(x) {if (z_verbose>=0) fprintf x ;} 243 | # define Tracev(x) {if (z_verbose>0) fprintf x ;} 244 | # define Tracevv(x) {if (z_verbose>1) fprintf x ;} 245 | # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} 246 | # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} 247 | #else 248 | # define Assert(cond,msg) 249 | # define Trace(x) 250 | # define Tracev(x) 251 | # define Tracevv(x) 252 | # define Tracec(c,x) 253 | # define Tracecv(c,x) 254 | #endif 255 | 256 | #ifndef Z_SOLO 257 | voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, 258 | unsigned size)); 259 | void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); 260 | #endif 261 | 262 | #define ZALLOC(strm, items, size) \ 263 | (*((strm)->zalloc))((strm)->opaque, (items), (size)) 264 | #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) 265 | #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} 266 | 267 | /* Reverse the bytes in a 32-bit value */ 268 | #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ 269 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) 270 | 271 | #endif /* ZUTIL_H */ 272 | -------------------------------------------------------------------------------- /dexgraph-reverse-engineering.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxence-ho/DexGraph/dced4f7ee0a270212fb31afc40eab514a9aa0352/dexgraph-reverse-engineering.pdf -------------------------------------------------------------------------------- /include/Dexdump/OpCodeNames.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Dalvik opcode names. 18 | */ 19 | #ifndef _DEXDUMP_OPCODENAMES 20 | #define _DEXDUMP_OPCODENAMES 21 | 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | const char* getOpcodeName(OpCode op); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif /*_DEXDUMP_OPCODENAMES*/ 35 | -------------------------------------------------------------------------------- /include/TreeConstructor/FmtDot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | namespace Fmt 7 | { 8 | namespace Dot 9 | { 10 | std::string get_header(TreeConstructor::Node const& node); 11 | std::string get_footer(); 12 | void dump_tree(TreeConstructor::Node const& current_node); 13 | std::string dump_single_node(TreeConstructor::NodeSPtr const node); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /include/TreeConstructor/FmtEdg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | namespace Fmt 7 | { 8 | namespace Edg 9 | { 10 | void dump_all( 11 | std::vector const& nodesptr_vec, 12 | std::vector> const& edges_vec); 14 | 15 | std::pair>> 17 | dump_single_node(TreeConstructor::NodeSPtr const node); 18 | 19 | void dump_edg_body( 20 | std::vector const& nodesptr_vec, 21 | std::vector> const& edges_vec); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /include/TreeConstructor/OpcodeType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | enum class OpCodeType 8 | { 9 | SEQ, 10 | IF, 11 | CALL, 12 | NEW, 13 | JMP, 14 | SWITCH, 15 | THROW, 16 | SYSCALL, 17 | RET, 18 | }; 19 | 20 | std::string OpCodeTypeToStr(OpCodeType const& opcodetype); 21 | 22 | namespace OpCodeClassifier 23 | { 24 | bool is_if(OpCode const& candidate); 25 | bool is_call(OpCode const& candidate); 26 | bool is_jmp(OpCode const& candidate); 27 | bool is_switch(OpCode const& candidate); 28 | bool is_exception(OpCode const& candidate); 29 | bool is_ret(OpCode const& candidate); 30 | bool is_new(OpCode const & candidate); 31 | OpCodeType get_opcode_type(OpCode const& opcode); 32 | } 33 | -------------------------------------------------------------------------------- /include/TreeConstructor/PackedSwitchPayload.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct PackedSwitchPayload 6 | { 7 | unsigned short const ident = 0x0100; 8 | unsigned short size = 0; 9 | int first_key = 0; 10 | std::vector targets; 11 | }; 12 | -------------------------------------------------------------------------------- /include/TreeConstructor/SparseSwitchPayload.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct SparseSwitchPayload 6 | { 7 | unsigned short const ident = 0x0200; 8 | unsigned short size = 0; 9 | std::vector keys; 10 | std::vector targets; 11 | }; 12 | -------------------------------------------------------------------------------- /include/TreeConstructor/TCHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define tc_str_format(buff_str, ...) { \ 11 | char buff[256]; \ 12 | snprintf(buff, 256, __VA_ARGS__); \ 13 | buff_str = buff; \ 14 | } \ 15 | 16 | #define tc_print(string) { \ 17 | printf("%s", string.c_str()); \ 18 | } \ 19 | 20 | namespace TreeConstructor 21 | { 22 | namespace Helper 23 | { 24 | auto constexpr classlist_filename = "class_list.txt"; 25 | auto constexpr graph_filename = "graph.dot"; 26 | 27 | void write(std::basic_string const& filename, 28 | std::basic_string const& content); 29 | 30 | std::string get_formated_hex(int const& int_value); 31 | } 32 | 33 | // Switch Payload getters 34 | PackedSwitchPayload get_packed_switch_payload(int swicth_offset, 35 | intptr_t payload_addr); 36 | 37 | SparseSwitchPayload get_sparse_switch_offsets(int swicth_offset, 38 | intptr_t payload_addr); 39 | 40 | // MethodInfo constructor 41 | struct MethodInfo 42 | { 43 | uint32_t method_idx = 0; 44 | 45 | uint16_t class_idx = 0; 46 | uint16_t proto_idx = 0; 47 | uint32_t name_idx = 0; 48 | 49 | std::string class_descriptor; 50 | std::string name; 51 | std::string signature; 52 | 53 | friend bool operator ==(MethodInfo const& lhs, 54 | MethodInfo const& rhs) 55 | { 56 | return lhs.method_idx == rhs.method_idx; 57 | } 58 | 59 | friend bool operator < (MethodInfo const& lhs, 60 | MethodInfo const& rhs) 61 | { 62 | return lhs.method_idx < rhs.method_idx; 63 | } 64 | }; 65 | 66 | 67 | MethodInfo get_method_info(DexFile const& dex_file, 68 | uint32_t const& method_idx); 69 | } 70 | -------------------------------------------------------------------------------- /include/TreeConstructor/TCNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace TreeConstructor 14 | { 15 | struct Node; 16 | typedef std::shared_ptr NodeSPtr; 17 | struct Node 18 | { 19 | uint32_t baseAddr = 0; 20 | uint16_t size = 0; 21 | OpCode opcode = static_cast(0x00); 22 | uint32_t intern_offset = 0; 23 | MethodInfo called_method_info; 24 | std::vector opt_arg_offset; 25 | OpCodeType opcode_type; 26 | std::vector> next_nodes; 27 | 28 | Node() {}; 29 | Node(uint32_t const& _baseAddr, 30 | uint16_t const& _size, 31 | OpCode const& _opcode, 32 | MethodInfo const& _called_method_info, 33 | uint32_t const& _internal_offset, 34 | std::vector const& _opt_arg_offset); 35 | 36 | int count_node() const; 37 | }; 38 | 39 | typedef std::function FmtLambda; 40 | typedef std::function>>(NodeSPtr const&)> BinaryFmtLambda; 41 | std::string dot_traversal(Node const& node, 42 | FmtLambda dump_format_method); 43 | std::pair, std::vector>> 44 | binary_traversal(Node const& node, BinaryFmtLambda dump_format_method); 45 | 46 | 47 | NodeSPtr construct_node_from_vec(std::vector const &nodeptr_vector); 48 | 49 | std::vector get_method_call_nodes( 50 | std::vector const &node_vec); 51 | 52 | void process_calls(std::map &map, 53 | std::vector &call_node_vec); 54 | } 55 | -------------------------------------------------------------------------------- /include/libdex/CmdUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Access .dex (Dalvik Executable Format) files. The code here assumes that 18 | * the DEX file has been rewritten (byte-swapped, word-aligned) and that 19 | * the contents can be directly accessed as a collection of C arrays. Please 20 | * see docs/dalvik/dex-format.html for a detailed description. 21 | * 22 | * The structure and field names were chosen to match those in the DEX spec. 23 | * 24 | * It's generally assumed that the DEX file will be stored in shared memory, 25 | * obviating the need to copy code and constant pool entries into newly 26 | * allocated storage. Maintaining local pointers to items in the shared area 27 | * is valid and encouraged. 28 | * 29 | * All memory-mapped structures are 32-bit aligned unless otherwise noted. 30 | */ 31 | #ifndef _LIBDEX_CMDUTILS 32 | #define _LIBDEX_CMDUTILS 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /* encode the result of unzipping to a file */ 39 | typedef enum UnzipToFileResult { 40 | kUTFRSuccess = 0, 41 | kUTFRGenericFailure, 42 | kUTFRBadArgs, 43 | kUTFRNotZip, 44 | kUTFRNoClassesDex, 45 | kUTFROutputFileProblem, 46 | kUTFRBadZip, 47 | } UnzipToFileResult; 48 | 49 | /* 50 | * Map the specified DEX file, possibly after expanding it into a temp file 51 | * from a Jar. Pass in a MemMapping struct to hold the info. 52 | * 53 | * This is intended for use by tools (e.g. dexdump) that need to get a 54 | * read-only copy of a DEX file that could be in a number of different states. 55 | * 56 | * If "tempFileName" is NULL, a default value is used. The temp file is 57 | * deleted after the map succeeds. 58 | * 59 | * Returns 0 on success. 60 | */ 61 | UnzipToFileResult dexOpenAndMap(const char* fileName, const char* tempFileName, 62 | MemMapping* pMap, bool quiet); 63 | 64 | /* 65 | * Utility function to open a Zip archive, find "classes.dex", and extract 66 | * it to a file. 67 | */ 68 | UnzipToFileResult dexUnzipToFile(const char* zipFileName, 69 | const char* outFileName, bool quiet); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif /*_LIBDEX_CMDUTILS*/ 76 | -------------------------------------------------------------------------------- /include/libdex/DexCatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions for dealing with try-catch info. 19 | */ 20 | 21 | #ifndef _LIBDEX_DEXCATCH 22 | #define _LIBDEX_DEXCATCH 23 | 24 | #include "DexFile.h" 25 | #include "Leb128.h" 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* 32 | * Catch handler entry, used while iterating over catch_handler_items. 33 | */ 34 | typedef struct DexCatchHandler { 35 | u4 typeIdx; /* type index of the caught exception type */ 36 | u4 address; /* handler address */ 37 | } DexCatchHandler; 38 | 39 | /* Get the first handler offset for the given DexCode. 40 | * It's not 0 because the handlers list is prefixed with its size 41 | * (in entries) as a uleb128. */ 42 | u4 dexGetFirstHandlerOffset(const DexCode* pCode); 43 | 44 | /* Get count of handler lists for the given DexCode. */ 45 | u4 dexGetHandlersSize(const DexCode* pCode); 46 | 47 | /* 48 | * Iterator over catch handler data. This structure should be treated as 49 | * opaque. 50 | */ 51 | typedef struct DexCatchIterator { 52 | const u1* pEncodedData; 53 | bool catchesAll; 54 | u4 countRemaining; 55 | DexCatchHandler handler; 56 | } DexCatchIterator; 57 | 58 | /* Initialize a DexCatchIterator to emptiness. This mostly exists to 59 | * squelch innocuous warnings. */ 60 | DEX_INLINE void dexCatchIteratorClear(DexCatchIterator* pIterator) { 61 | pIterator->pEncodedData = NULL; 62 | pIterator->catchesAll = false; 63 | pIterator->countRemaining = 0; 64 | pIterator->handler.typeIdx = 0; 65 | pIterator->handler.address = 0; 66 | } 67 | 68 | /* Initialize a DexCatchIterator with a direct pointer to encoded handlers. */ 69 | DEX_INLINE void dexCatchIteratorInitToPointer(DexCatchIterator* pIterator, 70 | const u1* pEncodedData) 71 | { 72 | s4 count = readSignedLeb128(&pEncodedData); 73 | 74 | if (count <= 0) { 75 | pIterator->catchesAll = true; 76 | count = -count; 77 | } else { 78 | pIterator->catchesAll = false; 79 | } 80 | 81 | pIterator->pEncodedData = pEncodedData; 82 | pIterator->countRemaining = count; 83 | } 84 | 85 | /* Initialize a DexCatchIterator to a particular handler offset. */ 86 | DEX_INLINE void dexCatchIteratorInit(DexCatchIterator* pIterator, 87 | const DexCode* pCode, u4 offset) 88 | { 89 | dexCatchIteratorInitToPointer(pIterator, 90 | dexGetCatchHandlerData(pCode) + offset); 91 | } 92 | 93 | /* Get the next item from a DexCatchIterator. Returns NULL if at end. */ 94 | DEX_INLINE DexCatchHandler* dexCatchIteratorNext(DexCatchIterator* pIterator) { 95 | if (pIterator->countRemaining == 0) { 96 | if (! pIterator->catchesAll) { 97 | return NULL; 98 | } 99 | 100 | pIterator->catchesAll = false; 101 | pIterator->handler.typeIdx = kDexNoIndex; 102 | } else { 103 | u4 typeIdx = readUnsignedLeb128(&pIterator->pEncodedData); 104 | pIterator->handler.typeIdx = typeIdx; 105 | pIterator->countRemaining--; 106 | } 107 | 108 | pIterator->handler.address = readUnsignedLeb128(&pIterator->pEncodedData); 109 | return &pIterator->handler; 110 | } 111 | 112 | /* Get the handler offset just past the end of the one just iterated over. 113 | * This ends the iteration if it wasn't already. */ 114 | u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator, 115 | const DexCode* pCode); 116 | 117 | /* Helper for dexFindCatchHandler(). Do not call directly. */ 118 | int dexFindCatchHandlerOffset0(u2 triesSize, const DexTry* pTries, 119 | u4 address); 120 | 121 | /* Find the handler associated with a given address, if any. 122 | * Initializes the given iterator and returns true if a match is 123 | * found. Returns false if there is no applicable handler. */ 124 | DEX_INLINE bool dexFindCatchHandler(DexCatchIterator *pIterator, 125 | const DexCode* pCode, u4 address) { 126 | u2 triesSize = pCode->triesSize; 127 | int offset = -1; 128 | 129 | // Short-circuit the overwhelmingly common cases. 130 | switch (triesSize) { 131 | case 0: { 132 | break; 133 | } 134 | case 1: { 135 | const DexTry* tries = dexGetTries(pCode); 136 | u4 start = tries[0].startAddr; 137 | 138 | if (address < start) { 139 | break; 140 | } 141 | 142 | u4 end = start + tries[0].insnCount; 143 | 144 | if (address >= end) { 145 | break; 146 | } 147 | 148 | offset = tries[0].handlerOff; 149 | break; 150 | } 151 | default: { 152 | offset = dexFindCatchHandlerOffset0(triesSize, dexGetTries(pCode), 153 | address); 154 | } 155 | } 156 | 157 | if (offset < 0) { 158 | dexCatchIteratorClear(pIterator); // This squelches warnings. 159 | return false; 160 | } else { 161 | dexCatchIteratorInit(pIterator, pCode, offset); 162 | return true; 163 | } 164 | } 165 | 166 | #ifdef __cplusplus 167 | } 168 | #endif 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /include/libdex/DexClass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions to deal with class definition structures in DEX files 19 | */ 20 | 21 | #ifndef _LIBDEX_DEXCLASS 22 | #define _LIBDEX_DEXCLASS 23 | 24 | #include "DexFile.h" 25 | #include "Leb128.h" 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* expanded form of a class_data_item header */ 32 | typedef struct DexClassDataHeader { 33 | u4 staticFieldsSize; 34 | u4 instanceFieldsSize; 35 | u4 directMethodsSize; 36 | u4 virtualMethodsSize; 37 | } DexClassDataHeader; 38 | 39 | /* expanded form of encoded_field */ 40 | typedef struct DexField { 41 | u4 fieldIdx; /* index to a field_id_item */ 42 | u4 accessFlags; 43 | } DexField; 44 | 45 | /* expanded form of encoded_method */ 46 | typedef struct DexMethod { 47 | u4 methodIdx; /* index to a method_id_item */ 48 | u4 accessFlags; 49 | u4 codeOff; /* file offset to a code_item */ 50 | } DexMethod; 51 | 52 | /* expanded form of class_data_item. Note: If a particular item is 53 | * absent (e.g., no static fields), then the corresponding pointer 54 | * is set to NULL. */ 55 | typedef struct DexClassData { 56 | DexClassDataHeader header; 57 | DexField* staticFields; 58 | DexField* instanceFields; 59 | DexMethod* directMethods; 60 | DexMethod* virtualMethods; 61 | } DexClassData; 62 | 63 | /* Read and verify the header of a class_data_item. This updates the 64 | * given data pointer to point past the end of the read data and 65 | * returns an "okay" flag (that is, false == failure). */ 66 | bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit, 67 | DexClassDataHeader *pHeader); 68 | 69 | /* Read and verify an encoded_field. This updates the 70 | * given data pointer to point past the end of the read data and 71 | * returns an "okay" flag (that is, false == failure). 72 | * 73 | * The lastIndex value should be set to 0 before the first field in 74 | * a list is read. It is updated as fields are read and used in the 75 | * decode process. 76 | * 77 | * The verification done by this function is of the raw data format 78 | * only; it does not verify that access flags or indices 79 | * are valid. */ 80 | bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit, 81 | DexField* pField, u4* lastIndex); 82 | 83 | /* Read and verify an encoded_method. This updates the 84 | * given data pointer to point past the end of the read data and 85 | * returns an "okay" flag (that is, false == failure). 86 | * 87 | * The lastIndex value should be set to 0 before the first method in 88 | * a list is read. It is updated as fields are read and used in the 89 | * decode process. 90 | * 91 | * The verification done by this function is of the raw data format 92 | * only; it does not verify that access flags, indices, or offsets 93 | * are valid. */ 94 | bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit, 95 | DexMethod* pMethod, u4* lastIndex); 96 | 97 | /* Read, verify, and return an entire class_data_item. This updates 98 | * the given data pointer to point past the end of the read data. This 99 | * function allocates a single chunk of memory for the result, which 100 | * must subsequently be free()d. This function returns NULL if there 101 | * was trouble parsing the data. If this function is passed NULL, it 102 | * returns an initialized empty DexClassData structure. 103 | * 104 | * The verification done by this function is of the raw data format 105 | * only; it does not verify that access flags, indices, or offsets 106 | * are valid. */ 107 | DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit); 108 | 109 | /* 110 | * Get the DexCode for a DexMethod. Returns NULL if the class is native 111 | * or abstract. 112 | */ 113 | DEX_INLINE const DexCode* dexGetCode(const DexFile* pDexFile, 114 | const DexMethod* pDexMethod) 115 | { 116 | if (pDexMethod->codeOff == 0) 117 | return NULL; 118 | return (const DexCode*) (pDexFile->baseAddr + pDexMethod->codeOff); 119 | } 120 | 121 | 122 | /* Read the header of a class_data_item without verification. This 123 | * updates the given data pointer to point past the end of the read 124 | * data. */ 125 | DEX_INLINE void dexReadClassDataHeader(const u1** pData, 126 | DexClassDataHeader *pHeader) { 127 | pHeader->staticFieldsSize = readUnsignedLeb128(pData); 128 | pHeader->instanceFieldsSize = readUnsignedLeb128(pData); 129 | pHeader->directMethodsSize = readUnsignedLeb128(pData); 130 | pHeader->virtualMethodsSize = readUnsignedLeb128(pData); 131 | } 132 | 133 | /* Read an encoded_field without verification. This updates the 134 | * given data pointer to point past the end of the read data. 135 | * 136 | * The lastIndex value should be set to 0 before the first field in 137 | * a list is read. It is updated as fields are read and used in the 138 | * decode process. 139 | */ 140 | DEX_INLINE void dexReadClassDataField(const u1** pData, DexField* pField, 141 | u4* lastIndex) { 142 | u4 index = *lastIndex + readUnsignedLeb128(pData); 143 | 144 | pField->accessFlags = readUnsignedLeb128(pData); 145 | pField->fieldIdx = index; 146 | *lastIndex = index; 147 | } 148 | 149 | /* Read an encoded_method without verification. This updates the 150 | * given data pointer to point past the end of the read data. 151 | * 152 | * The lastIndex value should be set to 0 before the first method in 153 | * a list is read. It is updated as fields are read and used in the 154 | * decode process. 155 | */ 156 | DEX_INLINE void dexReadClassDataMethod(const u1** pData, DexMethod* pMethod, 157 | u4* lastIndex) { 158 | u4 index = *lastIndex + readUnsignedLeb128(pData); 159 | 160 | pMethod->accessFlags = readUnsignedLeb128(pData); 161 | pMethod->codeOff = readUnsignedLeb128(pData); 162 | pMethod->methodIdx = index; 163 | *lastIndex = index; 164 | } 165 | 166 | #ifdef __cplusplus 167 | } 168 | #endif 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /include/libdex/DexDataMap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Verification-time map of data section items 19 | */ 20 | 21 | #ifndef _LIBDEX_DEXDATAMAP 22 | #define _LIBDEX_DEXDATAMAP 23 | 24 | #include "DexFile.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | typedef struct DexDataMap { 31 | u4 count; /* number of items currently in the map */ 32 | u4 max; /* maximum number of items that may be held */ 33 | u4* offsets; /* array of item offsets */ 34 | u2* types; /* corresponding array of item types */ 35 | } DexDataMap; 36 | 37 | /* 38 | * Allocate and initialize a DexDataMap. Returns NULL on failure. 39 | */ 40 | DexDataMap* dexDataMapAlloc(u4 maxCount); 41 | 42 | /* 43 | * Free a DexDataMap. 44 | */ 45 | void dexDataMapFree(DexDataMap* map); 46 | 47 | /* 48 | * Add a new element to the map. The offset must be greater than the 49 | * all previously added offsets. 50 | */ 51 | void dexDataMapAdd(DexDataMap* map, u4 offset, u2 type); 52 | 53 | /* 54 | * Get the type associated with the given offset. This returns -1 if 55 | * there is no entry for the given offset. 56 | */ 57 | int dexDataMapGet(DexDataMap* map, u4 offset); 58 | 59 | /* 60 | * Verify that there is an entry in the map, mapping the given offset to 61 | * the given type. This will return true if such an entry exists and 62 | * return false as well as log an error if not. 63 | */ 64 | bool dexDataMapVerify(DexDataMap* map, u4 offset, u2 type); 65 | 66 | /* 67 | * Like dexDataMapVerify(), but also accept a 0 offset as valid. 68 | */ 69 | DEX_INLINE bool dexDataMapVerify0Ok(DexDataMap* map, u4 offset, u2 type) { 70 | if (offset == 0) { 71 | return true; 72 | } 73 | 74 | return dexDataMapVerify(map, offset, type); 75 | } 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif /*_LIBDEX_DEXDATAMAP*/ 82 | -------------------------------------------------------------------------------- /include/libdex/DexProto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions for dealing with method prototypes 19 | */ 20 | 21 | #ifndef _LIBDEX_DEXPROTO 22 | #define _LIBDEX_DEXPROTO 23 | 24 | #include "DexFile.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* 31 | * Single-thread single-string cache. This structure holds a pointer to 32 | * a string which is semi-automatically manipulated by some of the 33 | * method prototype functions. Functions which use in this struct 34 | * generally return a string that is valid until the next 35 | * time the same DexStringCache is used. 36 | */ 37 | typedef struct DexStringCache { 38 | char* value; /* the latest value */ 39 | size_t allocatedSize; /* size of the allocated buffer, if allocated */ 40 | char buffer[120]; /* buffer used to hold small-enough results */ 41 | } DexStringCache; 42 | 43 | /* 44 | * Initialize the given DexStringCache. Use this function before passing 45 | * one into any other function. 46 | */ 47 | void dexStringCacheInit(DexStringCache* pCache); 48 | 49 | /* 50 | * Release the allocated contents of the given DexStringCache, if any. 51 | * Use this function after your last use of a DexStringCache. 52 | */ 53 | void dexStringCacheRelease(DexStringCache* pCache); 54 | 55 | /* 56 | * If the given DexStringCache doesn't already point at the given value, 57 | * make a copy of it into the cache. This always returns a writable 58 | * pointer to the contents (whether or not a copy had to be made). This 59 | * function is intended to be used after making a call that at least 60 | * sometimes doesn't populate a DexStringCache. 61 | */ 62 | char* dexStringCacheEnsureCopy(DexStringCache* pCache, const char* value); 63 | 64 | /* 65 | * Abandon the given DexStringCache, and return a writable copy of the 66 | * given value (reusing the string cache's allocation if possible). 67 | * The return value must be free()d by the caller. Use this instead of 68 | * dexStringCacheRelease() if you want the buffer to survive past the 69 | * scope of the DexStringCache. 70 | */ 71 | char* dexStringCacheAbandon(DexStringCache* pCache, const char* value); 72 | 73 | /* 74 | * Method prototype structure, which refers to a protoIdx in a 75 | * particular DexFile. 76 | */ 77 | typedef struct DexProto { 78 | const DexFile* dexFile; /* file the idx refers to */ 79 | u4 protoIdx; /* index into proto_ids table of dexFile */ 80 | } DexProto; 81 | 82 | /* 83 | * Set the given DexProto to refer to the prototype of the given MethodId. 84 | */ 85 | DEX_INLINE void dexProtoSetFromMethodId(DexProto* pProto, 86 | const DexFile* pDexFile, const DexMethodId* pMethodId) 87 | { 88 | pProto->dexFile = pDexFile; 89 | pProto->protoIdx = pMethodId->protoIdx; 90 | } 91 | 92 | /* 93 | * Get the short-form method descriptor for the given prototype. The 94 | * prototype must be protoIdx-based. 95 | */ 96 | const char* dexProtoGetShorty(const DexProto* pProto); 97 | 98 | /* 99 | * Get the full method descriptor for the given prototype. 100 | */ 101 | const char* dexProtoGetMethodDescriptor(const DexProto* pProto, 102 | DexStringCache* pCache); 103 | 104 | /* 105 | * Get a copy of the descriptor string associated with the given prototype. 106 | * The returned pointer must be free()ed by the caller. 107 | */ 108 | char* dexProtoCopyMethodDescriptor(const DexProto* pProto); 109 | 110 | /* 111 | * Get the parameter descriptors for the given prototype. This is the 112 | * concatenation of all the descriptors for all the parameters, in 113 | * order, with no other adornment. 114 | */ 115 | const char* dexProtoGetParameterDescriptors(const DexProto* pProto, 116 | DexStringCache* pCache); 117 | 118 | /* 119 | * Return the utf-8 encoded descriptor string from the proto of a MethodId. 120 | */ 121 | DEX_INLINE const char* dexGetDescriptorFromMethodId(const DexFile* pDexFile, 122 | const DexMethodId* pMethodId, DexStringCache* pCache) 123 | { 124 | DexProto proto; 125 | 126 | dexProtoSetFromMethodId(&proto, pDexFile, pMethodId); 127 | return dexProtoGetMethodDescriptor(&proto, pCache); 128 | } 129 | 130 | /* 131 | * Get a copy of the utf-8 encoded method descriptor string from the 132 | * proto of a MethodId. The returned pointer must be free()ed by the 133 | * caller. 134 | */ 135 | DEX_INLINE char* dexCopyDescriptorFromMethodId(const DexFile* pDexFile, 136 | const DexMethodId* pMethodId) 137 | { 138 | DexProto proto; 139 | 140 | dexProtoSetFromMethodId(&proto, pDexFile, pMethodId); 141 | return dexProtoCopyMethodDescriptor(&proto); 142 | } 143 | 144 | /* 145 | * Get the type descriptor for the return type of the given prototype. 146 | */ 147 | const char* dexProtoGetReturnType(const DexProto* pProto); 148 | 149 | /* 150 | * Get the parameter count of the given prototype. 151 | */ 152 | size_t dexProtoGetParameterCount(const DexProto* pProto); 153 | 154 | /* 155 | * Compute the number of parameter words (u4 units) required by the 156 | * given prototype. For example, if the method takes (int, long) and 157 | * returns double, this would return 3 (one for the int, two for the 158 | * long, and the return type isn't relevant). 159 | */ 160 | int dexProtoComputeArgsSize(const DexProto* pProto); 161 | 162 | /* 163 | * Compare the two prototypes. The two prototypes are compared 164 | * with the return type as the major order, then the first arguments, 165 | * then second, etc. If two prototypes are identical except that one 166 | * has extra arguments, then the shorter argument is considered the 167 | * earlier one in sort order (similar to strcmp()). 168 | */ 169 | int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2); 170 | 171 | /* 172 | * Compare the two prototypes. The two prototypes are compared 173 | * with the first argument as the major order, then second, etc. If two 174 | * prototypes are identical except that one has extra arguments, then the 175 | * shorter argument is considered the earlier one in sort order (similar 176 | * to strcmp()). 177 | */ 178 | int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2); 179 | 180 | /* 181 | * Compare a prototype and a string method descriptor. The comparison 182 | * is done as if the descriptor were converted to a prototype and compared 183 | * with dexProtoCompare(). 184 | */ 185 | int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor); 186 | 187 | /* 188 | * Single-thread prototype parameter iterator. This structure holds a 189 | * pointer to a prototype and its parts, along with a cursor. 190 | */ 191 | typedef struct DexParameterIterator { 192 | const DexProto* proto; 193 | const DexTypeList* parameters; 194 | int parameterCount; 195 | int cursor; 196 | } DexParameterIterator; 197 | 198 | /* 199 | * Initialize the given DexParameterIterator to be at the start of the 200 | * parameters of the given prototype. 201 | */ 202 | void dexParameterIteratorInit(DexParameterIterator* pIterator, 203 | const DexProto* pProto); 204 | 205 | /* 206 | * Get the type_id index for the next parameter, if any. This returns 207 | * kDexNoIndex if the last parameter has already been consumed. 208 | */ 209 | u4 dexParameterIteratorNextIndex(DexParameterIterator* pIterator); 210 | 211 | /* 212 | * Get the type descriptor for the next parameter, if any. This returns 213 | * NULL if the last parameter has already been consumed. 214 | */ 215 | const char* dexParameterIteratorNextDescriptor( 216 | DexParameterIterator* pIterator); 217 | 218 | 219 | #ifdef __cplusplus 220 | } 221 | #endif 222 | 223 | #endif /*_LIBDEX_DEXPROTO*/ 224 | -------------------------------------------------------------------------------- /include/libdex/InstrUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Dalvik instruction utility functions. 19 | */ 20 | #ifndef _LIBDEX_INSTRUTILS 21 | #define _LIBDEX_INSTRUTILS 22 | 23 | #include "DexFile.h" 24 | #include "OpCode.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* 31 | * Dalvik-defined instruction formats. 32 | * 33 | * (This defines InstructionFormat as an unsigned char to reduce the size 34 | * of the table. This isn't necessary with some compilers, which use an 35 | * integer width appropriate for the number of enum values.) 36 | * 37 | * If you add or delete a format, you have to change some or all of: 38 | * - this enum 39 | * - the switch inside dexDecodeInstruction() in InstrUtils.c 40 | * - the switch inside dumpInstruction() in DexDump.c 41 | */ 42 | //typedef unsigned char InstructionFormat; 43 | enum InstructionFormat { 44 | kFmtUnknown = 0, 45 | kFmt10x, // op 46 | kFmt12x, // op vA, vB 47 | kFmt11n, // op vA, #+B 48 | kFmt11x, // op vAA 49 | kFmt10t, // op +AA 50 | kFmt20bc, // op AA, thing@BBBB 51 | kFmt20t, // op +AAAA 52 | kFmt22x, // op vAA, vBBBB 53 | kFmt21t, // op vAA, +BBBB 54 | kFmt21s, // op vAA, #+BBBB 55 | kFmt21h, // op vAA, #+BBBB00000[00000000] 56 | kFmt21c, // op vAA, thing@BBBB 57 | kFmt23x, // op vAA, vBB, vCC 58 | kFmt22b, // op vAA, vBB, #+CC 59 | kFmt22t, // op vA, vB, +CCCC 60 | kFmt22s, // op vA, vB, #+CCCC 61 | kFmt22c, // op vA, vB, thing@CCCC 62 | kFmt22cs, // [opt] op vA, vB, field offset CCCC 63 | kFmt32x, // op vAAAA, vBBBB 64 | kFmt30t, // op +AAAAAAAA 65 | kFmt31t, // op vAA, +BBBBBBBB 66 | kFmt31i, // op vAA, #+BBBBBBBB 67 | kFmt31c, // op vAA, thing@BBBBBBBB 68 | kFmt35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG) 69 | kFmt35ms, // [opt] invoke-virtual+super 70 | kFmt35fs, // [opt] invoke-interface 71 | kFmt3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB 72 | kFmt3rms, // [opt] invoke-virtual+super/range 73 | kFmt3rfs, // [opt] invoke-interface/range 74 | kFmt3inline, // [opt] inline invoke 75 | kFmt3rinline, // [opt] inline invoke/range 76 | kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB 77 | }; 78 | 79 | /* 80 | * Holds the contents of a decoded instruction. 81 | */ 82 | typedef struct DecodedInstruction { 83 | u4 vA; 84 | u4 vB; 85 | u8 vB_wide; /* for kFmt51l */ 86 | u4 vC; 87 | u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */ 88 | OpCode opCode; 89 | } DecodedInstruction; 90 | 91 | /* 92 | * Instruction width, a value in the range -3 to 5. 93 | */ 94 | typedef signed char InstructionWidth; 95 | 96 | /* 97 | * Instruction flags, used by the verifier to determine where control 98 | * can flow to next. 99 | */ 100 | //typedef unsigned char InstructionFlags; 101 | enum InstructionFlags { 102 | kInstrCanBranch = 1, // conditional or unconditional branch 103 | kInstrCanContinue = 1 << 1, // flow can continue to next statement 104 | kInstrCanSwitch = 1 << 2, // switch statement 105 | kInstrCanThrow = 1 << 3, // could cause an exception to be thrown 106 | kInstrCanReturn = 1 << 4, // returns, no additional statements 107 | kInstrInvoke = 1 << 5, // a flavor of invoke 108 | kInstrUnconditional = 1 << 6, // unconditional branch 109 | }; 110 | 111 | 112 | /* 113 | * Allocate and populate a 256-element array with instruction widths. A 114 | * width of zero means the entry does not exist. 115 | */ 116 | InstructionWidth* dexCreateInstrWidthTable(void); 117 | 118 | /* 119 | * Returns the width of the specified instruction, or 0 if not defined. 120 | * Optimized instructions use negative values. 121 | */ 122 | DEX_INLINE int dexGetInstrWidth(const InstructionWidth* widths, OpCode opCode) 123 | { 124 | // assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 125 | return widths[opCode]; 126 | } 127 | 128 | /* 129 | * Return the width of the specified instruction, or 0 if not defined. 130 | */ 131 | DEX_INLINE int dexGetInstrWidthAbs(const InstructionWidth* widths,OpCode opCode) 132 | { 133 | //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 134 | 135 | int val = dexGetInstrWidth(widths, opCode); 136 | if (val < 0) 137 | val = -val; 138 | /* XXX - the no-compare trick may be a cycle slower on ARM */ 139 | return val; 140 | } 141 | 142 | /* 143 | * Return the width of the specified instruction, or 0 if not defined. Also 144 | * works for special OP_NOP entries, including switch statement data tables 145 | * and array data. 146 | */ 147 | int dexGetInstrOrTableWidthAbs(const InstructionWidth* widths, const u2* insns); 148 | 149 | 150 | /* 151 | * Allocate and populate a 256-element array with instruction flags. 152 | */ 153 | InstructionFlags* dexCreateInstrFlagsTable(void); 154 | 155 | /* 156 | * Returns the flags for the specified opcode. 157 | */ 158 | DEX_INLINE int dexGetInstrFlags(const InstructionFlags* flags, OpCode opCode) 159 | { 160 | //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 161 | return flags[opCode]; 162 | } 163 | 164 | 165 | /* 166 | * Allocate and populate a 256-element array with instruction formats. 167 | */ 168 | InstructionFormat* dexCreateInstrFormatTable(void); 169 | 170 | /* 171 | * Return the instruction format for the specified opcode. 172 | */ 173 | DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts, 174 | OpCode opCode) 175 | { 176 | //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 177 | return fmts[opCode]; 178 | } 179 | 180 | /* 181 | * Decode the instruction pointed to by "insns". 182 | */ 183 | void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns, 184 | DecodedInstruction* pDec); 185 | 186 | #ifdef __cplusplus 187 | } 188 | #endif 189 | 190 | #endif /*_LIBDEX_INSTRUTILS*/ 191 | -------------------------------------------------------------------------------- /include/libdex/Leb128.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions for interpreting LEB128 (little endian base 128) values 19 | */ 20 | 21 | #ifndef _LIBDEX_LEB128 22 | #define _LIBDEX_LEB128 23 | 24 | #include "DexFile.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* 31 | * Reads an unsigned LEB128 value, updating the given pointer to point 32 | * just past the end of the read value. This function tolerates 33 | * non-zero high-order bits in the fifth encoded byte. 34 | */ 35 | DEX_INLINE int readUnsignedLeb128(const u1** pStream) { 36 | const u1* ptr = *pStream; 37 | int result = *(ptr++); 38 | 39 | if (result > 0x7f) { 40 | int cur = *(ptr++); 41 | result = (result & 0x7f) | ((cur & 0x7f) << 7); 42 | if (cur > 0x7f) { 43 | cur = *(ptr++); 44 | result |= (cur & 0x7f) << 14; 45 | if (cur > 0x7f) { 46 | cur = *(ptr++); 47 | result |= (cur & 0x7f) << 21; 48 | if (cur > 0x7f) { 49 | /* 50 | * Note: We don't check to see if cur is out of 51 | * range here, meaning we tolerate garbage in the 52 | * high four-order bits. 53 | */ 54 | cur = *(ptr++); 55 | result |= cur << 28; 56 | } 57 | } 58 | } 59 | } 60 | 61 | *pStream = ptr; 62 | return result; 63 | } 64 | 65 | /* 66 | * Reads a signed LEB128 value, updating the given pointer to point 67 | * just past the end of the read value. This function tolerates 68 | * non-zero high-order bits in the fifth encoded byte. 69 | */ 70 | DEX_INLINE int readSignedLeb128(const u1** pStream) { 71 | const u1* ptr = *pStream; 72 | int result = *(ptr++); 73 | 74 | if (result <= 0x7f) { 75 | result = (result << 25) >> 25; 76 | } else { 77 | int cur = *(ptr++); 78 | result = (result & 0x7f) | ((cur & 0x7f) << 7); 79 | if (cur <= 0x7f) { 80 | result = (result << 18) >> 18; 81 | } else { 82 | cur = *(ptr++); 83 | result |= (cur & 0x7f) << 14; 84 | if (cur <= 0x7f) { 85 | result = (result << 11) >> 11; 86 | } else { 87 | cur = *(ptr++); 88 | result |= (cur & 0x7f) << 21; 89 | if (cur <= 0x7f) { 90 | result = (result << 4) >> 4; 91 | } else { 92 | /* 93 | * Note: We don't check to see if cur is out of 94 | * range here, meaning we tolerate garbage in the 95 | * high four-order bits. 96 | */ 97 | cur = *(ptr++); 98 | result |= cur << 28; 99 | } 100 | } 101 | } 102 | } 103 | 104 | *pStream = ptr; 105 | return result; 106 | } 107 | 108 | /* 109 | * Reads an unsigned LEB128 value, updating the given pointer to point 110 | * just past the end of the read value and also indicating whether the 111 | * value was syntactically valid. The only syntactically *invalid* 112 | * values are ones that are five bytes long where the final byte has 113 | * any but the low-order four bits set. Additionally, if the limit is 114 | * passed as non-NULL and bytes would need to be read past the limit, 115 | * then the read is considered invalid. 116 | */ 117 | int readAndVerifyUnsignedLeb128(const u1** pStream, const u1* limit, 118 | bool* okay); 119 | 120 | /* 121 | * Reads a signed LEB128 value, updating the given pointer to point 122 | * just past the end of the read value and also indicating whether the 123 | * value was syntactically valid. The only syntactically *invalid* 124 | * values are ones that are five bytes long where the final byte has 125 | * any but the low-order four bits set. Additionally, if the limit is 126 | * passed as non-NULL and bytes would need to be read past the limit, 127 | * then the read is considered invalid. 128 | */ 129 | int readAndVerifySignedLeb128(const u1** pStream, const u1* limit, bool* okay); 130 | 131 | 132 | /* 133 | * Writes a 32-bit value in unsigned ULEB128 format. 134 | * 135 | * Returns the updated pointer. 136 | */ 137 | DEX_INLINE u1* writeUnsignedLeb128(u1* ptr, u4 data) 138 | { 139 | while (true) { 140 | u1 out = data & 0x7f; 141 | if (out != data) { 142 | *ptr++ = out | 0x80; 143 | data >>= 7; 144 | } else { 145 | *ptr++ = out; 146 | break; 147 | } 148 | } 149 | 150 | return ptr; 151 | } 152 | 153 | /* 154 | * Returns the number of bytes needed to encode "val" in ULEB128 form. 155 | */ 156 | DEX_INLINE int unsignedLeb128Size(u4 data) 157 | { 158 | int count = 0; 159 | 160 | do { 161 | data >>= 7; 162 | count++; 163 | } while (data != 0); 164 | 165 | return count; 166 | } 167 | 168 | #ifdef __cplusplus 169 | } 170 | #endif 171 | 172 | #endif 173 | -------------------------------------------------------------------------------- /include/libdex/OptInvocation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Utility functions related to "dexopt". 18 | */ 19 | #ifndef _LIBDEX_OPTINVOCATION 20 | #define _LIBDEX_OPTINVOCATION 21 | 22 | #include 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | 30 | /* 31 | * Utility routines, used by the VM. 32 | */ 33 | char* dexOptGenerateCacheFileName(const char* fileName, 34 | const char* subFileName); 35 | int dexOptCreateEmptyHeader(int fd); 36 | 37 | /* some flags that get passed through to "dexopt" command */ 38 | #define DEXOPT_OPT_ENABLED (1) 39 | #define DEXOPT_OPT_ALL (1 << 1) 40 | #define DEXOPT_VERIFY_ENABLED (1 << 2) 41 | #define DEXOPT_VERIFY_ALL (1 << 3) 42 | #define DEXOPT_IS_BOOTSTRAP (1 << 4) 43 | #define DEXOPT_GEN_REGISTER_MAP (1 << 5) 44 | 45 | 46 | #ifdef __cplusplus 47 | }; 48 | #endif 49 | 50 | #endif /*_LIBDEX_OPTINVOCATION*/ 51 | -------------------------------------------------------------------------------- /include/libdex/SysUtil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * System utilities. 19 | */ 20 | #ifndef _LIBDEX_SYSUTIL 21 | #define _LIBDEX_SYSUTIL 22 | 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* 30 | * System page size. Normally you're expected to get this from 31 | * sysconf(_SC_PAGESIZE) or some system-specific define (usually PAGESIZE 32 | * or PAGE_SIZE). If we use a simple #define the compiler can generate 33 | * appropriate masks directly, so we define it here and verify it as the 34 | * VM is starting up. 35 | * 36 | * Must be a power of 2. 37 | */ 38 | #define SYSTEM_PAGE_SIZE 4096 39 | 40 | /* 41 | * Use this to keep track of mapped segments. 42 | */ 43 | typedef struct MemMapping { 44 | void* addr; /* start of data */ 45 | size_t length; /* length of data */ 46 | 47 | void* baseAddr; /* page-aligned base address */ 48 | size_t baseLength; /* length of mapping */ 49 | } MemMapping; 50 | 51 | /* 52 | * Copy a map. 53 | */ 54 | void sysCopyMap(MemMapping* dst, const MemMapping* src); 55 | 56 | /* 57 | * Load a file into a new shared memory segment. All data from the current 58 | * offset to the end of the file is pulled in. 59 | * 60 | * The segment is read-write, allowing VM fixups. (It should be modified 61 | * to support .gz/.zip compressed data.) 62 | * 63 | * On success, "pMap" is filled in, and zero is returned. 64 | */ 65 | int sysLoadFileInShmem(int fd, MemMapping* pMap); 66 | 67 | /* 68 | * Map a file (from fd's current offset) into a shared, 69 | * read-only memory segment. 70 | * 71 | * On success, "pMap" is filled in, and zero is returned. 72 | */ 73 | int sysMapFileInShmemReadOnly(int fd, MemMapping* pMap); 74 | 75 | /* 76 | * Map a file (from fd's current offset) into a shared, read-only memory 77 | * segment that can be made writable. (In some cases, such as when 78 | * mapping a file on a FAT filesystem, the result may be fully writable.) 79 | * 80 | * On success, "pMap" is filled in, and zero is returned. 81 | */ 82 | int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap); 83 | 84 | /* 85 | * Like sysMapFileInShmemReadOnly, but on only part of a file. 86 | */ 87 | int sysMapFileSegmentInShmem(int fd, off_t start, long length, 88 | MemMapping* pMap); 89 | 90 | /* 91 | * Create a private anonymous mapping, useful for large allocations. 92 | * 93 | * On success, "pMap" is filled in, and zero is returned. 94 | */ 95 | int sysCreatePrivateMap(size_t length, MemMapping* pMap); 96 | 97 | /* 98 | * Change the access rights on one or more pages. If "wantReadWrite" is 99 | * zero, the pages will be made read-only; otherwise they will be read-write. 100 | * 101 | * Returns 0 on success. 102 | */ 103 | int sysChangeMapAccess(void* addr, size_t length, int wantReadWrite, 104 | MemMapping* pmap); 105 | 106 | /* 107 | * Release the pages associated with a shared memory segment. 108 | * 109 | * This does not free "pMap"; it just releases the memory. 110 | */ 111 | void sysReleaseShmem(MemMapping* pMap); 112 | 113 | #ifdef __cplusplus 114 | } 115 | #endif 116 | 117 | #endif /*_DALVIK_SYSUTIL*/ 118 | -------------------------------------------------------------------------------- /include/libdex/ZipArchive.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Read-only access to Zip archives, with minimal heap allocation. 18 | */ 19 | #ifndef _LIBDEX_ZIPARCHIVE 20 | #define _LIBDEX_ZIPARCHIVE 21 | 22 | #include "SysUtil.h" 23 | #include "DexFile.h" // need DEX_INLINE 24 | 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* 31 | * Trivial typedef to ensure that ZipEntry is not treated as a simple 32 | * integer. We use NULL to indicate an invalid value. 33 | */ 34 | typedef void* ZipEntry; 35 | 36 | /* 37 | * One entry in the hash table. 38 | */ 39 | typedef struct ZipHashEntry { 40 | const char* name; 41 | unsigned short nameLen; 42 | //unsigned int hash; 43 | } ZipHashEntry; 44 | 45 | /* 46 | * Read-only Zip archive. 47 | * 48 | * We want "open" and "find entry by name" to be fast operations, and we 49 | * want to use as little memory as possible. We memory-map the file, 50 | * and load a hash table with pointers to the filenames (which aren't 51 | * null-terminated). The other fields are at a fixed offset from the 52 | * filename, so we don't need to extract those (but we do need to byte-read 53 | * and endian-swap them every time we want them). 54 | * 55 | * To speed comparisons when doing a lookup by name, we could make the mapping 56 | * "private" (copy-on-write) and null-terminate the filenames after verifying 57 | * the record structure. However, this requires a private mapping of 58 | * every page that the Central Directory touches. Easier to tuck a copy 59 | * of the string length into the hash table entry. 60 | */ 61 | typedef struct ZipArchive { 62 | /* open Zip archive */ 63 | int mFd; 64 | 65 | /* mapped file */ 66 | MemMapping mMap; 67 | 68 | /* number of entries in the Zip archive */ 69 | int mNumEntries; 70 | 71 | /* 72 | * We know how many entries are in the Zip archive, so we can have a 73 | * fixed-size hash table. We probe on collisions. 74 | */ 75 | int mHashTableSize; 76 | ZipHashEntry* mHashTable; 77 | } ZipArchive; 78 | 79 | /* Zip compression methods we support */ 80 | enum { 81 | kCompressStored = 0, // no compression 82 | kCompressDeflated = 8, // standard deflate 83 | }; 84 | 85 | 86 | /* 87 | * Open a Zip archive. 88 | * 89 | * On success, returns 0 and populates "pArchive". Returns nonzero errno 90 | * value on failure. 91 | */ 92 | int dexZipOpenArchive(const char* fileName, ZipArchive* pArchive); 93 | 94 | /* 95 | * Like dexZipOpenArchive, but takes a file descriptor open for reading 96 | * at the start of the file. The descriptor must be mappable (this does 97 | * not allow access to a stream). 98 | * 99 | * "debugFileName" will appear in error messages, but is not otherwise used. 100 | */ 101 | int dexZipPrepArchive(int fd, const char* debugFileName, ZipArchive* pArchive); 102 | 103 | /* 104 | * Close archive, releasing resources associated with it. 105 | * 106 | * Depending on the implementation this could unmap pages used by classes 107 | * stored in a Jar. This should only be done after unloading classes. 108 | */ 109 | void dexZipCloseArchive(ZipArchive* pArchive); 110 | 111 | /* 112 | * Return the archive's file descriptor. 113 | */ 114 | DEX_INLINE int dexZipGetArchiveFd(const ZipArchive* pArchive) { 115 | return pArchive->mFd; 116 | } 117 | 118 | /* 119 | * Find an entry in the Zip archive, by name. Returns NULL if the entry 120 | * was not found. 121 | */ 122 | ZipEntry dexZipFindEntry(const ZipArchive* pArchive, 123 | const char* entryName); 124 | 125 | /* 126 | * Retrieve one or more of the "interesting" fields. Non-NULL pointers 127 | * are filled in. 128 | */ 129 | bool dexZipGetEntryInfo(const ZipArchive* pArchive, ZipEntry entry, 130 | int* pMethod, long* pUncompLen, long* pCompLen, off_t* pOffset, 131 | long* pModWhen, long* pCrc32); 132 | 133 | /* 134 | * Simple accessors. 135 | */ 136 | DEX_INLINE long dexGetZipEntryOffset(const ZipArchive* pArchive, 137 | const ZipEntry entry) 138 | { 139 | off_t val = 0; 140 | dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, &val, NULL, NULL); 141 | return (long) val; 142 | } 143 | DEX_INLINE long dexGetZipEntryUncompLen(const ZipArchive* pArchive, 144 | const ZipEntry entry) 145 | { 146 | long val = 0; 147 | dexZipGetEntryInfo(pArchive, entry, NULL, &val, NULL, NULL, NULL, NULL); 148 | return val; 149 | } 150 | DEX_INLINE long dexGetZipEntryModTime(const ZipArchive* pArchive, 151 | const ZipEntry entry) 152 | { 153 | long val = 0; 154 | dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, &val, NULL); 155 | return val; 156 | } 157 | DEX_INLINE long dexGetZipEntryCrc32(const ZipArchive* pArchive, 158 | const ZipEntry entry) 159 | { 160 | long val = 0; 161 | dexZipGetEntryInfo(pArchive, entry, NULL, NULL, NULL, NULL, NULL, &val); 162 | return val; 163 | } 164 | 165 | /* 166 | * Uncompress and write an entry to a file descriptor. 167 | */ 168 | bool dexZipExtractEntryToFile(const ZipArchive* pArchive, 169 | const ZipEntry entry, int fd); 170 | 171 | /* 172 | * Utility function to compute a CRC-32. 173 | */ 174 | u4 dexInitCrc32(void); 175 | u4 dexComputeCrc32(u4 crc, const void* buf, size_t len); 176 | 177 | #ifdef __cplusplus 178 | } 179 | #endif 180 | 181 | #endif /*_LIBDEX_ZIPARCHIVE*/ 182 | -------------------------------------------------------------------------------- /include/libdex/sha1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * See "sha1.c" for author info. 3 | */ 4 | #ifndef _DALVIK_SHA1 5 | #define _DALVIK_SHA1 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | typedef struct { 12 | unsigned long state[5]; 13 | unsigned long count[2]; 14 | unsigned char buffer[64]; 15 | } SHA1_CTX; 16 | 17 | #define HASHSIZE 20 18 | 19 | void SHA1Init(SHA1_CTX* context); 20 | void SHA1Update(SHA1_CTX* context, const unsigned char* data, 21 | unsigned long len); 22 | void SHA1Final(unsigned char digest[HASHSIZE], SHA1_CTX* context); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif /*_DALVIK_SHA1*/ 29 | -------------------------------------------------------------------------------- /include/other/inttypes.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxence-ho/DexGraph/dced4f7ee0a270212fb31afc40eab514a9aa0352/include/other/inttypes.h -------------------------------------------------------------------------------- /include/other/typeof.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPEOF_H 2 | #define _TYPEOF_H 3 | 4 | #include 5 | 6 | #define typeof BOOST_TYPEOF 7 | 8 | #endif -------------------------------------------------------------------------------- /include/vm/Common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Common defines for all Dalvik code. 19 | */ 20 | #ifndef _DALVIK_COMMON 21 | #define _DALVIK_COMMON 22 | 23 | #ifndef LOG_TAG 24 | # define LOG_TAG "dalvikvm" 25 | #endif 26 | 27 | #include 28 | #include 29 | 30 | #if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT) 31 | # undef assert 32 | # define assert(x) \ 33 | ((x) ? ((void)0) : (LOGE("ASSERT FAILED (%s:%d): %s\n", \ 34 | __FILE__, __LINE__, #x), *(int*)39=39, 0) ) 35 | #endif 36 | 37 | 38 | /* 39 | * If "very verbose" logging is enabled, make it equivalent to LOGV. 40 | * Otherwise, make it disappear. 41 | * 42 | * Define this above the #include "Dalvik.h" to enable for only a 43 | * single file. 44 | */ 45 | /* #define VERY_VERBOSE_LOG */ 46 | #if defined(VERY_VERBOSE_LOG) 47 | # define LOGVV LOGV 48 | # define IF_LOGVV() IF_LOGV() 49 | #else 50 | # define LOGVV(...) ((void)0) 51 | # define IF_LOGVV() if (false) 52 | #endif 53 | 54 | 55 | /* 56 | * These match the definitions in the VM specification. 57 | */ 58 | #ifdef HAVE_STDINT_H 59 | # include /* C99 */ 60 | typedef uint8_t u1; 61 | typedef uint16_t u2; 62 | typedef uint32_t u4; 63 | typedef uint64_t u8; 64 | typedef int8_t s1; 65 | typedef int16_t s2; 66 | typedef int32_t s4; 67 | typedef int64_t s8; 68 | #else 69 | typedef unsigned char u1; 70 | typedef unsigned short u2; 71 | typedef unsigned int u4; 72 | typedef unsigned long long u8; 73 | typedef signed char s1; 74 | typedef signed short s2; 75 | typedef signed int s4; 76 | typedef signed long long s8; 77 | #endif 78 | 79 | /* 80 | * Storage for primitive types and object references. 81 | * 82 | * Some parts of the code (notably object field access) assume that values 83 | * are "left aligned", i.e. given "JValue jv", "jv.i" and "*((s4*)&jv)" 84 | * yield the same result. This seems to be guaranteed by gcc on big- and 85 | * little-endian systems. 86 | */ 87 | typedef union JValue { 88 | u1 z; 89 | s1 b; 90 | u2 c; 91 | s2 s; 92 | s4 i; 93 | s8 j; 94 | float f; 95 | double d; 96 | void* l; 97 | } JValue; 98 | 99 | /* 100 | * The definition uses _Bool, a type known to the compiler. 101 | */ 102 | #ifdef HAVE_STDBOOL_H 103 | # include /* C99 */ 104 | #else 105 | # ifndef __bool_true_false_are_defined 106 | //typedef enum { false=0, true=!false } bool; 107 | //# define __bool_true_false_are_defined 1 108 | # endif 109 | #endif 110 | 111 | #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) 112 | 113 | 114 | #if defined(HAVE_ENDIAN_H) 115 | # include 116 | #else /*not HAVE_ENDIAN_H*/ 117 | # define __BIG_ENDIAN 4321 118 | # define __LITTLE_ENDIAN 1234 119 | # if defined(HAVE_LITTLE_ENDIAN) 120 | # define __BYTE_ORDER __LITTLE_ENDIAN 121 | # else 122 | # define __BYTE_ORDER __BIG_ENDIAN 123 | # endif 124 | #endif /*not HAVE_ENDIAN_H*/ 125 | 126 | 127 | #if 1 128 | /* 129 | * Pretend we have the Android logging macros. These are replaced by the 130 | * Android logging implementation. 131 | */ 132 | #define ANDROID_LOG_DEBUG 3 133 | #define LOGV(...) LOG_PRI(2, 0, __VA_ARGS__) 134 | #define LOGD(...) LOG_PRI(3, 0, __VA_ARGS__) 135 | #define LOGI(...) LOG_PRI(4, 0, __VA_ARGS__) 136 | #define LOGW(...) LOG_PRI(5, 0, __VA_ARGS__) 137 | #define LOGE(...) LOG_PRI(6, 0, __VA_ARGS__) 138 | #define MIN_LOG_LEVEL 2 139 | /* 140 | dvmFprintf(stdout, "%s:%-4d ", __FILE__, __LINE__); \ 141 | dvmFprintf(stdout, __VA_ARGS__); \ 142 | */ 143 | #define LOG_PRI(priority, tag, ...) do { \ 144 | if (priority >= MIN_LOG_LEVEL) { \ 145 | fprintf(stdout, "%s:%-4d ", __FILE__, __LINE__); \ 146 | fprintf(stdout, __VA_ARGS__); \ 147 | } \ 148 | } while(0) 149 | #else 150 | # include "utils/Log.h" 151 | #endif 152 | 153 | #endif /*_DALVIK_COMMON*/ 154 | -------------------------------------------------------------------------------- /include/vm/DalvikVersion.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Dalvik VM version info. 19 | */ 20 | #ifndef _DALVIK_VERSION 21 | #define _DALVIK_VERSION 22 | 23 | /* 24 | * The version we show to tourists. 25 | */ 26 | #define DALVIK_MAJOR_VERSION 1 27 | #define DALVIK_MINOR_VERSION 2 28 | #define DALVIK_BUG_VERSION 0 29 | 30 | /* 31 | * VM build number. This must change whenever something that affects the 32 | * way classes load changes, e.g. field ordering or vtable layout. Changing 33 | * this guarantees that the optimized form of the DEX file is regenerated. 34 | */ 35 | #define DALVIK_VM_BUILD 19 36 | 37 | #endif /*_DALVIK_VERSION*/ 38 | -------------------------------------------------------------------------------- /src/Dexdump/OpCodenames.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Table of Dalvik opcode names. 18 | */ 19 | #include 20 | 21 | /* 22 | * The following two lines work, but slashes and dashes both turn into 23 | * underscores, and the strings are all upper case. The output is easier 24 | * to read if we do the strings by hand (could probably write a 25 | * post-processing function easily enough if maintenance becomes annoying). 26 | */ 27 | //#define H(_op) #_op 28 | //DEFINE_GOTO_TABLE(gOpNames) 29 | 30 | /* 31 | * Dalvik opcode names. 32 | */ 33 | static const char* gOpNames[256] = { 34 | /* 0x00 */ 35 | "nop", 36 | "move", 37 | "move/from16", 38 | "move/16", 39 | "move-wide", 40 | "move-wide/from16", 41 | "move-wide/16", 42 | "move-object", 43 | "move-object/from16", 44 | "move-object/16", 45 | "move-result", 46 | "move-result-wide", 47 | "move-result-object", 48 | "move-exception", 49 | "return-void", 50 | "return", 51 | 52 | /* 0x10 */ 53 | "return-wide", 54 | "return-object", 55 | "const/4", 56 | "const/16", 57 | "const", 58 | "const/high16", 59 | "const-wide/16", 60 | "const-wide/32", 61 | "const-wide", 62 | "const-wide/high16", 63 | "const-string", 64 | "const-string/jumbo", 65 | "const-class", 66 | "monitor-enter", 67 | "monitor-exit", 68 | "check-cast", 69 | 70 | /* 0x20 */ 71 | "instance-of", 72 | "array-length", 73 | "new-instance", 74 | "new-array", 75 | "filled-new-array", 76 | "filled-new-array/range", 77 | "fill-array-data", 78 | "throw", 79 | "goto", 80 | "goto/16", 81 | "goto/32", 82 | "packed-switch", 83 | "sparse-switch", 84 | "cmpl-float", 85 | "cmpg-float", 86 | "cmpl-double", 87 | 88 | /* 0x30 */ 89 | "cmpg-double", 90 | "cmp-long", 91 | "if-eq", 92 | "if-ne", 93 | "if-lt", 94 | "if-ge", 95 | "if-gt", 96 | "if-le", 97 | "if-eqz", 98 | "if-nez", 99 | "if-ltz", 100 | "if-gez", 101 | "if-gtz", 102 | "if-lez", 103 | "UNUSED", 104 | "UNUSED", 105 | 106 | /* 0x40 */ 107 | "UNUSED", 108 | "UNUSED", 109 | "UNUSED", 110 | "UNUSED", 111 | "aget", 112 | "aget-wide", 113 | "aget-object", 114 | "aget-boolean", 115 | "aget-byte", 116 | "aget-char", 117 | "aget-short", 118 | "aput", 119 | "aput-wide", 120 | "aput-object", 121 | "aput-boolean", 122 | "aput-byte", 123 | 124 | /* 0x50 */ 125 | "aput-char", 126 | "aput-short", 127 | "iget", 128 | "iget-wide", 129 | "iget-object", 130 | "iget-boolean", 131 | "iget-byte", 132 | "iget-char", 133 | "iget-short", 134 | "iput", 135 | "iput-wide", 136 | "iput-object", 137 | "iput-boolean", 138 | "iput-byte", 139 | "iput-char", 140 | "iput-short", 141 | 142 | /* 0x60 */ 143 | "sget", 144 | "sget-wide", 145 | "sget-object", 146 | "sget-boolean", 147 | "sget-byte", 148 | "sget-char", 149 | "sget-short", 150 | "sput", 151 | "sput-wide", 152 | "sput-object", 153 | "sput-boolean", 154 | "sput-byte", 155 | "sput-char", 156 | "sput-short", 157 | "invoke-virtual", 158 | "invoke-super", 159 | 160 | /* 0x70 */ 161 | "invoke-direct", 162 | "invoke-static", 163 | "invoke-interface", 164 | "UNUSED", 165 | "invoke-virtual/range", 166 | "invoke-super/range", 167 | "invoke-direct/range", 168 | "invoke-static/range", 169 | "invoke-interface/range", 170 | "UNUSED", 171 | "UNUSED", 172 | "neg-int", 173 | "not-int", 174 | "neg-long", 175 | "not-long", 176 | "neg-float", 177 | 178 | /* 0x80 */ 179 | "neg-double", 180 | "int-to-long", 181 | "int-to-float", 182 | "int-to-double", 183 | "long-to-int", 184 | "long-to-float", 185 | "long-to-double", 186 | "float-to-int", 187 | "float-to-long", 188 | "float-to-double", 189 | "double-to-int", 190 | "double-to-long", 191 | "double-to-float", 192 | "int-to-byte", 193 | "int-to-char", 194 | "int-to-short", 195 | 196 | /* 0x90 */ 197 | "add-int", 198 | "sub-int", 199 | "mul-int", 200 | "div-int", 201 | "rem-int", 202 | "and-int", 203 | "or-int", 204 | "xor-int", 205 | "shl-int", 206 | "shr-int", 207 | "ushr-int", 208 | "add-long", 209 | "sub-long", 210 | "mul-long", 211 | "div-long", 212 | "rem-long", 213 | 214 | /* 0xa0 */ 215 | "and-long", 216 | "or-long", 217 | "xor-long", 218 | "shl-long", 219 | "shr-long", 220 | "ushr-long", 221 | "add-float", 222 | "sub-float", 223 | "mul-float", 224 | "div-float", 225 | "rem-float", 226 | "add-double", 227 | "sub-double", 228 | "mul-double", 229 | "div-double", 230 | "rem-double", 231 | 232 | /* 0xb0 */ 233 | "add-int/2addr", 234 | "sub-int/2addr", 235 | "mul-int/2addr", 236 | "div-int/2addr", 237 | "rem-int/2addr", 238 | "and-int/2addr", 239 | "or-int/2addr", 240 | "xor-int/2addr", 241 | "shl-int/2addr", 242 | "shr-int/2addr", 243 | "ushr-int/2addr", 244 | "add-long/2addr", 245 | "sub-long/2addr", 246 | "mul-long/2addr", 247 | "div-long/2addr", 248 | "rem-long/2addr", 249 | 250 | /* 0xc0 */ 251 | "and-long/2addr", 252 | "or-long/2addr", 253 | "xor-long/2addr", 254 | "shl-long/2addr", 255 | "shr-long/2addr", 256 | "ushr-long/2addr", 257 | "add-float/2addr", 258 | "sub-float/2addr", 259 | "mul-float/2addr", 260 | "div-float/2addr", 261 | "rem-float/2addr", 262 | "add-double/2addr", 263 | "sub-double/2addr", 264 | "mul-double/2addr", 265 | "div-double/2addr", 266 | "rem-double/2addr", 267 | 268 | /* 0xd0 */ 269 | "add-int/lit16", 270 | "rsub-int", 271 | "mul-int/lit16", 272 | "div-int/lit16", 273 | "rem-int/lit16", 274 | "and-int/lit16", 275 | "or-int/lit16", 276 | "xor-int/lit16", 277 | "add-int/lit8", 278 | "rsub-int/lit8", 279 | "mul-int/lit8", 280 | "div-int/lit8", 281 | "rem-int/lit8", 282 | "and-int/lit8", 283 | "or-int/lit8", 284 | "xor-int/lit8", 285 | 286 | /* 0xe0 */ 287 | "shl-int/lit8", 288 | "shr-int/lit8", 289 | "ushr-int/lit8", 290 | "UNUSED", 291 | "UNUSED", 292 | "UNUSED", 293 | "UNUSED", 294 | "UNUSED", 295 | "UNUSED", 296 | "UNUSED", 297 | "UNUSED", 298 | "UNUSED", 299 | "^breakpoint", // does not appear in DEX files 300 | "^throw-verification-error", // does not appear in DEX files 301 | "+execute-inline", 302 | "+execute-inline/range", 303 | 304 | /* 0xf0 */ 305 | "+invoke-direct-empty", 306 | "UNUSED", 307 | "+iget-quick", 308 | "+iget-wide-quick", 309 | "+iget-object-quick", 310 | "+iput-quick", 311 | "+iput-wide-quick", 312 | "+iput-object-quick", 313 | "+invoke-virtual-quick", 314 | "+invoke-virtual-quick/range", 315 | "+invoke-super-quick", 316 | "+invoke-super-quick/range", 317 | "UNUSED", 318 | "UNUSED", 319 | "UNUSED", 320 | "UNUSED", 321 | }; 322 | 323 | /* 324 | * Return the name of an opcode. 325 | */ 326 | const char* getOpcodeName(OpCode op) 327 | { 328 | return gOpNames[op]; 329 | } 330 | 331 | -------------------------------------------------------------------------------- /src/TreeConstructor/FmtDot.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | auto constexpr tab_str = " "; 7 | 8 | namespace Fmt 9 | { 10 | namespace Dot 11 | { 12 | std::string get_header(TreeConstructor::Node const& node) 13 | { 14 | std::stringstream header_ss; 15 | header_ss << "digraph {\n"; 16 | header_ss << tab_str << "label=\"" 17 | << TreeConstructor::Helper::get_formated_hex(node.baseAddr) 18 | << "\"\n"; 19 | return header_ss.str(); 20 | } 21 | 22 | std::string get_footer() 23 | { 24 | std::stringstream footer_ss; 25 | footer_ss << "}\n"; 26 | return footer_ss.str(); 27 | } 28 | 29 | void dump_tree(TreeConstructor::Node const& current_node) 30 | { 31 | // Print graph description 32 | std::stringstream dot_ss; 33 | dot_ss << get_header(current_node); 34 | 35 | dot_ss << dot_traversal(current_node, dump_single_node); 36 | 37 | dot_ss << get_footer(); 38 | tc_print(dot_ss.str()); 39 | } 40 | 41 | std::string dump_single_node(TreeConstructor::NodeSPtr const node) 42 | { 43 | using namespace TreeConstructor::Helper; 44 | std::stringstream dot_ss; 45 | // Current Node 46 | dot_ss << tab_str << "\"" 47 | << get_formated_hex(node->baseAddr) << "\""; 48 | dot_ss << "[label=\"" 49 | << OpCodeTypeToStr(node->opcode_type) << "\"];\n"; 50 | // Child fmt 51 | for (auto const& child_node : node->next_nodes) 52 | { 53 | // Link Child node to parent node 54 | dot_ss << tab_str << "\"" << get_formated_hex(node->baseAddr) << "\""; 55 | dot_ss << " -> "; 56 | dot_ss << "\"" << get_formated_hex(child_node->baseAddr) << "\";\n"; 57 | } 58 | return dot_ss.str(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/TreeConstructor/FmtEdg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | void tc_binary_print(std::ofstream & file, std::string const& str) 7 | { 8 | if (file.good()) 9 | file.write(str.c_str(), str.size()); 10 | } 11 | 12 | template 13 | void tc_int_binary_print(std::ofstream & file, IntType const& enum_int) 14 | { 15 | if (file.good()) 16 | { 17 | auto const to_write = reinterpret_cast(&enum_int); 18 | file.write(to_write, 19 | sizeof(IntType)); 20 | } 21 | } 22 | 23 | namespace Fmt 24 | { 25 | namespace Edg 26 | { 27 | std::string const edg_header = "GRAPHBIN"; 28 | void dump_all( 29 | std::vector const& nodesptr_vec, 30 | std::vector> const& edges_vec) 32 | { 33 | using TreeConstructor::NodeSPtr; 34 | std::ofstream file("graph.edg", std::ios::app | std::ios::binary); 35 | tc_binary_print(file, "GRAPHBIN"); 36 | file.close(); 37 | dump_edg_body(nodesptr_vec, edges_vec); 38 | } 39 | 40 | std::pair>> 42 | dump_single_node(TreeConstructor::NodeSPtr const node) 43 | { 44 | using TreeConstructor::NodeSPtr; 45 | std::vector> edges_vec; 46 | 47 | for (auto const& child_nodesptr : node->next_nodes) 48 | { 49 | auto const new_pair = 50 | std::make_pair(node, child_nodesptr); 51 | edges_vec.push_back(new_pair); 52 | } 53 | 54 | return std::make_pair(node, edges_vec); 55 | } 56 | 57 | void 58 | dump_node_vec(std::vector const& nodesptr_vec) 59 | { 60 | auto const node_count = (uint32_t)nodesptr_vec.size(); 61 | std::ofstream file("graph.edg", std::ios::app | std::ios::binary); 62 | tc_int_binary_print(file, node_count); 63 | 64 | for (auto const& nodesptr : nodesptr_vec) 65 | { 66 | if (nodesptr == nullptr) 67 | break; 68 | tc_binary_print(file, "n"); 69 | tc_int_binary_print(file, (uint64_t)nodesptr->baseAddr); 70 | tc_int_binary_print(file, static_cast(nodesptr->opcode_type)); 71 | } 72 | file.close(); 73 | } 74 | 75 | void dump_edge_vec( 76 | std::vector < 77 | std::pair> const& 78 | edges_vec) 79 | { 80 | std::ofstream file("graph.edg", std::ios::app | std::ios::binary); 81 | for (auto const& pair : edges_vec) 82 | { 83 | if (pair.first == nullptr || pair.second == nullptr) 84 | break; 85 | 86 | tc_binary_print(file, "e"); 87 | tc_int_binary_print(file, (uint64_t)pair.first->baseAddr); 88 | tc_int_binary_print(file, (uint64_t)pair.second->baseAddr); 89 | } 90 | file.close(); 91 | } 92 | 93 | void dump_edg_body( 94 | std::vector const& nodesptr_vec, 95 | std::vector> const& edges_vec) 97 | { 98 | for (auto const& node : nodesptr_vec) 99 | { 100 | auto count = 0; 101 | for (auto const& second_loop_node : nodesptr_vec) 102 | { 103 | if (node == second_loop_node) 104 | { 105 | count ++; 106 | } 107 | } 108 | if (count > 1) 109 | { 110 | // break here 111 | } 112 | } 113 | dump_node_vec(nodesptr_vec); 114 | dump_edge_vec(edges_vec); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/TreeConstructor/OpcodeType.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | auto constexpr if_opcodes = std::array 8 | { 9 | OP_IF_EQ, 10 | OP_IF_NE, 11 | OP_IF_LT, 12 | OP_IF_GE, 13 | OP_IF_GT, 14 | OP_IF_LE, 15 | OP_IF_EQZ, 16 | OP_IF_NEZ, 17 | OP_IF_LTZ, 18 | OP_IF_GEZ, 19 | OP_IF_GTZ, 20 | OP_IF_LEZ, 21 | }; 22 | 23 | auto constexpr call_opcodes = std::array 24 | { 25 | OP_INVOKE_VIRTUAL, 26 | OP_INVOKE_SUPER, 27 | OP_INVOKE_DIRECT, 28 | OP_INVOKE_STATIC, 29 | OP_INVOKE_INTERFACE, 30 | OP_INVOKE_VIRTUAL_RANGE, 31 | OP_INVOKE_SUPER_RANGE, 32 | OP_INVOKE_DIRECT_RANGE, 33 | OP_INVOKE_STATIC_RANGE, 34 | OP_INVOKE_INTERFACE_RANGE, 35 | }; 36 | 37 | auto constexpr jmp_opcodes = std::array 38 | { 39 | OP_GOTO, 40 | OP_GOTO_16, 41 | OP_GOTO_32, 42 | }; 43 | 44 | auto constexpr switch_opcodes = std::array 45 | { 46 | OP_PACKED_SWITCH, 47 | OP_SPARSE_SWITCH, 48 | }; 49 | 50 | auto constexpr exception_opcodes = std::array 51 | { 52 | OP_THROW, 53 | }; 54 | 55 | auto constexpr ret_opcodes = std::array 56 | { 57 | OP_RETURN_VOID, 58 | OP_RETURN, 59 | OP_RETURN_WIDE, 60 | OP_RETURN_OBJECT, 61 | }; 62 | 63 | auto constexpr new_opcodes = std::array 64 | { 65 | OP_NEW_INSTANCE, 66 | OP_NEW_ARRAY, 67 | OP_FILLED_NEW_ARRAY, 68 | OP_FILLED_NEW_ARRAY_RANGE, 69 | }; 70 | 71 | bool OpCodeClassifier::is_if(OpCode const& candidate) 72 | { 73 | return (std::find(begin(if_opcodes), end(if_opcodes), candidate) != 74 | std::end(if_opcodes)); 75 | } 76 | 77 | bool OpCodeClassifier::is_call(OpCode const& candidate) 78 | { 79 | return (std::find(begin(call_opcodes), end(call_opcodes), candidate) != 80 | std::end(call_opcodes)); 81 | } 82 | 83 | bool OpCodeClassifier::is_jmp(OpCode const& candidate) 84 | { 85 | return (std::find(begin(jmp_opcodes), end(jmp_opcodes), candidate) != 86 | std::end(jmp_opcodes)); 87 | } 88 | 89 | bool OpCodeClassifier::is_switch(OpCode const& candidate) 90 | { 91 | return (std::find(switch_opcodes.begin(), switch_opcodes.end(), candidate) != 92 | std::end(switch_opcodes)); 93 | } 94 | 95 | bool OpCodeClassifier::is_exception(OpCode const& candidate) 96 | { 97 | return (std::find(exception_opcodes.begin(), exception_opcodes.end(), 98 | candidate) != std::end(exception_opcodes)); 99 | } 100 | 101 | bool OpCodeClassifier::is_ret(OpCode const& candidate) 102 | { 103 | return (std::find(begin(ret_opcodes), end(ret_opcodes), candidate) != 104 | std::end(ret_opcodes)); 105 | } 106 | 107 | bool OpCodeClassifier::is_new(OpCode const& candidate) 108 | { 109 | return (std::find(begin(new_opcodes), end(new_opcodes), candidate) != 110 | std::end(new_opcodes)); 111 | } 112 | 113 | std::string OpCodeTypeToStr(OpCodeType const& opcodetype) 114 | { 115 | switch (opcodetype) 116 | { 117 | case OpCodeType::SEQ: return "SEQ"; break; 118 | case OpCodeType::IF: return "IF"; break; 119 | case OpCodeType::CALL: return "CALL"; break; 120 | case OpCodeType::NEW: return "NEW"; break; 121 | case OpCodeType::JMP: return "JMP"; break; 122 | case OpCodeType::SWITCH: return "SWITCH"; break; 123 | case OpCodeType::THROW: return "THROW"; break; 124 | case OpCodeType::SYSCALL: return "SYSCALL"; break; 125 | case OpCodeType::RET: return "RET"; break; 126 | } 127 | } 128 | 129 | OpCodeType OpCodeClassifier::get_opcode_type(OpCode const& opcode) 130 | { 131 | if (is_if(opcode)) 132 | return OpCodeType::IF; 133 | else if (is_call(opcode)) 134 | return OpCodeType::CALL; 135 | else if (is_jmp(opcode)) 136 | return OpCodeType::JMP; 137 | else if (is_switch(opcode)) 138 | return OpCodeType::SWITCH; 139 | else if (is_exception(opcode)) 140 | return OpCodeType::THROW; 141 | else if (is_ret(opcode)) 142 | return OpCodeType::RET; 143 | else if (is_new(opcode)) 144 | return OpCodeType::NEW; 145 | else 146 | return OpCodeType::SEQ; 147 | } 148 | -------------------------------------------------------------------------------- /src/TreeConstructor/TCHelper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace TreeConstructor 9 | { 10 | namespace Helper 11 | { 12 | void write(std::basic_string const& filename, 13 | std::basic_string const& msg) 14 | { 15 | std::ofstream ofs; 16 | ofs.open(filename, std::ios_base::app); 17 | //if (ofs) 18 | ofs << msg << "\n"; 19 | ofs.close(); 20 | } 21 | 22 | std::string get_formated_hex(int const& int_value) 23 | { 24 | std::stringstream s; 25 | s << "0x" 26 | << std::setfill('0') 27 | << std::setw(4) 28 | << std::hex 29 | << int_value; 30 | return s.str(); 31 | } 32 | } 33 | PackedSwitchPayload get_packed_switch_payload(int switch_offset, 34 | intptr_t payload_addr) 35 | { 36 | auto ret = PackedSwitchPayload(); 37 | 38 | // Assert identification of data pack 39 | auto const candidate_id = *((const uint16_t*)payload_addr); 40 | assert(candidate_id == ret.ident && "Incorrect payload ident."); 41 | 42 | // Get payload size 43 | auto const size = *((const uint16_t*)payload_addr + 1)/2; 44 | ret.size = size; 45 | 46 | // Get first_key 47 | ret.first_key = *((const int*)payload_addr + 1); 48 | 49 | 50 | // Get offset payload (given offset are relative to switch addr) 51 | for (std::size_t i = 0; i < size; i++) 52 | { 53 | int const relative_offset = *((unsigned int*)payload_addr + 2 + i); 54 | auto const methodrelative_offset = switch_offset + relative_offset; 55 | ret.targets.push_back(methodrelative_offset); 56 | } 57 | 58 | // Check payload size 59 | assert(ret.targets.size() == size && "Incorrectly sized payload."); 60 | 61 | return ret; 62 | } 63 | 64 | SparseSwitchPayload get_sparse_switch_offsets(int switch_offset, 65 | intptr_t payload_addr) 66 | { 67 | auto ret = SparseSwitchPayload(); 68 | 69 | // Assert identification of data pack 70 | auto const candidate_id = *((const uint16_t*)payload_addr); 71 | assert(candidate_id == ret.ident && "Incorrect payload ident."); 72 | 73 | // Get payload size 74 | auto const size = *((const uint16_t*)payload_addr + 1); 75 | ret.size = size; 76 | 77 | // Get keys 78 | for (std::size_t i = 0; i < size; i ++) 79 | { 80 | int const key = *((const int*)payload_addr + 1 + i); 81 | ret.keys.push_back(key); 82 | } 83 | 84 | // Check keys size 85 | assert(ret.keys.size() == size && "Incorrectly sized keys payload"); 86 | 87 | // Get offset payload (given offset are relative to switch addr) 88 | for (std::size_t i = 0; i < size; i++) 89 | { 90 | int const relative_offset = *((unsigned int*)payload_addr + 1 + size + i); 91 | auto const methodrelative_offset = switch_offset + relative_offset; 92 | ret.targets.push_back(methodrelative_offset); 93 | } 94 | 95 | // Check payload size 96 | assert(ret.targets.size() == size && "Incorrectly sized targets payload."); 97 | 98 | return ret; 99 | } 100 | 101 | MethodInfo get_method_info(DexFile const& dex_file, 102 | uint32_t const& method_idx) 103 | { 104 | 105 | if (method_idx >= dex_file.pHeader->methodIdsSize) 106 | throw std::range_error("method_idx is not in methodIds block"); 107 | 108 | auto const pMethodId = dexGetMethodId(&dex_file, method_idx); 109 | 110 | auto const class_idx = pMethodId->classIdx; 111 | auto const proto_idx = pMethodId->protoIdx; 112 | auto const name_idx = pMethodId->nameIdx; 113 | 114 | auto const class_descriptor = dexStringByTypeIdx(&dex_file, pMethodId->classIdx); 115 | auto const name = dexStringById(&dex_file, pMethodId->nameIdx); 116 | auto const signature = dexCopyDescriptorFromMethodId(&dex_file, pMethodId); 117 | 118 | 119 | auto const ret = MethodInfo { 120 | method_idx, 121 | 122 | class_idx, 123 | proto_idx, 124 | 125 | name_idx, 126 | 127 | class_descriptor, 128 | name, 129 | signature, 130 | }; 131 | 132 | return ret; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/libdex/CmdUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Some utility functions for use with command-line utilities. 18 | */ 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /* 30 | * Extract "classes.dex" from archive file. 31 | * 32 | * If "quiet" is set, don't report common errors. 33 | */ 34 | UnzipToFileResult dexUnzipToFile(const char* zipFileName, 35 | const char* outFileName, bool quiet) 36 | { 37 | UnzipToFileResult result = kUTFRSuccess; 38 | static const char* kFileToExtract = "classes.dex"; 39 | ZipArchive archive; 40 | ZipEntry entry; 41 | bool unlinkOnFailure = false; 42 | int fd = -1; 43 | 44 | if (dexZipOpenArchive(zipFileName, &archive) != 0) { 45 | if (!quiet) { 46 | fprintf(stderr, "Unable to open '%s' as zip archive\n", 47 | zipFileName); 48 | } 49 | result = kUTFRNotZip; 50 | goto bail; 51 | } 52 | 53 | fd = open(outFileName, O_WRONLY | O_CREAT | O_EXCL, 0600); 54 | if (fd < 0) { 55 | fprintf(stderr, "Unable to create output file '%s': %s\n", 56 | outFileName, strerror(errno)); 57 | result = kUTFROutputFileProblem; 58 | goto bail; 59 | } 60 | 61 | unlinkOnFailure = true; 62 | 63 | entry = dexZipFindEntry(&archive, kFileToExtract); 64 | if (entry == NULL) { 65 | if (!quiet) { 66 | fprintf(stderr, "Unable to find '%s' in '%s'\n", 67 | kFileToExtract, zipFileName); 68 | } 69 | result = kUTFRNoClassesDex; 70 | goto bail; 71 | } 72 | 73 | if (!dexZipExtractEntryToFile(&archive, entry, fd)) { 74 | fprintf(stderr, "Extract of '%s' from '%s' failed\n", 75 | kFileToExtract, zipFileName); 76 | result = kUTFRBadZip; 77 | goto bail; 78 | } 79 | 80 | bail: 81 | if (fd >= 0) 82 | close(fd); 83 | if (unlinkOnFailure && result != kUTFRSuccess) 84 | unlink(outFileName); 85 | dexZipCloseArchive(&archive); 86 | return result; 87 | } 88 | 89 | /* 90 | * Map the specified DEX file read-only (possibly after expanding it into a 91 | * temp file from a Jar). Pass in a MemMapping struct to hold the info. 92 | * 93 | * The temp file is deleted after the map succeeds. 94 | * 95 | * This is intended for use by tools (e.g. dexdump) that need to get a 96 | * read-only copy of a DEX file that could be in a number of different states. 97 | * 98 | * If "quiet" is set, don't report common errors. 99 | * 100 | * Returns 0 (kUTFRSuccess) on success. 101 | */ 102 | UnzipToFileResult dexOpenAndMap(const char* fileName, const char* tempFileName, 103 | MemMapping* pMap, bool quiet) 104 | { 105 | UnzipToFileResult result = kUTFRGenericFailure; 106 | int len = strlen(fileName); 107 | char tempNameBuf[32]; 108 | bool removeTemp = false; 109 | int fd = -1; 110 | 111 | if (len < 5) { 112 | if (!quiet) { 113 | fprintf(stderr, 114 | "ERROR: filename must end in .dex, .zip, .jar, or .apk\n"); 115 | } 116 | result = kUTFRBadArgs; 117 | goto bail; 118 | } 119 | 120 | if (strcasecmp(fileName + len -3, "dex") != 0) { 121 | if (tempFileName == NULL) { 122 | /* 123 | * Try .zip/.jar/.apk, all of which are Zip archives with 124 | * "classes.dex" inside. We need to extract the compressed 125 | * data to a temp file, the location of which varies. 126 | */ 127 | if (access("./", 2) == 0) 128 | sprintf(tempNameBuf, "./dex-temp-%d", getpid()); 129 | else if (access("/tmp", 2) == 0) 130 | sprintf(tempNameBuf, "/tmp/dex-temp-%d", getpid()); 131 | else 132 | sprintf(tempNameBuf, "/sdcard/dex-temp-%d", getpid()); 133 | 134 | tempFileName = tempNameBuf; 135 | } 136 | 137 | result = dexUnzipToFile(fileName, tempFileName, quiet); 138 | 139 | if (result == kUTFRSuccess) { 140 | fileName = tempFileName; 141 | removeTemp = true; 142 | } else if (result == kUTFRNotZip) { 143 | if (!quiet) { 144 | fprintf(stderr, "Not Zip, retrying as DEX\n"); 145 | } 146 | } else { 147 | if (!quiet && result == kUTFRNoClassesDex) { 148 | fprintf(stderr, "Zip has no classes.dex\n"); 149 | } 150 | goto bail; 151 | } 152 | } 153 | 154 | /* 155 | * Pop open the (presumed) DEX file. 156 | */ 157 | fd = open(fileName, O_RDONLY); 158 | if (fd < 0) { 159 | if (!quiet) { 160 | fprintf(stderr, "ERROR: unable to open '%s': %s\n", 161 | fileName, strerror(errno)); 162 | } 163 | goto bail; 164 | } 165 | 166 | if (sysMapFileInShmemReadOnly(fd, pMap) != 0) { 167 | fprintf(stderr, "ERROR: Unable to map %s\n", fileName); 168 | close(fd); 169 | goto bail; 170 | } 171 | 172 | /* 173 | * Success! Close the file and return with the start/length in pMap. 174 | */ 175 | result = (UnzipToFileResult)0; 176 | 177 | bail: 178 | if (fd >= 0) 179 | close(fd); 180 | if (removeTemp) { 181 | if (unlink(tempFileName) != 0) { 182 | fprintf(stderr, "Warning: unable to remove temp '%s'\n", 183 | tempFileName); 184 | } 185 | } 186 | return result; 187 | } 188 | -------------------------------------------------------------------------------- /src/libdex/DexCatch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions for dealing with try-catch info. 19 | */ 20 | 21 | #include 22 | 23 | /* Get the first handler offset for the given DexCode. 24 | * It's not 0 because the handlers list is prefixed with its size 25 | * (in entries) as a uleb128. */ 26 | u4 dexGetFirstHandlerOffset(const DexCode* pCode) { 27 | if (pCode->triesSize == 0) { 28 | return 0; 29 | } 30 | 31 | const u1* baseData = dexGetCatchHandlerData(pCode); 32 | const u1* data = baseData; 33 | 34 | readUnsignedLeb128(&data); 35 | 36 | return data - baseData; 37 | } 38 | 39 | /* Get count of handler lists for the given DexCode. */ 40 | u4 dexGetHandlersSize(const DexCode* pCode) { 41 | if (pCode->triesSize == 0) { 42 | return 0; 43 | } 44 | 45 | const u1* data = dexGetCatchHandlerData(pCode); 46 | 47 | return readUnsignedLeb128(&data); 48 | } 49 | 50 | /* Helper for dexFindCatchHandlerOffset(), which does an actual search 51 | * in the tries table. Returns -1 if there is no applicable handler. */ 52 | int dexFindCatchHandlerOffset0(u2 triesSize, const DexTry* pTries, 53 | u4 address) { 54 | // Note: Signed type is important for max and min. 55 | int min = 0; 56 | int max = triesSize - 1; 57 | 58 | while (max >= min) { 59 | int guess = (min + max) >> 1; 60 | const DexTry* pTry = &pTries[guess]; 61 | u4 start = pTry->startAddr; 62 | 63 | if (address < start) { 64 | max = guess - 1; 65 | continue; 66 | } 67 | 68 | u4 end = start + pTry->insnCount; 69 | 70 | if (address >= end) { 71 | min = guess + 1; 72 | continue; 73 | } 74 | 75 | // We have a winner! 76 | return (int) pTry->handlerOff; 77 | } 78 | 79 | // No match. 80 | return -1; 81 | } 82 | 83 | /* Get the handler offset just past the end of the one just iterated over. 84 | * This ends the iteration if it wasn't already. */ 85 | u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator, 86 | const DexCode* pCode) { 87 | while (dexCatchIteratorNext(pIterator) != NULL) /* empty */ ; 88 | 89 | return (u4) (pIterator->pEncodedData - dexGetCatchHandlerData(pCode)); 90 | } 91 | -------------------------------------------------------------------------------- /src/libdex/DexClass.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions to deal with class definition structures in DEX files 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | /* Helper for verification which reads and verifies a given number 27 | * of uleb128 values. */ 28 | static bool verifyUlebs(const u1* pData, const u1* pLimit, u4 count) { 29 | bool okay = true; 30 | u4 i; 31 | 32 | while (okay && (count-- != 0)) { 33 | readAndVerifyUnsignedLeb128(&pData, pLimit, &okay); 34 | } 35 | 36 | return okay; 37 | } 38 | 39 | /* Read and verify the header of a class_data_item. This updates the 40 | * given data pointer to point past the end of the read data and 41 | * returns an "okay" flag (that is, false == failure). */ 42 | bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit, 43 | DexClassDataHeader *pHeader) { 44 | if (! verifyUlebs(*pData, pLimit, 4)) { 45 | return false; 46 | } 47 | 48 | dexReadClassDataHeader(pData, pHeader); 49 | return true; 50 | } 51 | 52 | /* Read and verify an encoded_field. This updates the 53 | * given data pointer to point past the end of the read data and 54 | * returns an "okay" flag (that is, false == failure). 55 | * 56 | * The lastIndex value should be set to 0 before the first field in 57 | * a list is read. It is updated as fields are read and used in the 58 | * decode process. 59 | * 60 | * The verification done by this function is of the raw data format 61 | * only; it does not verify that access flags or indices 62 | * are valid. */ 63 | bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit, 64 | DexField* pField, u4* lastIndex) { 65 | if (! verifyUlebs(*pData, pLimit, 2)) { 66 | return false; 67 | } 68 | 69 | dexReadClassDataField(pData, pField, lastIndex); 70 | return true; 71 | } 72 | 73 | /* Read and verify an encoded_method. This updates the 74 | * given data pointer to point past the end of the read data and 75 | * returns an "okay" flag (that is, false == failure). 76 | * 77 | * The lastIndex value should be set to 0 before the first method in 78 | * a list is read. It is updated as fields are read and used in the 79 | * decode process. 80 | * 81 | * The verification done by this function is of the raw data format 82 | * only; it does not verify that access flags, indices, or offsets 83 | * are valid. */ 84 | bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit, 85 | DexMethod* pMethod, u4* lastIndex) { 86 | if (! verifyUlebs(*pData, pLimit, 3)) { 87 | return false; 88 | } 89 | 90 | dexReadClassDataMethod(pData, pMethod, lastIndex); 91 | return true; 92 | } 93 | 94 | /* Read, verify, and return an entire class_data_item. This updates 95 | * the given data pointer to point past the end of the read data. This 96 | * function allocates a single chunk of memory for the result, which 97 | * must subsequently be free()d. This function returns NULL if there 98 | * was trouble parsing the data. If this function is passed NULL, it 99 | * returns an initialized empty DexClassData structure. 100 | * 101 | * The verification done by this function is of the raw data format 102 | * only; it does not verify that access flags, indices, or offsets 103 | * are valid. */ 104 | DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit) { 105 | DexClassDataHeader header; 106 | u4 lastIndex; 107 | 108 | if (*pData == NULL) { 109 | DexClassData* result = (DexClassData *)malloc(sizeof(DexClassData)); 110 | memset(result, 0, sizeof(*result)); 111 | return result; 112 | } 113 | 114 | if (! dexReadAndVerifyClassDataHeader(pData, pLimit, &header)) { 115 | return NULL; 116 | } 117 | 118 | size_t resultSize = sizeof(DexClassData) + 119 | (header.staticFieldsSize * sizeof(DexField)) + 120 | (header.instanceFieldsSize * sizeof(DexField)) + 121 | (header.directMethodsSize * sizeof(DexMethod)) + 122 | (header.virtualMethodsSize * sizeof(DexMethod)); 123 | 124 | DexClassData* result = (DexClassData *)malloc(resultSize); 125 | u1* ptr = ((u1*) result) + sizeof(DexClassData); 126 | bool okay = true; 127 | u4 i; 128 | 129 | if (result == NULL) { 130 | return NULL; 131 | } 132 | 133 | result->header = header; 134 | 135 | if (header.staticFieldsSize != 0) { 136 | result->staticFields = (DexField*) ptr; 137 | ptr += header.staticFieldsSize * sizeof(DexField); 138 | } else { 139 | result->staticFields = NULL; 140 | } 141 | 142 | if (header.instanceFieldsSize != 0) { 143 | result->instanceFields = (DexField*) ptr; 144 | ptr += header.instanceFieldsSize * sizeof(DexField); 145 | } else { 146 | result->instanceFields = NULL; 147 | } 148 | 149 | if (header.directMethodsSize != 0) { 150 | result->directMethods = (DexMethod*) ptr; 151 | ptr += header.directMethodsSize * sizeof(DexMethod); 152 | } else { 153 | result->directMethods = NULL; 154 | } 155 | 156 | if (header.virtualMethodsSize != 0) { 157 | result->virtualMethods = (DexMethod*) ptr; 158 | } else { 159 | result->virtualMethods = NULL; 160 | } 161 | 162 | lastIndex = 0; 163 | for (i = 0; okay && (i < header.staticFieldsSize); i++) { 164 | okay = dexReadAndVerifyClassDataField(pData, pLimit, 165 | &result->staticFields[i], &lastIndex); 166 | } 167 | 168 | lastIndex = 0; 169 | for (i = 0; okay && (i < header.instanceFieldsSize); i++) { 170 | okay = dexReadAndVerifyClassDataField(pData, pLimit, 171 | &result->instanceFields[i], &lastIndex); 172 | } 173 | 174 | lastIndex = 0; 175 | for (i = 0; okay && (i < header.directMethodsSize); i++) { 176 | okay = dexReadAndVerifyClassDataMethod(pData, pLimit, 177 | &result->directMethods[i], &lastIndex); 178 | } 179 | 180 | lastIndex = 0; 181 | for (i = 0; okay && (i < header.virtualMethodsSize); i++) { 182 | okay = dexReadAndVerifyClassDataMethod(pData, pLimit, 183 | &result->virtualMethods[i], &lastIndex); 184 | } 185 | 186 | if (! okay) { 187 | free(result); 188 | return NULL; 189 | } 190 | 191 | return result; 192 | } 193 | -------------------------------------------------------------------------------- /src/libdex/DexDataMap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Verification-time map of data section items 19 | */ 20 | 21 | #include 22 | //#include "safe_iop/safe_iop.h" 23 | #include 24 | #include 25 | 26 | /* 27 | * Allocate and initialize a DexDataMap. Returns NULL on failure. 28 | */ 29 | DexDataMap* dexDataMapAlloc(u4 maxCount) { 30 | /* 31 | * Allocate a single chunk for the DexDataMap per se as well as the 32 | * two arrays. 33 | */ 34 | size_t size = 0; 35 | DexDataMap* map = NULL; 36 | 37 | /* 38 | * Avoiding pulling in safe_iop for safe_iopf. 39 | */ 40 | #if 0 41 | if (!safe_mul(&size, maxCount, sizeof(u4) + sizeof(u2)) || 42 | !safe_add(&size, size, sizeof(DexDataMap))) { 43 | return NULL; 44 | } 45 | #endif 46 | map = (DexDataMap*)malloc(size); 47 | 48 | if (map == NULL) { 49 | return NULL; 50 | } 51 | 52 | map->count = 0; 53 | map->max = maxCount; 54 | map->offsets = (u4*) (map + 1); 55 | map->types = (u2*) (map->offsets + maxCount); 56 | 57 | return map; 58 | } 59 | 60 | /* 61 | * Free a DexDataMap. 62 | */ 63 | void dexDataMapFree(DexDataMap* map) { 64 | /* 65 | * Since everything got allocated together, everything can be freed 66 | * in one fell swoop. Also, free(NULL) is a nop (per spec), so we 67 | * don't have to worry about an explicit test for that. 68 | */ 69 | free(map); 70 | } 71 | 72 | /* 73 | * Add a new element to the map. The offset must be greater than the 74 | * all previously added offsets. 75 | */ 76 | void dexDataMapAdd(DexDataMap* map, u4 offset, u2 type) { 77 | assert(map != NULL); 78 | assert(map->count < map->max); 79 | 80 | if ((map->count != 0) && 81 | (map->offsets[map->count - 1] >= offset)) { 82 | LOGE("Out-of-order data map offset: 0x%x then 0x%x\n", 83 | map->offsets[map->count - 1], offset); 84 | return; 85 | } 86 | 87 | map->offsets[map->count] = offset; 88 | map->types[map->count] = type; 89 | map->count++; 90 | } 91 | 92 | /* 93 | * Get the type associated with the given offset. This returns -1 if 94 | * there is no entry for the given offset. 95 | */ 96 | int dexDataMapGet(DexDataMap* map, u4 offset) { 97 | assert(map != NULL); 98 | 99 | // Note: Signed type is important for max and min. 100 | int min = 0; 101 | int max = map->count - 1; 102 | u4* offsets = map->offsets; 103 | 104 | while (max >= min) { 105 | int guessIdx = (min + max) >> 1; 106 | u4 guess = offsets[guessIdx]; 107 | 108 | if (offset < guess) { 109 | max = guessIdx - 1; 110 | } else if (offset > guess) { 111 | min = guessIdx + 1; 112 | } else { 113 | // We have a winner! 114 | return map->types[guessIdx]; 115 | } 116 | } 117 | 118 | // No match. 119 | return -1; 120 | } 121 | 122 | /* 123 | * Verify that there is an entry in the map, mapping the given offset to 124 | * the given type. This will return true if such an entry exists and 125 | * return false as well as log an error if not. 126 | */ 127 | bool dexDataMapVerify(DexDataMap* map, u4 offset, u2 type) { 128 | int found = dexDataMapGet(map, offset); 129 | 130 | if (found == type) { 131 | return true; 132 | } 133 | 134 | if (found < 0) { 135 | LOGE("No data map entry found @ 0x%x; expected %x\n", 136 | offset, type); 137 | } else { 138 | LOGE("Unexpected data map entry @ 0x%x: expected %x, found %x\n", 139 | offset, type, found); 140 | } 141 | 142 | return false; 143 | } 144 | -------------------------------------------------------------------------------- /src/libdex/DexInlines.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Generate non-inline copies of inline functions in header files. 18 | */ 19 | 20 | #define _DEX_GEN_INLINES 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | -------------------------------------------------------------------------------- /src/libdex/DexProto.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions for dealing with method prototypes 19 | */ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | /* 27 | * =========================================================================== 28 | * String Cache 29 | * =========================================================================== 30 | */ 31 | 32 | /* 33 | * Make sure that the given cache can hold a string of the given length, 34 | * including the final '\0' byte. 35 | */ 36 | static void dexStringCacheAlloc(DexStringCache* pCache, size_t length) { 37 | if (pCache->allocatedSize != 0) { 38 | if (pCache->allocatedSize >= length) { 39 | return; 40 | } 41 | free((void*) pCache->value); 42 | } 43 | 44 | if (length <= sizeof(pCache->buffer)) { 45 | pCache->value = pCache->buffer; 46 | pCache->allocatedSize = 0; 47 | } else { 48 | pCache->value = (char*)malloc(length); 49 | pCache->allocatedSize = length; 50 | } 51 | } 52 | 53 | /* 54 | * Initialize the given DexStringCache. Use this function before passing 55 | * one into any other function. 56 | */ 57 | void dexStringCacheInit(DexStringCache* pCache) { 58 | pCache->value = pCache->buffer; 59 | pCache->allocatedSize = 0; 60 | pCache->buffer[0] = '\0'; 61 | } 62 | 63 | /* 64 | * Release the allocated contents of the given DexStringCache, if any. 65 | * Use this function after your last use of a DexStringCache. 66 | */ 67 | void dexStringCacheRelease(DexStringCache* pCache) { 68 | if (pCache->allocatedSize != 0) { 69 | free((void*) pCache->value); 70 | pCache->value = pCache->buffer; 71 | pCache->allocatedSize = 0; 72 | } 73 | } 74 | 75 | /* 76 | * If the given DexStringCache doesn't already point at the given value, 77 | * make a copy of it into the cache. This always returns a writable 78 | * pointer to the contents (whether or not a copy had to be made). This 79 | * function is intended to be used after making a call that at least 80 | * sometimes doesn't populate a DexStringCache. 81 | */ 82 | char* dexStringCacheEnsureCopy(DexStringCache* pCache, const char* value) { 83 | if (value != pCache->value) { 84 | size_t length = strlen(value) + 1; 85 | dexStringCacheAlloc(pCache, length); 86 | memcpy(pCache->value, value, length); 87 | } 88 | 89 | return pCache->value; 90 | } 91 | 92 | /* 93 | * Abandon the given DexStringCache, and return a writable copy of the 94 | * given value (reusing the string cache's allocation if possible). 95 | * The return value must be free()d by the caller. Use this instead of 96 | * dexStringCacheRelease() if you want the buffer to survive past the 97 | * scope of the DexStringCache. 98 | */ 99 | char* dexStringCacheAbandon(DexStringCache* pCache, const char* value) { 100 | if ((value == pCache->value) && (pCache->allocatedSize != 0)) { 101 | char* result = pCache->value; 102 | pCache->allocatedSize = 0; 103 | pCache->value = pCache->buffer; 104 | return result; 105 | } else { 106 | return strdup(value); 107 | } 108 | } 109 | 110 | 111 | /* 112 | * =========================================================================== 113 | * Method Prototypes 114 | * =========================================================================== 115 | */ 116 | 117 | /* 118 | * Return the DexProtoId from the given DexProto. The DexProto must 119 | * actually refer to a DexProtoId. 120 | */ 121 | static inline const DexProtoId* getProtoId(const DexProto* pProto) { 122 | return dexGetProtoId(pProto->dexFile, pProto->protoIdx); 123 | } 124 | 125 | /* 126 | * Get the short-form method descriptor for the given prototype. The 127 | * prototype must be protoIdx-based. 128 | */ 129 | const char* dexProtoGetShorty(const DexProto* pProto) { 130 | const DexProtoId* protoId = getProtoId(pProto); 131 | 132 | return dexStringById(pProto->dexFile, protoId->shortyIdx); 133 | } 134 | 135 | /* 136 | * Get the full method descriptor for the given prototype. 137 | */ 138 | const char* dexProtoGetMethodDescriptor(const DexProto* pProto, 139 | DexStringCache* pCache) { 140 | const DexFile* dexFile = pProto->dexFile; 141 | const DexProtoId* protoId = getProtoId(pProto); 142 | const DexTypeList* typeList = dexGetProtoParameters(dexFile, protoId); 143 | size_t length = 3; // parens and terminating '\0' 144 | u4 paramCount = (typeList == NULL) ? 0 : typeList->size; 145 | u4 i; 146 | 147 | for (i = 0; i < paramCount; i++) { 148 | u4 idx = dexTypeListGetIdx(typeList, i); 149 | length += strlen(dexStringByTypeIdx(dexFile, idx)); 150 | } 151 | 152 | length += strlen(dexStringByTypeIdx(dexFile, protoId->returnTypeIdx)); 153 | 154 | dexStringCacheAlloc(pCache, length); 155 | 156 | char *at = (char*) pCache->value; 157 | *(at++) = '('; 158 | 159 | for (i = 0; i < paramCount; i++) { 160 | u4 idx = dexTypeListGetIdx(typeList, i); 161 | const char* desc = dexStringByTypeIdx(dexFile, idx); 162 | strcpy(at, desc); 163 | at += strlen(desc); 164 | } 165 | 166 | *(at++) = ')'; 167 | 168 | strcpy(at, dexStringByTypeIdx(dexFile, protoId->returnTypeIdx)); 169 | return pCache->value; 170 | } 171 | 172 | /* 173 | * Get a copy of the descriptor string associated with the given prototype. 174 | * The returned pointer must be free()ed by the caller. 175 | */ 176 | char* dexProtoCopyMethodDescriptor(const DexProto* pProto) { 177 | DexStringCache cache; 178 | 179 | dexStringCacheInit(&cache); 180 | return dexStringCacheAbandon(&cache, 181 | dexProtoGetMethodDescriptor(pProto, &cache)); 182 | } 183 | 184 | /* 185 | * Get the parameter descriptors for the given prototype. This is the 186 | * concatenation of all the descriptors for all the parameters, in 187 | * order, with no other adornment. 188 | */ 189 | const char* dexProtoGetParameterDescriptors(const DexProto* pProto, 190 | DexStringCache* pCache) { 191 | DexParameterIterator iterator; 192 | size_t length = 1; /* +1 for the terminating '\0' */ 193 | 194 | dexParameterIteratorInit(&iterator, pProto); 195 | 196 | for (;;) { 197 | const char* descriptor = dexParameterIteratorNextDescriptor(&iterator); 198 | if (descriptor == NULL) { 199 | break; 200 | } 201 | 202 | length += strlen(descriptor); 203 | } 204 | 205 | dexParameterIteratorInit(&iterator, pProto); 206 | 207 | dexStringCacheAlloc(pCache, length); 208 | char *at = (char*) pCache->value; 209 | 210 | for (;;) { 211 | const char* descriptor = dexParameterIteratorNextDescriptor(&iterator); 212 | if (descriptor == NULL) { 213 | break; 214 | } 215 | 216 | strcpy(at, descriptor); 217 | at += strlen(descriptor); 218 | } 219 | 220 | return pCache->value; 221 | } 222 | 223 | /* 224 | * Get the type descriptor for the return type of the given prototype. 225 | */ 226 | const char* dexProtoGetReturnType(const DexProto* pProto) { 227 | const DexProtoId* protoId = getProtoId(pProto); 228 | return dexStringByTypeIdx(pProto->dexFile, protoId->returnTypeIdx); 229 | } 230 | 231 | /* 232 | * Get the parameter count of the given prototype. 233 | */ 234 | size_t dexProtoGetParameterCount(const DexProto* pProto) { 235 | const DexProtoId* protoId = getProtoId(pProto); 236 | const DexTypeList* typeList = 237 | dexGetProtoParameters(pProto->dexFile, protoId); 238 | return (typeList == NULL) ? 0 : typeList->size; 239 | } 240 | 241 | /* 242 | * Compute the number of parameter words (u4 units) required by the 243 | * given prototype. For example, if the method takes (int, long) and 244 | * returns double, this would return 3 (one for the int, two for the 245 | * long, and the return type isn't relevant). 246 | */ 247 | int dexProtoComputeArgsSize(const DexProto* pProto) { 248 | const char* shorty = dexProtoGetShorty(pProto); 249 | int count = 0; 250 | 251 | /* Skip the return type. */ 252 | shorty++; 253 | 254 | for (;;) { 255 | switch (*(shorty++)) { 256 | case '\0': { 257 | return count; 258 | } 259 | case 'D': 260 | case 'J': { 261 | count += 2; 262 | break; 263 | } 264 | default: { 265 | count++; 266 | break; 267 | } 268 | } 269 | } 270 | } 271 | 272 | /* 273 | * Common implementation for dexProtoCompare() and dexProtoCompareParameters(). 274 | */ 275 | static int protoCompare(const DexProto* pProto1, const DexProto* pProto2, 276 | bool compareReturnType) { 277 | 278 | if (pProto1 == pProto2) { 279 | // Easy out. 280 | return 0; 281 | } else { 282 | const DexFile* dexFile1 = pProto1->dexFile; 283 | const DexProtoId* protoId1 = getProtoId(pProto1); 284 | const DexTypeList* typeList1 = 285 | dexGetProtoParameters(dexFile1, protoId1); 286 | int paramCount1 = (typeList1 == NULL) ? 0 : typeList1->size; 287 | 288 | const DexFile* dexFile2 = pProto2->dexFile; 289 | const DexProtoId* protoId2 = getProtoId(pProto2); 290 | const DexTypeList* typeList2 = 291 | dexGetProtoParameters(dexFile2, protoId2); 292 | int paramCount2 = (typeList2 == NULL) ? 0 : typeList2->size; 293 | 294 | if (protoId1 == protoId2) { 295 | // Another easy out. 296 | return 0; 297 | } 298 | 299 | // Compare return types. 300 | 301 | if (compareReturnType) { 302 | int result = 303 | strcmp(dexStringByTypeIdx(dexFile1, protoId1->returnTypeIdx), 304 | dexStringByTypeIdx(dexFile2, protoId2->returnTypeIdx)); 305 | 306 | if (result != 0) { 307 | return result; 308 | } 309 | } 310 | 311 | // Compare parameters. 312 | 313 | int minParam = (paramCount1 > paramCount2) ? paramCount2 : paramCount1; 314 | int i; 315 | 316 | for (i = 0; i < minParam; i++) { 317 | u4 idx1 = dexTypeListGetIdx(typeList1, i); 318 | u4 idx2 = dexTypeListGetIdx(typeList2, i); 319 | int result = 320 | strcmp(dexStringByTypeIdx(dexFile1, idx1), 321 | dexStringByTypeIdx(dexFile2, idx2)); 322 | 323 | if (result != 0) { 324 | return result; 325 | } 326 | } 327 | 328 | if (paramCount1 < paramCount2) { 329 | return -1; 330 | } else if (paramCount1 > paramCount2) { 331 | return 1; 332 | } else { 333 | return 0; 334 | } 335 | } 336 | } 337 | 338 | /* 339 | * Compare the two prototypes. The two prototypes are compared 340 | * with the return type as the major order, then the first arguments, 341 | * then second, etc. If two prototypes are identical except that one 342 | * has extra arguments, then the shorter argument is considered the 343 | * earlier one in sort order (similar to strcmp()). 344 | */ 345 | int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2) { 346 | return protoCompare(pProto1, pProto2, true); 347 | } 348 | 349 | /* 350 | * Compare the two prototypes. The two prototypes are compared 351 | * with the first argument as the major order, then second, etc. If two 352 | * prototypes are identical except that one has extra arguments, then the 353 | * shorter argument is considered the earlier one in sort order (similar 354 | * to strcmp()). 355 | */ 356 | int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2){ 357 | return protoCompare(pProto1, pProto2, false); 358 | } 359 | 360 | 361 | /* 362 | * Helper for dexProtoCompareToDescriptor(), which gets the return type 363 | * descriptor from a method descriptor string. 364 | */ 365 | static const char* methodDescriptorReturnType(const char* descriptor) { 366 | const char* result = strchr(descriptor, ')'); 367 | 368 | if (result == NULL) { 369 | return NULL; 370 | } 371 | 372 | // The return type is the character just past the ')'. 373 | return result + 1; 374 | } 375 | 376 | /* 377 | * Helper for dexProtoCompareToDescriptor(), which indicates the end 378 | * of an embedded argument type descriptor, which is also the 379 | * beginning of the next argument type descriptor. Since this is for 380 | * argument types, it doesn't accept 'V' as a valid type descriptor. 381 | */ 382 | static const char* methodDescriptorNextType(const char* descriptor) { 383 | // Skip any array references. 384 | 385 | while (*descriptor == '[') { 386 | descriptor++; 387 | } 388 | 389 | switch (*descriptor) { 390 | case 'B': case 'C': case 'D': case 'F': 391 | case 'I': case 'J': case 'S': case 'Z': { 392 | return descriptor + 1; 393 | } 394 | case 'L': { 395 | const char* result = strchr(descriptor + 1, ';'); 396 | if (result != NULL) { 397 | // The type ends just past the ';'. 398 | return result + 1; 399 | } 400 | } 401 | } 402 | 403 | return NULL; 404 | } 405 | 406 | /* 407 | * Compare a prototype and a string method descriptor. The comparison 408 | * is done as if the descriptor were converted to a prototype and compared 409 | * with dexProtoCompare(). 410 | */ 411 | int dexProtoCompareToDescriptor(const DexProto* proto, 412 | const char* descriptor) { 413 | // First compare the return types. 414 | 415 | int result = strcmp(dexProtoGetReturnType(proto), 416 | methodDescriptorReturnType(descriptor)); 417 | 418 | if (result != 0) { 419 | return result; 420 | } 421 | 422 | // The return types match, so we have to check arguments. 423 | 424 | DexParameterIterator iterator; 425 | dexParameterIteratorInit(&iterator, proto); 426 | 427 | // Skip the '('. 428 | assert (*descriptor == '('); 429 | descriptor++; 430 | 431 | for (;;) { 432 | const char* protoDesc = dexParameterIteratorNextDescriptor(&iterator); 433 | 434 | if (*descriptor == ')') { 435 | // It's the end of the descriptor string. 436 | if (protoDesc == NULL) { 437 | // It's also the end of the prototype's arguments. 438 | return 0; 439 | } else { 440 | // The prototype still has more arguments. 441 | return 1; 442 | } 443 | } 444 | 445 | if (protoDesc == NULL) { 446 | /* 447 | * The prototype doesn't have arguments left, but the 448 | * descriptor string does. 449 | */ 450 | return -1; 451 | } 452 | 453 | // Both prototype and descriptor have arguments. Compare them. 454 | 455 | const char* nextDesc = methodDescriptorNextType(descriptor); 456 | 457 | for (;;) { 458 | char c1 = *(protoDesc++); 459 | char c2 = (descriptor < nextDesc) ? *(descriptor++) : '\0'; 460 | 461 | if (c1 < c2) { 462 | // This includes the case where the proto is shorter. 463 | return -1; 464 | } else if (c1 > c2) { 465 | // This includes the case where the desc is shorter. 466 | return 1; 467 | } else if (c1 == '\0') { 468 | // The two types are equal in length. (c2 necessarily == '\0'.) 469 | break; 470 | } 471 | } 472 | 473 | /* 474 | * If we made it here, the two arguments matched, and 475 | * descriptor == nextDesc. 476 | */ 477 | } 478 | } 479 | 480 | 481 | /* 482 | * =========================================================================== 483 | * Parameter Iterators 484 | * =========================================================================== 485 | */ 486 | 487 | /* 488 | * Initialize the given DexParameterIterator to be at the start of the 489 | * parameters of the given prototype. 490 | */ 491 | void dexParameterIteratorInit(DexParameterIterator* pIterator, 492 | const DexProto* pProto) { 493 | pIterator->proto = pProto; 494 | pIterator->cursor = 0; 495 | 496 | pIterator->parameters = 497 | dexGetProtoParameters(pProto->dexFile, getProtoId(pProto)); 498 | pIterator->parameterCount = (pIterator->parameters == NULL) ? 0 499 | : pIterator->parameters->size; 500 | } 501 | 502 | /* 503 | * Get the type_id index for the next parameter, if any. This returns 504 | * kDexNoIndex if the last parameter has already been consumed. 505 | */ 506 | u4 dexParameterIteratorNextIndex(DexParameterIterator* pIterator) { 507 | int cursor = pIterator->cursor; 508 | int parameterCount = pIterator->parameterCount; 509 | 510 | if (cursor >= parameterCount) { 511 | // The iteration is complete. 512 | return kDexNoIndex; 513 | } else { 514 | u4 idx = dexTypeListGetIdx(pIterator->parameters, cursor); 515 | pIterator->cursor++; 516 | return idx; 517 | } 518 | } 519 | 520 | /* 521 | * Get the type descriptor for the next parameter, if any. This returns 522 | * NULL if the last parameter has already been consumed. 523 | */ 524 | const char* dexParameterIteratorNextDescriptor( 525 | DexParameterIterator* pIterator) { 526 | u4 idx = dexParameterIteratorNextIndex(pIterator); 527 | 528 | if (idx == kDexNoIndex) { 529 | return NULL; 530 | } 531 | 532 | return dexStringByTypeIdx(pIterator->proto->dexFile, idx); 533 | } 534 | 535 | -------------------------------------------------------------------------------- /src/libdex/Leb128.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Functions for interpreting LEB128 (little endian base 128) values 19 | */ 20 | 21 | #include 22 | 23 | /* 24 | * Reads an unsigned LEB128 value, updating the given pointer to point 25 | * just past the end of the read value and also indicating whether the 26 | * value was syntactically valid. The only syntactically *invalid* 27 | * values are ones that are five bytes long where the final byte has 28 | * any but the low-order four bits set. Additionally, if the limit is 29 | * passed as non-NULL and bytes would need to be read past the limit, 30 | * then the read is considered invalid. 31 | */ 32 | int readAndVerifyUnsignedLeb128(const u1** pStream, const u1* limit, 33 | bool* okay) { 34 | const u1* ptr = *pStream; 35 | int result = readUnsignedLeb128(pStream); 36 | 37 | if (((limit != NULL) && (*pStream > limit)) 38 | || (((*pStream - ptr) == 5) && (ptr[4] > 0x0f))) { 39 | *okay = false; 40 | } 41 | 42 | return result; 43 | } 44 | 45 | /* 46 | * Reads a signed LEB128 value, updating the given pointer to point 47 | * just past the end of the read value and also indicating whether the 48 | * value was syntactically valid. The only syntactically *invalid* 49 | * values are ones that are five bytes long where the final byte has 50 | * any but the low-order four bits set. Additionally, if the limit is 51 | * passed as non-NULL and bytes would need to be read past the limit, 52 | * then the read is considered invalid. 53 | */ 54 | int readAndVerifySignedLeb128(const u1** pStream, const u1* limit, 55 | bool* okay) { 56 | const u1* ptr = *pStream; 57 | int result = readSignedLeb128(pStream); 58 | 59 | if (((limit != NULL) && (*pStream > limit)) 60 | || (((*pStream - ptr) == 5) && (ptr[4] > 0x0f))) { 61 | *okay = false; 62 | } 63 | 64 | return result; 65 | } 66 | -------------------------------------------------------------------------------- /src/libdex/OptInvocation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * Utility functions for managing an invocation of "dexopt". 18 | */ 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | typedef long ssize_t; 32 | 33 | #include 34 | #include 35 | 36 | static const char* kClassesDex = "classes.dex"; 37 | 38 | 39 | /* 40 | * Given the filename of a .jar or .dex file, construct the DEX file cache 41 | * name. 42 | * 43 | * For a Jar, "subFileName" is the name of the entry (usually "classes.dex"). 44 | * For a DEX, it may be NULL. 45 | * 46 | * Returns a newly-allocated string, or NULL on failure. 47 | */ 48 | char* dexOptGenerateCacheFileName(const char* fileName, const char* subFileName) 49 | { 50 | char nameBuf[512]; 51 | static const char kDexCachePath[] = "dalvik-cache"; 52 | char absoluteFile[sizeof(nameBuf)]; 53 | const size_t kBufLen = sizeof(nameBuf) - 1; 54 | const char* dataRoot; 55 | char* cp; 56 | 57 | /* 58 | * Get the absolute path of the Jar or DEX file. 59 | */ 60 | absoluteFile[0] = '\0'; 61 | if (fileName[0] != '/') { 62 | /* 63 | * Generate the absolute path. This doesn't do everything it 64 | * should, e.g. if filename is "./out/whatever" it doesn't crunch 65 | * the leading "./" out, but it'll do. 66 | */ 67 | if (getcwd(absoluteFile, kBufLen) == NULL) { 68 | LOGE("Can't get CWD while opening jar file\n"); 69 | return NULL; 70 | } 71 | strncat(absoluteFile, "/", kBufLen); 72 | } 73 | strncat(absoluteFile, fileName, kBufLen); 74 | 75 | /* 76 | * Append the name of the Jar file entry, if any. This is not currently 77 | * required, but will be if we start putting more than one DEX file 78 | * in a Jar. 79 | */ 80 | if (subFileName != NULL) { 81 | strncat(absoluteFile, "/", kBufLen); 82 | strncat(absoluteFile, subFileName, kBufLen); 83 | } 84 | 85 | /* Turn the path into a flat filename by replacing 86 | * any slashes after the first one with '@' characters. 87 | */ 88 | cp = absoluteFile + 1; 89 | while (*cp != '\0') { 90 | if (*cp == '/') { 91 | *cp = '@'; 92 | } 93 | cp++; 94 | } 95 | 96 | /* Build the name of the cache directory. 97 | */ 98 | dataRoot = getenv("ANDROID_DATA"); 99 | if (dataRoot == NULL) 100 | dataRoot = "/data"; 101 | std::snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kDexCachePath); 102 | 103 | /* Tack on the file name for the actual cache file path. 104 | */ 105 | strncat(nameBuf, absoluteFile, kBufLen); 106 | return strdup(nameBuf); 107 | } 108 | 109 | /* 110 | * Create a skeletal "opt" header in a new file. Most of the fields are 111 | * initialized to garbage, but we fill in "dexOffset" so others can 112 | * see how large the header is. 113 | * 114 | * "fd" must be positioned at the start of the file. On return, it will 115 | * be positioned just past the header, and the place where the DEX data 116 | * should go. 117 | * 118 | * Returns 0 on success, errno on failure. 119 | */ 120 | int dexOptCreateEmptyHeader(int fd) 121 | { 122 | DexOptHeader optHdr; 123 | ssize_t actual; 124 | 125 | assert(lseek(fd, 0, SEEK_CUR) == 0); 126 | 127 | /* 128 | * The data is only expected to be readable on the current system, so 129 | * we just write the structure. We do need the file offset to be 64-bit 130 | * aligned to fulfill a DEX requirement. 131 | */ 132 | assert((sizeof(optHdr) & 0x07) == 0); 133 | memset(&optHdr, 0xff, sizeof(optHdr)); 134 | optHdr.dexOffset = sizeof(optHdr); 135 | actual = write(fd, &optHdr, sizeof(optHdr)); 136 | if (actual != sizeof(optHdr)) { 137 | int err = errno ? errno : -1; 138 | LOGE("opt header write failed: %s", strerror(errno)); 139 | return errno; 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /src/libdex/SysUtil.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | * System utilities. 19 | */ 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef HAVE_POSIX_FILEMAP 29 | #include 30 | #endif 31 | 32 | #include 33 | #include 34 | 35 | /* 36 | * Having trouble finding a portable way to get this. sysconf(_SC_PAGE_SIZE) 37 | * seems appropriate, but we don't have that on the device. Some systems 38 | * have getpagesize(2), though the linux man page has some odd cautions. 39 | */ 40 | #define DEFAULT_PAGE_SIZE 4096 41 | 42 | 43 | /* 44 | * Create an anonymous shared memory segment large enough to hold "length" 45 | * bytes. The actual segment may be larger because mmap() operates on 46 | * page boundaries (usually 4K). 47 | */ 48 | static void* sysCreateAnonShmem(size_t length) 49 | { 50 | #ifdef HAVE_POSIX_FILEMAP 51 | void* ptr; 52 | 53 | ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, 54 | MAP_SHARED | MAP_ANON, -1, 0); 55 | if (ptr == MAP_FAILED) { 56 | LOGW("mmap(%d, RW, SHARED|ANON) failed: %s\n", (int) length, 57 | strerror(errno)); 58 | return NULL; 59 | } 60 | 61 | return ptr; 62 | #else 63 | LOGE("sysCreateAnonShmem not implemented.\n"); 64 | return NULL; 65 | #endif 66 | } 67 | 68 | /* 69 | * Create a private anonymous storage area. 70 | */ 71 | int sysCreatePrivateMap(size_t length, MemMapping* pMap) 72 | { 73 | void* memPtr; 74 | 75 | memPtr = sysCreateAnonShmem(length); 76 | if (memPtr == NULL) 77 | return -1; 78 | 79 | pMap->addr = pMap->baseAddr = memPtr; 80 | pMap->length = pMap->baseLength = length; 81 | return 0; 82 | } 83 | 84 | /* 85 | * Determine the current offset and remaining length of the open file. 86 | */ 87 | static int getFileStartAndLength(int fd, off_t *start_, size_t *length_) 88 | { 89 | off_t start, end; 90 | size_t length; 91 | 92 | assert(start_ != NULL); 93 | assert(length_ != NULL); 94 | 95 | start = lseek(fd, 0L, SEEK_CUR); 96 | end = lseek(fd, 0L, SEEK_END); 97 | (void) lseek(fd, start, SEEK_SET); 98 | 99 | if (start == (off_t) -1 || end == (off_t) -1) { 100 | LOGE("could not determine length of file\n"); 101 | return -1; 102 | } 103 | 104 | length = end - start; 105 | if (length == 0) { 106 | LOGE("file is empty\n"); 107 | return -1; 108 | } 109 | 110 | *start_ = start; 111 | *length_ = length; 112 | 113 | return 0; 114 | } 115 | 116 | /* 117 | * Pull the contents of a file into an new shared memory segment. We grab 118 | * everything from fd's current offset on. 119 | * 120 | * We need to know the length ahead of time so we can allocate a segment 121 | * of sufficient size. 122 | */ 123 | int sysLoadFileInShmem(int fd, MemMapping* pMap) 124 | { 125 | #ifdef HAVE_POSIX_FILEMAP 126 | off_t start; 127 | size_t length, actual; 128 | void* memPtr; 129 | 130 | assert(pMap != NULL); 131 | 132 | if (getFileStartAndLength(fd, &start, &length) < 0) 133 | return -1; 134 | 135 | memPtr = sysCreateAnonShmem(length); 136 | if (memPtr == NULL) 137 | return -1; 138 | 139 | actual = read(fd, memPtr, length); 140 | if (actual != length) { 141 | LOGE("only read %d of %d bytes\n", (int) actual, (int) length); 142 | sysReleaseShmem(pMap); 143 | return -1; 144 | } 145 | 146 | pMap->baseAddr = pMap->addr = memPtr; 147 | pMap->baseLength = pMap->length = length; 148 | 149 | return 0; 150 | #else 151 | LOGE("sysLoadFileInShmem not implemented.\n"); 152 | return -1; 153 | #endif 154 | } 155 | 156 | #ifndef HAVE_POSIX_FILEMAP 157 | int sysFakeMapFile(int fd, MemMapping* pMap) 158 | { 159 | /* No MMAP, just fake it by copying the bits. 160 | For Win32 we could use MapViewOfFile if really necessary 161 | (see libs/utils/FileMap.cpp). 162 | */ 163 | off_t start; 164 | size_t length; 165 | void* memPtr; 166 | 167 | assert(pMap != NULL); 168 | 169 | if (getFileStartAndLength(fd, &start, &length) < 0) 170 | return -1; 171 | 172 | memPtr = malloc(length); 173 | if (read(fd, memPtr, length) < 0) { 174 | LOGW("read(fd=%d, start=%d, length=%d) failed: %s\n", (int) length, 175 | fd, (int) start, strerror(errno)); 176 | return -1; 177 | } 178 | 179 | pMap->baseAddr = pMap->addr = memPtr; 180 | pMap->baseLength = pMap->length = length; 181 | 182 | return 0; 183 | } 184 | #endif 185 | 186 | /* 187 | * Map a file (from fd's current offset) into a shared, read-only memory 188 | * segment. The file offset must be a multiple of the system page size. 189 | * 190 | * On success, returns 0 and fills out "pMap". On failure, returns a nonzero 191 | * value and does not disturb "pMap". 192 | */ 193 | int sysMapFileInShmemReadOnly(int fd, MemMapping* pMap) 194 | { 195 | #ifdef HAVE_POSIX_FILEMAP 196 | off_t start; 197 | size_t length; 198 | void* memPtr; 199 | 200 | assert(pMap != NULL); 201 | 202 | if (getFileStartAndLength(fd, &start, &length) < 0) 203 | return -1; 204 | 205 | memPtr = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, start); 206 | if (memPtr == MAP_FAILED) { 207 | LOGW("mmap(%d, RO, FILE|SHARED, %d, %d) failed: %s\n", (int) length, 208 | fd, (int) start, strerror(errno)); 209 | return -1; 210 | } 211 | 212 | pMap->baseAddr = pMap->addr = memPtr; 213 | pMap->baseLength = pMap->length = length; 214 | 215 | return 0; 216 | #else 217 | return sysFakeMapFile(fd, pMap); 218 | #endif 219 | } 220 | 221 | /* 222 | * Map a file (from fd's current offset) into a private, read-write memory 223 | * segment that will be marked read-only (a/k/a "writable read-only"). The 224 | * file offset must be a multiple of the system page size. 225 | * 226 | * In some cases the mapping will be fully writable (e.g. for files on 227 | * FAT filesystems). 228 | * 229 | * On success, returns 0 and fills out "pMap". On failure, returns a nonzero 230 | * value and does not disturb "pMap". 231 | */ 232 | int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap) 233 | { 234 | #ifdef HAVE_POSIX_FILEMAP 235 | off_t start; 236 | size_t length; 237 | void* memPtr; 238 | 239 | assert(pMap != NULL); 240 | 241 | if (getFileStartAndLength(fd, &start, &length) < 0) 242 | return -1; 243 | 244 | memPtr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, 245 | fd, start); 246 | if (memPtr == MAP_FAILED) { 247 | LOGW("mmap(%d, R/W, FILE|PRIVATE, %d, %d) failed: %s\n", (int) length, 248 | fd, (int) start, strerror(errno)); 249 | return -1; 250 | } 251 | if (mprotect(memPtr, length, PROT_READ) < 0) { 252 | /* this fails with EACCESS on FAT filesystems, e.g. /sdcard */ 253 | int err = errno; 254 | memPtr, length, strerror(err)); 255 | LOGD("mprotect(RO) failed (%d), file will remain read-write\n", err); 256 | } 257 | 258 | pMap->baseAddr = pMap->addr = memPtr; 259 | pMap->baseLength = pMap->length = length; 260 | 261 | return 0; 262 | #else 263 | return sysFakeMapFile(fd, pMap); 264 | #endif 265 | } 266 | 267 | /* 268 | * Map part of a file (from fd's current offset) into a shared, read-only 269 | * memory segment. 270 | * 271 | * On success, returns 0 and fills out "pMap". On failure, returns a nonzero 272 | * value and does not disturb "pMap". 273 | */ 274 | int sysMapFileSegmentInShmem(int fd, off_t start, long length, 275 | MemMapping* pMap) 276 | { 277 | #ifdef HAVE_POSIX_FILEMAP 278 | off_t dummy; 279 | size_t fileLength, actualLength; 280 | off_t actualStart; 281 | int adjust; 282 | void* memPtr; 283 | 284 | assert(pMap != NULL); 285 | 286 | if (getFileStartAndLength(fd, &dummy, &fileLength) < 0) 287 | return -1; 288 | 289 | if (start + length > (long)fileLength) { 290 | LOGW("bad segment: st=%d len=%ld flen=%d\n", 291 | (int) start, length, (int) fileLength); 292 | return -1; 293 | } 294 | 295 | /* adjust to be page-aligned */ 296 | adjust = start % DEFAULT_PAGE_SIZE; 297 | actualStart = start - adjust; 298 | actualLength = length + adjust; 299 | 300 | memPtr = mmap(NULL, actualLength, PROT_READ, MAP_FILE | MAP_SHARED, 301 | fd, actualStart); 302 | if (memPtr == MAP_FAILED) { 303 | LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n", 304 | (int) actualLength, fd, (int) actualStart, strerror(errno)); 305 | return -1; 306 | } 307 | 308 | pMap->baseAddr = memPtr; 309 | pMap->baseLength = actualLength; 310 | pMap->addr = (char*)memPtr + adjust; 311 | pMap->length = length; 312 | 313 | LOGVV("mmap seg (st=%d ln=%d): bp=%p bl=%d ad=%p ln=%d\n", 314 | (int) start, (int) length, 315 | pMap->baseAddr, (int) pMap->baseLength, 316 | pMap->addr, (int) pMap->length); 317 | 318 | return 0; 319 | #else 320 | LOGE("sysMapFileSegmentInShmem not implemented.\n"); 321 | return -1; 322 | #endif 323 | } 324 | 325 | /* 326 | * Change the access rights on one or more pages to read-only or read-write. 327 | * 328 | * Returns 0 on success. 329 | */ 330 | int sysChangeMapAccess(void* addr, size_t length, int wantReadWrite, 331 | MemMapping* pMap) 332 | { 333 | #ifdef HAVE_POSIX_FILEMAP 334 | /* 335 | * Verify that "addr" is part of this mapping file. 336 | */ 337 | if (addr < pMap->baseAddr || 338 | (u1*)addr >= (u1*)pMap->baseAddr + pMap->baseLength) 339 | { 340 | LOGE("Attempted to change %p; map is %p - %p\n", 341 | addr, pMap->baseAddr, (u1*)pMap->baseAddr + pMap->baseLength); 342 | return -1; 343 | } 344 | 345 | /* 346 | * Align "addr" to a page boundary and adjust "length" appropriately. 347 | * (The address must be page-aligned, the length doesn't need to be, 348 | * but we do need to ensure we cover the same range.) 349 | */ 350 | u1* alignAddr = (u1*) ((int) addr & ~(SYSTEM_PAGE_SIZE-1)); 351 | size_t alignLength = length + ((u1*) addr - alignAddr); 352 | 353 | //LOGI("%p/%zd --> %p/%zd\n", addr, length, alignAddr, alignLength); 354 | int prot = wantReadWrite ? (PROT_READ|PROT_WRITE) : (PROT_READ); 355 | if (mprotect(alignAddr, alignLength, prot) != 0) { 356 | int err = errno; 357 | return (errno != 0) ? errno : -1; 358 | } 359 | #endif 360 | 361 | /* for "fake" mapping, no need to do anything */ 362 | return 0; 363 | } 364 | 365 | /* 366 | * Release a memory mapping. 367 | */ 368 | void sysReleaseShmem(MemMapping* pMap) 369 | { 370 | #ifdef HAVE_POSIX_FILEMAP 371 | if (pMap->baseAddr == NULL && pMap->baseLength == 0) 372 | return; 373 | 374 | if (munmap(pMap->baseAddr, pMap->baseLength) < 0) { 375 | LOGW("munmap(%p, %d) failed: %s\n", 376 | pMap->baseAddr, (int)pMap->baseLength, strerror(errno)); 377 | } else { 378 | pMap->baseAddr = NULL; 379 | pMap->baseLength = 0; 380 | } 381 | #else 382 | /* Free the bits allocated by sysMapFileInShmem. */ 383 | if (pMap->baseAddr != NULL) { 384 | free(pMap->baseAddr); 385 | pMap->baseAddr = NULL; 386 | } 387 | pMap->baseLength = 0; 388 | #endif 389 | } 390 | 391 | /* 392 | * Make a copy of a MemMapping. 393 | */ 394 | void sysCopyMap(MemMapping* dst, const MemMapping* src) 395 | { 396 | memcpy(dst, src, sizeof(MemMapping)); 397 | } 398 | 399 | -------------------------------------------------------------------------------- /src/libdex/sha1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Tweaked in various ways for Google/Android: 3 | * - Changed from .cpp to .c. 4 | * - Made argument to SHA1Update a const pointer, and enabled 5 | * SHA1HANDSOFF. This incurs a speed penalty but prevents us from 6 | * trashing the input. 7 | * - Include to get endian info. 8 | * - Split a small piece into a header file. 9 | */ 10 | 11 | /* 12 | sha1sum: inspired by md5sum. 13 | 14 | SHA-1 in C 15 | By Steve Reid 16 | 100% Public Domain 17 | 18 | ----------------- 19 | Modified 7/98 20 | By James H. Brown 21 | Still 100% Public Domain 22 | 23 | bit machines 24 | Routine SHA1Update changed from 25 | void SHA1Update(SHA1_CTX* context, unsigned char* data, 26 | unsigned int len) 27 | to 28 | void SHA1Update(SHA1_CTX* context, unsigned char* data, 29 | unsigned long len) 30 | 31 | The 'len' parameter was declared an int which works fine on 32 32 | bit machines. However, on 16 bit machines an int is too small 33 | for the shifts being done against it. This caused the hash 34 | function to generate incorrect values if len was greater than 35 | 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). 36 | 37 | Since the file IO in main() reads 16K at a time, any file 8K or 38 | larger would be guaranteed to generate the wrong hash (e.g. 39 | Test Vector #3, a million "a"s). 40 | 41 | I also changed the declaration of variables i & j in SHA1Update 42 | to unsigned long from unsigned int for the same reason. 43 | 44 | These changes should make no difference to any 32 bit 45 | implementations since an int and a long are the same size in 46 | those environments. 47 | 48 | -- 49 | I also corrected a few compiler warnings generated by Borland 50 | C. 51 | 1. Added #include for exit() prototype 52 | 2. Removed unused variable 'j' in SHA1Final 53 | 3. Changed exit(0) to return(0) at end of main. 54 | 55 | ALL changes I made can be located by searching for comments 56 | containing 'JHB' 57 | 58 | ----------------- 59 | Modified 13 August 2000 60 | By Michael Paul Johnson 61 | Still 100% Public Domain 62 | 63 | Changed command line syntax, added feature to automatically 64 | check files against their previous SHA-1 check values, kind of 65 | like md5sum does. Added functions hexval, verifyfile, 66 | and sha1file. Rewrote main(). 67 | ----------------- 68 | 69 | Test Vectors (from FIPS PUB 180-1) 70 | "abc" 71 | A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 72 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 73 | 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 74 | A million repetitions of "a" 75 | 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 76 | */ 77 | 78 | #define SHA1HANDSOFF /*Copies data before messing with it.*/ 79 | 80 | /*#define CMDLINE * include main() and file processing */ 81 | 82 | #include 83 | 84 | #include 85 | #include 86 | #ifdef __BORLANDC__ 87 | #include 88 | #include 89 | #include /* prototype for exit() - JHB 90 | needed for Win32, but chokes Linux - MPJ */ 91 | #define X_LITTLE_ENDIAN /* This should be #define'd if true.*/ 92 | #else 93 | #include 94 | #include 95 | //# include 96 | 97 | #include // want common byte ordering def 98 | 99 | # if __BYTE_ORDER == __LITTLE_ENDIAN 100 | # define X_LITTLE_ENDIAN 101 | # endif 102 | #endif 103 | #include 104 | 105 | #define LINESIZE 2048 106 | 107 | static void SHA1Transform(unsigned long state[5], 108 | const unsigned char buffer[64]); 109 | 110 | #define rol(value,bits) \ 111 | (((value)<<(bits))|((value)>>(32-(bits)))) 112 | 113 | /* blk0() and blk() perform the initial expand. */ 114 | /* I got the idea of expanding during the round function from 115 | SSLeay */ 116 | #ifdef X_LITTLE_ENDIAN 117 | #define blk0(i) (block->l[i]=(rol(block->l[i],24)&0xFF00FF00) \ 118 | |(rol(block->l[i],8)&0x00FF00FF)) 119 | #else 120 | #define blk0(i) block->l[i] 121 | #endif 122 | #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 123 | ^block->l[(i+2)&15]^block->l[i&15],1)) 124 | 125 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 126 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 127 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 128 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 129 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 130 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 131 | 132 | 133 | /* Hash a single 512-bit block. This is the core of the algorithm. */ 134 | 135 | static void SHA1Transform(unsigned long state[5], 136 | const unsigned char buffer[64]) 137 | { 138 | unsigned long a, b, c, d, e; 139 | typedef union { 140 | unsigned char c[64]; 141 | unsigned long l[16]; 142 | } CHAR64LONG16; 143 | CHAR64LONG16* block; 144 | #ifdef SHA1HANDSOFF 145 | static unsigned char workspace[64]; 146 | block = (CHAR64LONG16*)workspace; 147 | memcpy(block, buffer, 64); 148 | #else 149 | block = (CHAR64LONG16*)buffer; 150 | #endif 151 | /* Copy context->state[] to working vars */ 152 | a = state[0]; 153 | b = state[1]; 154 | c = state[2]; 155 | d = state[3]; 156 | e = state[4]; 157 | /* 4 rounds of 20 operations each. Loop unrolled. */ 158 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); 159 | R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); 160 | R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); 161 | R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 162 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); 163 | R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); 164 | R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); 165 | R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 166 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); 167 | R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); 168 | R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); 169 | R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 170 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); 171 | R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); 172 | R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); 173 | R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 174 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); 175 | R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); 176 | R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); 177 | R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 178 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); 179 | R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); 180 | R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); 181 | R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 182 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); 183 | R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); 184 | R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 185 | 186 | /* Add the working vars back into context.state[] */ 187 | state[0] += a; 188 | state[1] += b; 189 | state[2] += c; 190 | state[3] += d; 191 | state[4] += e; 192 | /* Wipe variables */ 193 | /* a = b = c = d = e = 0; Nice try, but the compiler 194 | optimizes this out, anyway, and it produces an annoying 195 | warning. */ 196 | } 197 | 198 | 199 | /* SHA1Init - Initialize new context */ 200 | 201 | void SHA1Init(SHA1_CTX* context) 202 | { 203 | /* SHA1 initialization constants */ 204 | context->state[0] = 0x67452301; 205 | context->state[1] = 0xEFCDAB89; 206 | context->state[2] = 0x98BADCFE; 207 | context->state[3] = 0x10325476; 208 | context->state[4] = 0xC3D2E1F0; 209 | context->count[0] = context->count[1] = 0; 210 | } 211 | 212 | 213 | /* Run your data through this. */ 214 | 215 | void SHA1Update(SHA1_CTX* context, const unsigned char* data, 216 | unsigned long len) /* JHB */ 217 | { 218 | unsigned long i, j; /* JHB */ 219 | 220 | j = (context->count[0] >> 3) & 63; 221 | if ((context->count[0] += len << 3) < (len << 3)) 222 | context->count[1]++; 223 | context->count[1] += (len >> 29); 224 | if ((j + len) > 63) 225 | { 226 | memcpy(&context->buffer[j], data, (i = 64-j)); 227 | SHA1Transform(context->state, context->buffer); 228 | for ( ; i + 63 < len; i += 64) { 229 | SHA1Transform(context->state, &data[i]); 230 | } 231 | j = 0; 232 | } 233 | else 234 | i = 0; 235 | memcpy(&context->buffer[j], &data[i], len - i); 236 | } 237 | 238 | 239 | /* Add padding and return the message digest. */ 240 | 241 | void SHA1Final(unsigned char digest[HASHSIZE], SHA1_CTX* 242 | context) 243 | { 244 | unsigned long i; /* JHB */ 245 | unsigned char finalcount[8]; 246 | 247 | for (i = 0; i < 8; i++) 248 | { 249 | finalcount[i] = (unsigned char)((context->count[(i>=4? 250 | 0:1)]>>((3-(i&3))*8))&255); 251 | /* Endian independent */ 252 | } 253 | SHA1Update(context, (unsigned char *)"\200", 1); 254 | while ((context->count[0] & 504) != 448) { 255 | SHA1Update(context, (unsigned char *)"\0", 1); 256 | } 257 | SHA1Update(context, finalcount, 8); 258 | /* Should cause a SHA1Transform() */ 259 | for (i = 0; i < HASHSIZE; i++) { 260 | digest[i] = (unsigned char) 261 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); 262 | } 263 | /* Wipe variables */ 264 | memset(context->buffer, 0, 64); 265 | memset(context->state, 0, HASHSIZE); 266 | memset(context->count, 0, 8); 267 | memset(&finalcount, 0, 8); 268 | #ifdef SHA1HANDSOFF 269 | /* make SHA1Transform overwrite it's own static vars */ 270 | SHA1Transform(context->state, context->buffer); 271 | #endif 272 | } 273 | 274 | 275 | 276 | #ifdef CMDLINE 277 | 278 | /* sha1file computes the SHA-1 hash of the named file and puts 279 | it in the 20-byte array digest. If fname is NULL, stdin is 280 | assumed. 281 | */ 282 | void sha1file(char *fname, unsigned char* digest) 283 | { 284 | int bytesread; 285 | SHA1_CTX context; 286 | unsigned char buffer[16384]; 287 | FILE* f; 288 | 289 | if (fname) 290 | { 291 | f = fopen(fname, "rb"); 292 | if (!f) 293 | { 294 | fprintf(stderr, "Can't open %s\n", fname); 295 | memset(digest, 0, HASHSIZE); 296 | return; 297 | } 298 | } 299 | else 300 | { 301 | f = stdin; 302 | } 303 | SHA1Init(&context); 304 | while (!feof(f)) 305 | { 306 | bytesread = fread(buffer, 1, 16384, f); 307 | SHA1Update(&context, buffer, bytesread); 308 | } 309 | SHA1Final(digest, &context); 310 | if (fname) 311 | fclose(f); 312 | } 313 | 314 | /* Convert ASCII hexidecimal digit to 4-bit value. */ 315 | unsigned char hexval(char c) 316 | { 317 | unsigned char h; 318 | 319 | c = toupper(c); 320 | if (c >= 'A') 321 | h = c - 'A' + 10; 322 | else 323 | h = c - '0'; 324 | return h; 325 | } 326 | 327 | /* Verify a file created with sha1sum by redirecting output 328 | to a file. */ 329 | int verifyfile(char *fname) 330 | { 331 | int j, k; 332 | int found = 0; 333 | unsigned char digest[HASHSIZE]; 334 | unsigned char expected_digest[HASHSIZE]; 335 | FILE *checkfile; 336 | char checkline[LINESIZE]; 337 | char *s; 338 | unsigned char err; 339 | 340 | checkfile = fopen(fname, "rt"); 341 | if (!checkfile) 342 | { 343 | fprintf(stderr, "Can't open %s\n", fname); 344 | return(0); 345 | } 346 | do 347 | { 348 | s = fgets(checkline, LINESIZE, checkfile); 349 | if (s) 350 | { 351 | if ((strlen(checkline)>26)&& 352 | 1 /*(!strncmp(checkline,"SHA1=", 5))*/) 353 | { 354 | /* Overwrite newline. */ 355 | checkline[strlen(checkline)-1]=0; 356 | found = 1; 357 | 358 | /* Read expected check value. */ 359 | for (k=0, j=5; k < HASHSIZE; k++) 360 | { 361 | expected_digest[k]=hexval(checkline[j++]); 362 | expected_digest[k]=(expected_digest[k]<<4) 363 | +hexval(checkline[j++]); 364 | } 365 | 366 | /* Compute fingerprints */ 367 | s = checkline+46; 368 | sha1file(s, digest); 369 | 370 | /* Compare fingerprints */ 371 | err = 0; 372 | for (k=0; k check.txt\n" 407 | "generates check value for test.txt in check.txt, and\n" 408 | "sha1sum -c check.txt\n" 409 | "checks test.txt against the check value in check.txt\n", 410 | progname); 411 | exit(1); 412 | } 413 | 414 | 415 | /**********************************************************/ 416 | 417 | int main(int argc, char** argv) 418 | { 419 | int i, j, k; 420 | int check = 0; 421 | int found = 0; 422 | unsigned char digest[HASHSIZE]; 423 | unsigned char expected_digest[HASHSIZE]; 424 | FILE *checkfile; 425 | char checkline[LINESIZE]; 426 | char *s; 427 | #ifdef __BORLANDC__ 428 | struct ffblk f; 429 | int done; 430 | char path[MAXPATH]; 431 | char drive[MAXDRIVE]; 432 | char dir[MAXDIR]; 433 | char name[MAXFILE]; 434 | char ext[MAXEXT]; 435 | #endif 436 | unsigned char err; 437 | 438 | for (i = 1; i < argc; i++) 439 | { 440 | if (argv[i][0] == '-') 441 | { 442 | switch (argv[i][1]) 443 | { 444 | case 'c': 445 | case 'C': 446 | check = 1; 447 | break; 448 | case 'g': 449 | case 'G': 450 | check = 0; 451 | break; 452 | default: 453 | syntax(argv[0]); 454 | } 455 | } 456 | } 457 | 458 | for (i=1; i