summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sehr <sehr@google.com>2019-04-04 19:42:15 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2019-04-04 19:42:15 +0000
commit8843541a211b388bd2d48037ea6595265d125730 (patch)
tree508eb8af457e6394312126b9c2941d35ba3911b9
parent6bc54f7aedd7c8c526f4eed4cc67bc0c88703f3c (diff)
parentf33b916861cf30ac51de7156ec4e69fa79d280b3 (diff)
downloaddalvik-oreo-mr1-iot-release.tar.gz
-rw-r--r--Android.bp1
-rw-r--r--libdex/Android.bp56
-rw-r--r--libdex/CmdUtils.cpp228
-rw-r--r--libdex/CmdUtils.h73
-rw-r--r--libdex/DexCatch.cpp90
-rw-r--r--libdex/DexCatch.h162
-rw-r--r--libdex/DexClass.cpp191
-rw-r--r--libdex/DexClass.h162
-rw-r--r--libdex/DexDataMap.cpp138
-rw-r--r--libdex/DexDataMap.h73
-rw-r--r--libdex/DexDebugInfo.cpp281
-rw-r--r--libdex/DexDebugInfo.h55
-rw-r--r--libdex/DexFile.cpp539
-rw-r--r--libdex/DexFile.h1084
-rw-r--r--libdex/DexInlines.cpp33
-rw-r--r--libdex/DexOpcodes.cpp299
-rw-r--r--libdex/DexOpcodes.h620
-rw-r--r--libdex/DexOptData.cpp128
-rw-r--r--libdex/DexOptData.h42
-rw-r--r--libdex/DexProto.cpp523
-rw-r--r--libdex/DexProto.h229
-rw-r--r--libdex/DexSwapVerify.cpp3070
-rw-r--r--libdex/DexUtf.cpp304
-rw-r--r--libdex/DexUtf.h131
-rw-r--r--libdex/InstrUtils.cpp702
-rw-r--r--libdex/InstrUtils.h201
-rw-r--r--libdex/Leb128.cpp65
-rw-r--r--libdex/Leb128.h164
-rw-r--r--libdex/OptInvocation.cpp177
-rw-r--r--libdex/OptInvocation.h30
-rw-r--r--libdex/SysUtil.cpp370
-rw-r--r--libdex/SysUtil.h109
-rw-r--r--libdex/ZipArchive.h86
-rw-r--r--libdex/sha1.cpp512
-rw-r--r--libdex/sha1.h20
35 files changed, 0 insertions, 10948 deletions
diff --git a/Android.bp b/Android.bp
index afc34655c..702d27da4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,4 @@
subdirs = [
"dx",
- "libdex",
"tools/hprof-conv",
]
diff --git a/libdex/Android.bp b/libdex/Android.bp
deleted file mode 100644
index 737e097cd..000000000
--- a/libdex/Android.bp
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-cc_library_static {
- name: "libdex",
- host_supported: true,
-
- srcs: [
- "CmdUtils.cpp",
- "DexCatch.cpp",
- "DexClass.cpp",
- "DexDataMap.cpp",
- "DexDebugInfo.cpp",
- "DexFile.cpp",
- "DexInlines.cpp",
- "DexOptData.cpp",
- "DexOpcodes.cpp",
- "DexProto.cpp",
- "DexSwapVerify.cpp",
- "DexUtf.cpp",
- "InstrUtils.cpp",
- "Leb128.cpp",
- "OptInvocation.cpp",
- "sha1.cpp",
- "SysUtil.cpp",
- ],
- include_dirs: [
- "dalvik",
- "external/zlib",
- ],
- static_libs: ["liblog"],
- whole_static_libs: ["libziparchive"],
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wimplicit-fallthrough",
- ],
- target: {
- windows: {
- enabled: true,
- cflags: ["-Wno-unused-parameter"],
- },
- },
-}
diff --git a/libdex/CmdUtils.cpp b/libdex/CmdUtils.cpp
deleted file mode 100644
index 8244a1189..000000000
--- a/libdex/CmdUtils.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Some utility functions for use with command-line utilities.
- */
-#include "DexFile.h"
-#include "ZipArchive.h"
-#include "CmdUtils.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/*
- * Extract "classes.dex" from archive file.
- *
- * If "quiet" is set, don't report common errors.
- */
-UnzipToFileResult dexUnzipToFile(const char* zipFileName,
- const char* outFileName, bool quiet)
-{
- UnzipToFileResult result = kUTFRSuccess;
- static const char* kFileToExtract = "classes.dex";
- ZipArchiveHandle archive;
- ZipEntry entry;
- bool unlinkOnFailure = false;
- int fd = -1;
-
- if (dexZipOpenArchive(zipFileName, &archive) != 0) {
- if (!quiet) {
- fprintf(stderr, "Unable to open '%s' as zip archive\n",
- zipFileName);
- }
- result = kUTFRNotZip;
- goto bail;
- }
-
- fd = open(outFileName, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
- if (fd < 0) {
- fprintf(stderr, "Unable to create output file '%s': %s\n",
- outFileName, strerror(errno));
- result = kUTFROutputFileProblem;
- goto bail;
- }
-
- unlinkOnFailure = true;
-
- if (dexZipFindEntry(archive, kFileToExtract, &entry) != 0) {
- if (!quiet) {
- fprintf(stderr, "Unable to find '%s' in '%s'\n",
- kFileToExtract, zipFileName);
- }
- result = kUTFRNoClassesDex;
- goto bail;
- }
-
- if (dexZipExtractEntryToFile(archive, &entry, fd) != 0) {
- fprintf(stderr, "Extract of '%s' from '%s' failed\n",
- kFileToExtract, zipFileName);
- result = kUTFRBadZip;
- goto bail;
- }
-
-bail:
- if (fd >= 0)
- close(fd);
- if (unlinkOnFailure && result != kUTFRSuccess)
- unlink(outFileName);
- dexZipCloseArchive(archive);
- return result;
-}
-
-/*
- * Map the specified DEX file read-only (possibly after expanding it into a
- * temp file from a Jar). Pass in a MemMapping struct to hold the info.
- * If the file is an unoptimized DEX file, then byte-swapping and structural
- * verification are performed on it before the memory is made read-only.
- *
- * The temp file is deleted after the map succeeds.
- *
- * This is intended for use by tools (e.g. dexdump) that need to get a
- * read-only copy of a DEX file that could be in a number of different states.
- *
- * If "tempFileName" is NULL, a default value is used. The temp file is
- * deleted after the map succeeds.
- *
- * If "quiet" is set, don't report common errors.
- *
- * Returns 0 (kUTFRSuccess) on success.
- */
-UnzipToFileResult dexOpenAndMap(const char* fileName, const char* tempFileName,
- MemMapping* pMap, bool quiet)
-{
- UnzipToFileResult result = kUTFRGenericFailure;
- int len = strlen(fileName);
- char tempNameBuf[32];
- bool removeTemp = false;
- int fd = -1;
-
- if (len < 5) {
- if (!quiet) {
- fprintf(stderr,
- "ERROR: filename must end in .dex, .zip, .jar, or .apk\n");
- }
- result = kUTFRBadArgs;
- goto bail;
- }
-
- if (strcasecmp(fileName + len -3, "dex") != 0) {
- if (tempFileName == NULL) {
- /*
- * Try .zip/.jar/.apk, all of which are Zip archives with
- * "classes.dex" inside. We need to extract the compressed
- * data to a temp file, the location of which varies.
- *
- * On the device we must use /sdcard because most other
- * directories aren't writable (either because of permissions
- * or because the volume is mounted read-only). On desktop
- * it's nice to use the designated temp directory.
- */
- if (access("/tmp", W_OK) == 0) {
- sprintf(tempNameBuf, "/tmp/dex-temp-%d", getpid());
- } else if (access("/sdcard", W_OK) == 0) {
- sprintf(tempNameBuf, "/sdcard/dex-temp-%d", getpid());
- } else {
- fprintf(stderr,
- "NOTE: /tmp and /sdcard unavailable for temp files\n");
- sprintf(tempNameBuf, "dex-temp-%d", getpid());
- }
-
- tempFileName = tempNameBuf;
- }
-
- result = dexUnzipToFile(fileName, tempFileName, quiet);
-
- if (result == kUTFRSuccess) {
- //printf("+++ Good unzip to '%s'\n", tempFileName);
- fileName = tempFileName;
- removeTemp = true;
- } else if (result == kUTFRNotZip) {
- if (!quiet) {
- fprintf(stderr, "Not Zip, retrying as DEX\n");
- }
- } else {
- if (!quiet && result == kUTFRNoClassesDex) {
- fprintf(stderr, "Zip has no classes.dex\n");
- }
- goto bail;
- }
- }
-
- result = kUTFRGenericFailure;
-
- /*
- * Pop open the (presumed) DEX file.
- */
- fd = open(fileName, O_RDONLY | O_BINARY);
- if (fd < 0) {
- if (!quiet) {
- fprintf(stderr, "ERROR: unable to open '%s': %s\n",
- fileName, strerror(errno));
- }
- goto bail;
- }
-
- if (sysMapFileInShmemWritableReadOnly(fd, pMap) != 0) {
- fprintf(stderr, "ERROR: Unable to map '%s'\n", fileName);
- goto bail;
- }
-
- /*
- * This call will fail if the file exists on a filesystem that
- * doesn't support mprotect(). If that's the case, then the file
- * will have already been mapped private-writable by the previous
- * call, so we don't need to do anything special if this call
- * returns non-zero.
- */
- sysChangeMapAccess(pMap->addr, pMap->length, true, pMap);
-
- if (dexSwapAndVerifyIfNecessary((u1*) pMap->addr, pMap->length)) {
- fprintf(stderr, "ERROR: Failed structural verification of '%s'\n",
- fileName);
- goto bail;
- }
-
- /*
- * Similar to above, this call will fail if the file wasn't ever
- * read-only to begin with. This is innocuous, though it is
- * undesirable from a memory hygiene perspective.
- */
- sysChangeMapAccess(pMap->addr, pMap->length, false, pMap);
-
- /*
- * Success! Close the file and return with the start/length in pMap.
- */
- result = kUTFRSuccess;
-
-bail:
- if (fd >= 0)
- close(fd);
- if (removeTemp) {
- /* this will fail if the OS doesn't allow removal of a mapped file */
- if (unlink(tempFileName) != 0) {
- fprintf(stderr, "WARNING: unable to remove temp '%s'\n",
- tempFileName);
- }
- }
- return result;
-}
diff --git a/libdex/CmdUtils.h b/libdex/CmdUtils.h
deleted file mode 100644
index 887eed9ba..000000000
--- a/libdex/CmdUtils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Access .dex (Dalvik Executable Format) files. The code here assumes that
- * the DEX file has been rewritten (byte-swapped, word-aligned) and that
- * the contents can be directly accessed as a collection of C arrays. Please
- * see docs/dalvik/dex-format.html for a detailed description.
- *
- * The structure and field names were chosen to match those in the DEX spec.
- *
- * It's generally assumed that the DEX file will be stored in shared memory,
- * obviating the need to copy code and constant pool entries into newly
- * allocated storage. Maintaining local pointers to items in the shared area
- * is valid and encouraged.
- *
- * All memory-mapped structures are 32-bit aligned unless otherwise noted.
- */
-#ifndef LIBDEX_CMDUTILS_H_
-#define LIBDEX_CMDUTILS_H_
-
-/* encode the result of unzipping to a file */
-enum UnzipToFileResult {
- kUTFRSuccess = 0,
- kUTFRGenericFailure,
- kUTFRBadArgs,
- kUTFRNotZip,
- kUTFRNoClassesDex,
- kUTFROutputFileProblem,
- kUTFRBadZip,
-};
-
-/*
- * Map the specified DEX file read-only (possibly after expanding it into a
- * temp file from a Jar). Pass in a MemMapping struct to hold the info.
- * If the file is an unoptimized DEX file, then byte-swapping and structural
- * verification are performed on it before the memory is made read-only.
- *
- * The temp file is deleted after the map succeeds.
- *
- * This is intended for use by tools (e.g. dexdump) that need to get a
- * read-only copy of a DEX file that could be in a number of different states.
- *
- * If "tempFileName" is NULL, a default value is used. The temp file is
- * deleted after the map succeeds.
- *
- * If "quiet" is set, don't report common errors.
- *
- * Returns 0 (kUTFRSuccess) on success.
- */
-UnzipToFileResult dexOpenAndMap(const char* fileName, const char* tempFileName,
- MemMapping* pMap, bool quiet);
-
-/*
- * Utility function to open a Zip archive, find "classes.dex", and extract
- * it to a file.
- */
-UnzipToFileResult dexUnzipToFile(const char* zipFileName,
- const char* outFileName, bool quiet);
-
-#endif // LIBDEX_CMDUTILS_H_
diff --git a/libdex/DexCatch.cpp b/libdex/DexCatch.cpp
deleted file mode 100644
index ed97e87d9..000000000
--- a/libdex/DexCatch.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions for dealing with try-catch info.
- */
-
-#include "DexCatch.h"
-
-/* Get the first handler offset for the given DexCode.
- * It's not 0 because the handlers list is prefixed with its size
- * (in entries) as a uleb128. */
-u4 dexGetFirstHandlerOffset(const DexCode* pCode) {
- if (pCode->triesSize == 0) {
- return 0;
- }
-
- const u1* baseData = dexGetCatchHandlerData(pCode);
- const u1* data = baseData;
-
- readUnsignedLeb128(&data);
-
- return data - baseData;
-}
-
-/* Get count of handler lists for the given DexCode. */
-u4 dexGetHandlersSize(const DexCode* pCode) {
- if (pCode->triesSize == 0) {
- return 0;
- }
-
- const u1* data = dexGetCatchHandlerData(pCode);
-
- return readUnsignedLeb128(&data);
-}
-
-/* Helper for dexFindCatchHandlerOffset(), which does an actual search
- * in the tries table. Returns -1 if there is no applicable handler. */
-int dexFindCatchHandlerOffset0(u2 triesSize, const DexTry* pTries,
- u4 address) {
- // Note: Signed type is important for max and min.
- int min = 0;
- int max = triesSize - 1;
-
- while (max >= min) {
- int guess = (min + max) >> 1;
- const DexTry* pTry = &pTries[guess];
- u4 start = pTry->startAddr;
-
- if (address < start) {
- max = guess - 1;
- continue;
- }
-
- u4 end = start + pTry->insnCount;
-
- if (address >= end) {
- min = guess + 1;
- continue;
- }
-
- // We have a winner!
- return (int) pTry->handlerOff;
- }
-
- // No match.
- return -1;
-}
-
-/* Get the handler offset just past the end of the one just iterated over.
- * This ends the iteration if it wasn't already. */
-u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator,
- const DexCode* pCode) {
- while (dexCatchIteratorNext(pIterator) != NULL) /* empty */ ;
-
- return (u4) (pIterator->pEncodedData - dexGetCatchHandlerData(pCode));
-}
diff --git a/libdex/DexCatch.h b/libdex/DexCatch.h
deleted file mode 100644
index cfea2d900..000000000
--- a/libdex/DexCatch.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions for dealing with try-catch info.
- */
-
-#ifndef LIBDEX_DEXCATCH_H_
-#define LIBDEX_DEXCATCH_H_
-
-#include "DexFile.h"
-#include "Leb128.h"
-
-/*
- * Catch handler entry, used while iterating over catch_handler_items.
- */
-struct DexCatchHandler {
- u4 typeIdx; /* type index of the caught exception type */
- u4 address; /* handler address */
-};
-
-/* Get the first handler offset for the given DexCode.
- * It's not 0 because the handlers list is prefixed with its size
- * (in entries) as a uleb128. */
-u4 dexGetFirstHandlerOffset(const DexCode* pCode);
-
-/* Get count of handler lists for the given DexCode. */
-u4 dexGetHandlersSize(const DexCode* pCode);
-
-/*
- * Iterator over catch handler data. This structure should be treated as
- * opaque.
- */
-struct DexCatchIterator {
- const u1* pEncodedData;
- bool catchesAll;
- u4 countRemaining;
- DexCatchHandler handler;
-};
-
-/* Initialize a DexCatchIterator to emptiness. This mostly exists to
- * squelch innocuous warnings. */
-DEX_INLINE void dexCatchIteratorClear(DexCatchIterator* pIterator) {
- pIterator->pEncodedData = NULL;
- pIterator->catchesAll = false;
- pIterator->countRemaining = 0;
- pIterator->handler.typeIdx = 0;
- pIterator->handler.address = 0;
-}
-
-/* Initialize a DexCatchIterator with a direct pointer to encoded handlers. */
-DEX_INLINE void dexCatchIteratorInitToPointer(DexCatchIterator* pIterator,
- const u1* pEncodedData)
-{
- s4 count = readSignedLeb128(&pEncodedData);
-
- if (count <= 0) {
- pIterator->catchesAll = true;
- count = -count;
- } else {
- pIterator->catchesAll = false;
- }
-
- pIterator->pEncodedData = pEncodedData;
- pIterator->countRemaining = count;
-}
-
-/* Initialize a DexCatchIterator to a particular handler offset. */
-DEX_INLINE void dexCatchIteratorInit(DexCatchIterator* pIterator,
- const DexCode* pCode, u4 offset)
-{
- dexCatchIteratorInitToPointer(pIterator,
- dexGetCatchHandlerData(pCode) + offset);
-}
-
-/* Get the next item from a DexCatchIterator. Returns NULL if at end. */
-DEX_INLINE DexCatchHandler* dexCatchIteratorNext(DexCatchIterator* pIterator) {
- if (pIterator->countRemaining == 0) {
- if (! pIterator->catchesAll) {
- return NULL;
- }
-
- pIterator->catchesAll = false;
- pIterator->handler.typeIdx = kDexNoIndex;
- } else {
- u4 typeIdx = readUnsignedLeb128(&pIterator->pEncodedData);
- pIterator->handler.typeIdx = typeIdx;
- pIterator->countRemaining--;
- }
-
- pIterator->handler.address = readUnsignedLeb128(&pIterator->pEncodedData);
- return &pIterator->handler;
-}
-
-/* Get the handler offset just past the end of the one just iterated over.
- * This ends the iteration if it wasn't already. */
-u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator,
- const DexCode* pCode);
-
-/* Helper for dexFindCatchHandler(). Do not call directly. */
-int dexFindCatchHandlerOffset0(u2 triesSize, const DexTry* pTries,
- u4 address);
-
-/* Find the handler associated with a given address, if any.
- * Initializes the given iterator and returns true if a match is
- * found. Returns false if there is no applicable handler. */
-DEX_INLINE bool dexFindCatchHandler(DexCatchIterator *pIterator,
- const DexCode* pCode, u4 address) {
- u2 triesSize = pCode->triesSize;
- int offset = -1;
-
- // Short-circuit the overwhelmingly common cases.
- switch (triesSize) {
- case 0: {
- break;
- }
- case 1: {
- const DexTry* tries = dexGetTries(pCode);
- u4 start = tries[0].startAddr;
-
- if (address < start) {
- break;
- }
-
- u4 end = start + tries[0].insnCount;
-
- if (address >= end) {
- break;
- }
-
- offset = tries[0].handlerOff;
- break;
- }
- default: {
- offset = dexFindCatchHandlerOffset0(triesSize, dexGetTries(pCode),
- address);
- }
- }
-
- if (offset < 0) {
- dexCatchIteratorClear(pIterator); // This squelches warnings.
- return false;
- } else {
- dexCatchIteratorInit(pIterator, pCode, offset);
- return true;
- }
-}
-
-#endif // LIBDEX_DEXCATCH_H_
diff --git a/libdex/DexClass.cpp b/libdex/DexClass.cpp
deleted file mode 100644
index a33906c94..000000000
--- a/libdex/DexClass.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions to deal with class definition structures in DEX files
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "DexClass.h"
-#include "Leb128.h"
-
-/* Helper for verification which reads and verifies a given number
- * of uleb128 values. */
-static bool verifyUlebs(const u1* pData, const u1* pLimit, u4 count) {
- bool okay = true;
-
- while (okay && (count-- != 0)) {
- readAndVerifyUnsignedLeb128(&pData, pLimit, &okay);
- }
-
- return okay;
-}
-
-/* Read and verify the header of a class_data_item. This updates the
- * given data pointer to point past the end of the read data and
- * returns an "okay" flag (that is, false == failure). */
-bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit,
- DexClassDataHeader *pHeader) {
- if (! verifyUlebs(*pData, pLimit, 4)) {
- return false;
- }
-
- dexReadClassDataHeader(pData, pHeader);
- return true;
-}
-
-/* Read and verify an encoded_field. This updates the
- * given data pointer to point past the end of the read data and
- * returns an "okay" flag (that is, false == failure).
- *
- * The lastIndex value should be set to 0 before the first field in
- * a list is read. It is updated as fields are read and used in the
- * decode process.
- *
- * The verification done by this function is of the raw data format
- * only; it does not verify that access flags or indices
- * are valid. */
-bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit,
- DexField* pField, u4* lastIndex) {
- if (! verifyUlebs(*pData, pLimit, 2)) {
- return false;
- }
-
- dexReadClassDataField(pData, pField, lastIndex);
- return true;
-}
-
-/* Read and verify an encoded_method. This updates the
- * given data pointer to point past the end of the read data and
- * returns an "okay" flag (that is, false == failure).
- *
- * The lastIndex value should be set to 0 before the first method in
- * a list is read. It is updated as fields are read and used in the
- * decode process.
- *
- * The verification done by this function is of the raw data format
- * only; it does not verify that access flags, indices, or offsets
- * are valid. */
-bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit,
- DexMethod* pMethod, u4* lastIndex) {
- if (! verifyUlebs(*pData, pLimit, 3)) {
- return false;
- }
-
- dexReadClassDataMethod(pData, pMethod, lastIndex);
- return true;
-}
-
-/* Read, verify, and return an entire class_data_item. This updates
- * the given data pointer to point past the end of the read data. This
- * function allocates a single chunk of memory for the result, which
- * must subsequently be free()d. This function returns NULL if there
- * was trouble parsing the data. If this function is passed NULL, it
- * returns an initialized empty DexClassData structure.
- *
- * The verification done by this function is of the raw data format
- * only; it does not verify that access flags, indices, or offsets
- * are valid. */
-DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit) {
- DexClassDataHeader header;
- u4 lastIndex;
-
- if (*pData == NULL) {
- DexClassData* result = (DexClassData*) malloc(sizeof(DexClassData));
- memset(result, 0, sizeof(*result));
- return result;
- }
-
- if (! dexReadAndVerifyClassDataHeader(pData, pLimit, &header)) {
- return NULL;
- }
-
- size_t resultSize = sizeof(DexClassData) +
- (header.staticFieldsSize * sizeof(DexField)) +
- (header.instanceFieldsSize * sizeof(DexField)) +
- (header.directMethodsSize * sizeof(DexMethod)) +
- (header.virtualMethodsSize * sizeof(DexMethod));
-
- DexClassData* result = (DexClassData*) malloc(resultSize);
- u1* ptr = ((u1*) result) + sizeof(DexClassData);
- bool okay = true;
- u4 i;
-
- if (result == NULL) {
- return NULL;
- }
-
- result->header = header;
-
- if (header.staticFieldsSize != 0) {
- result->staticFields = (DexField*) ptr;
- ptr += header.staticFieldsSize * sizeof(DexField);
- } else {
- result->staticFields = NULL;
- }
-
- if (header.instanceFieldsSize != 0) {
- result->instanceFields = (DexField*) ptr;
- ptr += header.instanceFieldsSize * sizeof(DexField);
- } else {
- result->instanceFields = NULL;
- }
-
- if (header.directMethodsSize != 0) {
- result->directMethods = (DexMethod*) ptr;
- ptr += header.directMethodsSize * sizeof(DexMethod);
- } else {
- result->directMethods = NULL;
- }
-
- if (header.virtualMethodsSize != 0) {
- result->virtualMethods = (DexMethod*) ptr;
- } else {
- result->virtualMethods = NULL;
- }
-
- lastIndex = 0;
- for (i = 0; okay && (i < header.staticFieldsSize); i++) {
- okay = dexReadAndVerifyClassDataField(pData, pLimit,
- &result->staticFields[i], &lastIndex);
- }
-
- lastIndex = 0;
- for (i = 0; okay && (i < header.instanceFieldsSize); i++) {
- okay = dexReadAndVerifyClassDataField(pData, pLimit,
- &result->instanceFields[i], &lastIndex);
- }
-
- lastIndex = 0;
- for (i = 0; okay && (i < header.directMethodsSize); i++) {
- okay = dexReadAndVerifyClassDataMethod(pData, pLimit,
- &result->directMethods[i], &lastIndex);
- }
-
- lastIndex = 0;
- for (i = 0; okay && (i < header.virtualMethodsSize); i++) {
- okay = dexReadAndVerifyClassDataMethod(pData, pLimit,
- &result->virtualMethods[i], &lastIndex);
- }
-
- if (! okay) {
- free(result);
- return NULL;
- }
-
- return result;
-}
diff --git a/libdex/DexClass.h b/libdex/DexClass.h
deleted file mode 100644
index 11b3b0eee..000000000
--- a/libdex/DexClass.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions to deal with class definition structures in DEX files
- */
-
-#ifndef LIBDEX_DEXCLASS_H_
-#define LIBDEX_DEXCLASS_H_
-
-#include "DexFile.h"
-#include "Leb128.h"
-
-/* expanded form of a class_data_item header */
-struct DexClassDataHeader {
- u4 staticFieldsSize;
- u4 instanceFieldsSize;
- u4 directMethodsSize;
- u4 virtualMethodsSize;
-};
-
-/* expanded form of encoded_field */
-struct DexField {
- u4 fieldIdx; /* index to a field_id_item */
- u4 accessFlags;
-};
-
-/* expanded form of encoded_method */
-struct DexMethod {
- u4 methodIdx; /* index to a method_id_item */
- u4 accessFlags;
- u4 codeOff; /* file offset to a code_item */
-};
-
-/* expanded form of class_data_item. Note: If a particular item is
- * absent (e.g., no static fields), then the corresponding pointer
- * is set to NULL. */
-struct DexClassData {
- DexClassDataHeader header;
- DexField* staticFields;
- DexField* instanceFields;
- DexMethod* directMethods;
- DexMethod* virtualMethods;
-};
-
-/* Read and verify the header of a class_data_item. This updates the
- * given data pointer to point past the end of the read data and
- * returns an "okay" flag (that is, false == failure). */
-bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit,
- DexClassDataHeader *pHeader);
-
-/* Read and verify an encoded_field. This updates the
- * given data pointer to point past the end of the read data and
- * returns an "okay" flag (that is, false == failure).
- *
- * The lastIndex value should be set to 0 before the first field in
- * a list is read. It is updated as fields are read and used in the
- * decode process.
- *
- * The verification done by this function is of the raw data format
- * only; it does not verify that access flags or indices
- * are valid. */
-bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit,
- DexField* pField, u4* lastIndex);
-
-/* Read and verify an encoded_method. This updates the
- * given data pointer to point past the end of the read data and
- * returns an "okay" flag (that is, false == failure).
- *
- * The lastIndex value should be set to 0 before the first method in
- * a list is read. It is updated as fields are read and used in the
- * decode process.
- *
- * The verification done by this function is of the raw data format
- * only; it does not verify that access flags, indices, or offsets
- * are valid. */
-bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit,
- DexMethod* pMethod, u4* lastIndex);
-
-/* Read, verify, and return an entire class_data_item. This updates
- * the given data pointer to point past the end of the read data. This
- * function allocates a single chunk of memory for the result, which
- * must subsequently be free()d. This function returns NULL if there
- * was trouble parsing the data. If this function is passed NULL, it
- * returns an initialized empty DexClassData structure.
- *
- * The verification done by this function is of the raw data format
- * only; it does not verify that access flags, indices, or offsets
- * are valid. */
-DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit);
-
-/*
- * Get the DexCode for a DexMethod. Returns NULL if the class is native
- * or abstract.
- */
-DEX_INLINE const DexCode* dexGetCode(const DexFile* pDexFile,
- const DexMethod* pDexMethod)
-{
- if (pDexMethod->codeOff == 0)
- return NULL;
- return (const DexCode*) (pDexFile->baseAddr + pDexMethod->codeOff);
-}
-
-
-/* Read the header of a class_data_item without verification. This
- * updates the given data pointer to point past the end of the read
- * data. */
-DEX_INLINE void dexReadClassDataHeader(const u1** pData,
- DexClassDataHeader *pHeader) {
- pHeader->staticFieldsSize = readUnsignedLeb128(pData);
- pHeader->instanceFieldsSize = readUnsignedLeb128(pData);
- pHeader->directMethodsSize = readUnsignedLeb128(pData);
- pHeader->virtualMethodsSize = readUnsignedLeb128(pData);
-}
-
-/* Read an encoded_field without verification. This updates the
- * given data pointer to point past the end of the read data.
- *
- * The lastIndex value should be set to 0 before the first field in
- * a list is read. It is updated as fields are read and used in the
- * decode process.
- */
-DEX_INLINE void dexReadClassDataField(const u1** pData, DexField* pField,
- u4* lastIndex) {
- u4 index = *lastIndex + readUnsignedLeb128(pData);
-
- pField->accessFlags = readUnsignedLeb128(pData);
- pField->fieldIdx = index;
- *lastIndex = index;
-}
-
-/* Read an encoded_method without verification. This updates the
- * given data pointer to point past the end of the read data.
- *
- * The lastIndex value should be set to 0 before the first method in
- * a list is read. It is updated as fields are read and used in the
- * decode process.
- */
-DEX_INLINE void dexReadClassDataMethod(const u1** pData, DexMethod* pMethod,
- u4* lastIndex) {
- u4 index = *lastIndex + readUnsignedLeb128(pData);
-
- pMethod->accessFlags = readUnsignedLeb128(pData);
- pMethod->codeOff = readUnsignedLeb128(pData);
- pMethod->methodIdx = index;
- *lastIndex = index;
-}
-
-#endif // LIBDEX_DEXCLASS_H_
diff --git a/libdex/DexDataMap.cpp b/libdex/DexDataMap.cpp
deleted file mode 100644
index 18e4a4519..000000000
--- a/libdex/DexDataMap.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Verification-time map of data section items
- */
-
-#include "DexDataMap.h"
-#include <stdlib.h>
-
-/*
- * Allocate and initialize a DexDataMap. Returns NULL on failure.
- */
-DexDataMap* dexDataMapAlloc(u4 maxCount) {
- /*
- * Allocate a single chunk for the DexDataMap itself as well as the
- * two arrays.
- */
- size_t size = 0;
- DexDataMap* map = NULL;
-
- const u4 sizeOfItems = (u4) (sizeof(u4) + sizeof(u2));
- if (__builtin_mul_overflow(maxCount, sizeOfItems, &size) ||
- __builtin_add_overflow(size, sizeof(DexDataMap), &size)) {
- return NULL;
- }
-
- map = (DexDataMap*) malloc(size);
-
- if (map == NULL) {
- return NULL;
- }
-
- map->count = 0;
- map->max = maxCount;
- map->offsets = (u4*) (map + 1);
- map->types = (u2*) (map->offsets + maxCount);
-
- return map;
-}
-
-/*
- * Free a DexDataMap.
- */
-void dexDataMapFree(DexDataMap* map) {
- /*
- * Since everything got allocated together, everything can be freed
- * in one fell swoop. Also, free(NULL) is a nop (per spec), so we
- * don't have to worry about an explicit test for that.
- */
- free(map);
-}
-
-/*
- * Add a new element to the map. The offset must be greater than the
- * all previously added offsets.
- */
-void dexDataMapAdd(DexDataMap* map, u4 offset, u2 type) {
- assert(map != NULL);
- assert(map->count < map->max);
-
- if ((map->count != 0) &&
- (map->offsets[map->count - 1] >= offset)) {
- ALOGE("Out-of-order data map offset: %#x then %#x",
- map->offsets[map->count - 1], offset);
- return;
- }
-
- map->offsets[map->count] = offset;
- map->types[map->count] = type;
- map->count++;
-}
-
-/*
- * Get the type associated with the given offset. This returns -1 if
- * there is no entry for the given offset.
- */
-int dexDataMapGet(DexDataMap* map, u4 offset) {
- assert(map != NULL);
-
- // Note: Signed type is important for max and min.
- int min = 0;
- int max = map->count - 1;
- u4* offsets = map->offsets;
-
- while (max >= min) {
- int guessIdx = (min + max) >> 1;
- u4 guess = offsets[guessIdx];
-
- if (offset < guess) {
- max = guessIdx - 1;
- } else if (offset > guess) {
- min = guessIdx + 1;
- } else {
- // We have a winner!
- return map->types[guessIdx];
- }
- }
-
- // No match.
- return -1;
-}
-
-/*
- * Verify that there is an entry in the map, mapping the given offset to
- * the given type. This will return true if such an entry exists and
- * return false as well as log an error if not.
- */
-bool dexDataMapVerify(DexDataMap* map, u4 offset, u2 type) {
- int found = dexDataMapGet(map, offset);
-
- if (found == type) {
- return true;
- }
-
- if (found < 0) {
- ALOGE("No data map entry found @ %#x; expected %x",
- offset, type);
- } else {
- ALOGE("Unexpected data map entry @ %#x: expected %x, found %x",
- offset, type, found);
- }
-
- return false;
-}
diff --git a/libdex/DexDataMap.h b/libdex/DexDataMap.h
deleted file mode 100644
index 7e43dc934..000000000
--- a/libdex/DexDataMap.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Verification-time map of data section items
- */
-
-#ifndef LIBDEX_DEXDATAMAP_H_
-#define LIBDEX_DEXDATAMAP_H_
-
-#include "DexFile.h"
-
-struct DexDataMap {
- u4 count; /* number of items currently in the map */
- u4 max; /* maximum number of items that may be held */
- u4* offsets; /* array of item offsets */
- u2* types; /* corresponding array of item types */
-};
-
-/*
- * Allocate and initialize a DexDataMap. Returns NULL on failure.
- */
-DexDataMap* dexDataMapAlloc(u4 maxCount);
-
-/*
- * Free a DexDataMap.
- */
-void dexDataMapFree(DexDataMap* map);
-
-/*
- * Add a new element to the map. The offset must be greater than the
- * all previously added offsets.
- */
-void dexDataMapAdd(DexDataMap* map, u4 offset, u2 type);
-
-/*
- * Get the type associated with the given offset. This returns -1 if
- * there is no entry for the given offset.
- */
-int dexDataMapGet(DexDataMap* map, u4 offset);
-
-/*
- * Verify that there is an entry in the map, mapping the given offset to
- * the given type. This will return true if such an entry exists and
- * return false as well as log an error if not.
- */
-bool dexDataMapVerify(DexDataMap* map, u4 offset, u2 type);
-
-/*
- * Like dexDataMapVerify(), but also accept a 0 offset as valid.
- */
-DEX_INLINE bool dexDataMapVerify0Ok(DexDataMap* map, u4 offset, u2 type) {
- if (offset == 0) {
- return true;
- }
-
- return dexDataMapVerify(map, offset, type);
-}
-
-#endif // LIBDEX_DEXDATAMAP_H_
diff --git a/libdex/DexDebugInfo.cpp b/libdex/DexDebugInfo.cpp
deleted file mode 100644
index 5f9ffbe0f..000000000
--- a/libdex/DexDebugInfo.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Handling of method debug info in a .dex file.
- */
-
-#include "DexDebugInfo.h"
-#include "DexProto.h"
-#include "Leb128.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * Reads a string index as encoded for the debug info format,
- * returning a string pointer or NULL as appropriate.
- */
-static const char* readStringIdx(const DexFile* pDexFile,
- const u1** pStream) {
- u4 stringIdx = readUnsignedLeb128(pStream);
-
- // Remember, encoded string indicies have 1 added to them.
- if (stringIdx == 0) {
- return NULL;
- } else {
- return dexStringById(pDexFile, stringIdx - 1);
- }
-}
-
-/*
- * Reads a type index as encoded for the debug info format, returning
- * a string pointer for its descriptor or NULL as appropriate.
- */
-static const char* readTypeIdx(const DexFile* pDexFile,
- const u1** pStream) {
- u4 typeIdx = readUnsignedLeb128(pStream);
-
- // Remember, encoded type indicies have 1 added to them.
- if (typeIdx == 0) {
- return NULL;
- } else {
- return dexStringByTypeIdx(pDexFile, typeIdx - 1);
- }
-}
-
-struct LocalInfo {
- const char *name;
- const char *descriptor;
- const char *signature;
- u2 startAddress;
- bool live;
-};
-
-static void emitLocalCbIfLive(void *cnxt, int reg, u4 endAddress,
- LocalInfo *localInReg, DexDebugNewLocalCb localCb)
-{
- if (localCb != NULL && localInReg[reg].live) {
- localCb(cnxt, reg, localInReg[reg].startAddress, endAddress,
- localInReg[reg].name,
- localInReg[reg].descriptor,
- localInReg[reg].signature == NULL
- ? "" : localInReg[reg].signature );
- }
-}
-
-static void invalidStream(const char* classDescriptor, const DexProto* proto) {
- IF_ALOGE() {
- char* methodDescriptor = dexProtoCopyMethodDescriptor(proto);
- ALOGE("Invalid debug info stream. class %s; proto %s",
- classDescriptor, methodDescriptor);
- free(methodDescriptor);
- }
-}
-
-static void dexDecodeDebugInfo0(
- const DexFile* pDexFile,
- const DexCode* pCode,
- const char* classDescriptor,
- u4 protoIdx,
- u4 accessFlags,
- DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb,
- void* cnxt,
- const u1* stream,
- LocalInfo* localInReg)
-{
- DexProto proto = { pDexFile, protoIdx };
- u4 line = readUnsignedLeb128(&stream);
- u4 parametersSize = readUnsignedLeb128(&stream);
- u2 argReg = pCode->registersSize - pCode->insSize;
- u4 address = 0;
-
- if ((accessFlags & ACC_STATIC) == 0) {
- /*
- * The code is an instance method, which means that there is
- * an initial this parameter. Also, the proto list should
- * contain exactly one fewer argument word than the insSize
- * indicates.
- */
- assert(pCode->insSize == (dexProtoComputeArgsSize(&proto) + 1));
- localInReg[argReg].name = "this";
- localInReg[argReg].descriptor = classDescriptor;
- localInReg[argReg].startAddress = 0;
- localInReg[argReg].live = true;
- argReg++;
- } else {
- assert(pCode->insSize == dexProtoComputeArgsSize(&proto));
- }
-
- DexParameterIterator iterator;
- dexParameterIteratorInit(&iterator, &proto);
-
- while (parametersSize-- != 0) {
- const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
- const char *name;
- int reg;
-
- if ((argReg >= pCode->registersSize) || (descriptor == NULL)) {
- invalidStream(classDescriptor, &proto);
- return;
- }
-
- name = readStringIdx(pDexFile, &stream);
- reg = argReg;
-
- switch (descriptor[0]) {
- case 'D':
- case 'J':
- argReg += 2;
- break;
- default:
- argReg += 1;
- break;
- }
-
- if (name != NULL) {
- localInReg[reg].name = name;
- localInReg[reg].descriptor = descriptor;
- localInReg[reg].signature = NULL;
- localInReg[reg].startAddress = address;
- localInReg[reg].live = true;
- }
- }
-
- for (;;) {
- u1 opcode = *stream++;
- u2 reg;
-
- switch (opcode) {
- case DBG_END_SEQUENCE:
- return;
-
- case DBG_ADVANCE_PC:
- address += readUnsignedLeb128(&stream);
- break;
-
- case DBG_ADVANCE_LINE:
- line += readSignedLeb128(&stream);
- break;
-
- case DBG_START_LOCAL:
- case DBG_START_LOCAL_EXTENDED:
- reg = readUnsignedLeb128(&stream);
- if (reg > pCode->registersSize) {
- invalidStream(classDescriptor, &proto);
- return;
- }
-
- // Emit what was previously there, if anything
- emitLocalCbIfLive(cnxt, reg, address,
- localInReg, localCb);
-
- localInReg[reg].name = readStringIdx(pDexFile, &stream);
- localInReg[reg].descriptor = readTypeIdx(pDexFile, &stream);
- if (opcode == DBG_START_LOCAL_EXTENDED) {
- localInReg[reg].signature
- = readStringIdx(pDexFile, &stream);
- } else {
- localInReg[reg].signature = NULL;
- }
- localInReg[reg].startAddress = address;
- localInReg[reg].live = true;
- break;
-
- case DBG_END_LOCAL:
- reg = readUnsignedLeb128(&stream);
- if (reg > pCode->registersSize) {
- invalidStream(classDescriptor, &proto);
- return;
- }
-
- emitLocalCbIfLive (cnxt, reg, address, localInReg, localCb);
- localInReg[reg].live = false;
- break;
-
- case DBG_RESTART_LOCAL:
- reg = readUnsignedLeb128(&stream);
- if (reg > pCode->registersSize) {
- invalidStream(classDescriptor, &proto);
- return;
- }
-
- if (localInReg[reg].name == NULL
- || localInReg[reg].descriptor == NULL) {
- invalidStream(classDescriptor, &proto);
- return;
- }
-
- /*
- * If the register is live, the "restart" is superfluous,
- * and we don't want to mess with the existing start address.
- */
- if (!localInReg[reg].live) {
- localInReg[reg].startAddress = address;
- localInReg[reg].live = true;
- }
- break;
-
- case DBG_SET_PROLOGUE_END:
- case DBG_SET_EPILOGUE_BEGIN:
- case DBG_SET_FILE:
- break;
-
- default: {
- int adjopcode = opcode - DBG_FIRST_SPECIAL;
-
- address += adjopcode / DBG_LINE_RANGE;
- line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
-
- if (posCb != NULL) {
- int done;
- done = posCb(cnxt, address, line);
-
- if (done) {
- // early exit
- return;
- }
- }
- break;
- }
- }
- }
-}
-
-// TODO optimize localCb == NULL case
-void dexDecodeDebugInfo(
- const DexFile* pDexFile,
- const DexCode* pCode,
- const char* classDescriptor,
- u4 protoIdx,
- u4 accessFlags,
- DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb,
- void* cnxt)
-{
- const u1* stream = dexGetDebugInfoStream(pDexFile, pCode);
- LocalInfo localInReg[pCode->registersSize];
-
- memset(localInReg, 0, sizeof(LocalInfo) * pCode->registersSize);
-
- if (stream != NULL) {
- dexDecodeDebugInfo0(pDexFile, pCode, classDescriptor, protoIdx, accessFlags,
- posCb, localCb, cnxt, stream, localInReg);
- }
-
- for (int reg = 0; reg < pCode->registersSize; reg++) {
- emitLocalCbIfLive(cnxt, reg, pCode->insnsSize, localInReg, localCb);
- }
-}
diff --git a/libdex/DexDebugInfo.h b/libdex/DexDebugInfo.h
deleted file mode 100644
index bd0954c8c..000000000
--- a/libdex/DexDebugInfo.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Handling of method debug info in a .dex file.
- */
-
-#ifndef LIBDEX_DEXDEBUGINFO_H_
-#define LIBDEX_DEXDEBUGINFO_H_
-
-#include "DexFile.h"
-
-/*
- * Callback for "new position table entry".
- * Returning non-0 causes the decoder to stop early.
- */
-typedef int (*DexDebugNewPositionCb)(void *cnxt, u4 address, u4 lineNum);
-
-/*
- * Callback for "new locals table entry". "signature" is an empty string
- * if no signature is available for an entry.
- */
-typedef void (*DexDebugNewLocalCb)(void *cnxt, u2 reg, u4 startAddress,
- u4 endAddress, const char *name, const char *descriptor,
- const char *signature);
-
-/*
- * Decode debug info for method.
- *
- * posCb is called in ascending address order.
- * localCb is called in order of ascending end address.
- */
-void dexDecodeDebugInfo(
- const DexFile* pDexFile,
- const DexCode* pDexCode,
- const char* classDescriptor,
- u4 protoIdx,
- u4 accessFlags,
- DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb,
- void* cnxt);
-
-#endif // LIBDEX_DEXDEBUGINFO_H_
diff --git a/libdex/DexFile.cpp b/libdex/DexFile.cpp
deleted file mode 100644
index d9acd5188..000000000
--- a/libdex/DexFile.cpp
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Access the contents of a .dex file.
- */
-
-#include "DexFile.h"
-#include "DexOptData.h"
-#include "DexProto.h"
-#include "DexCatch.h"
-#include "Leb128.h"
-#include "sha1.h"
-#include "ZipArchive.h"
-
-#include <zlib.h>
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-
-
-/*
- * Verifying checksums is good, but it slows things down and causes us to
- * touch every page. In the "optimized" world, it doesn't work at all,
- * because we rewrite the contents.
- */
-static const bool kVerifySignature = false;
-
-/* (documented in header) */
-char dexGetPrimitiveTypeDescriptorChar(PrimitiveType type) {
- const char* string = dexGetPrimitiveTypeDescriptor(type);
-
- return (string == NULL) ? '\0' : string[0];
-}
-
-/* (documented in header) */
-const char* dexGetPrimitiveTypeDescriptor(PrimitiveType type) {
- switch (type) {
- case PRIM_VOID: return "V";
- case PRIM_BOOLEAN: return "Z";
- case PRIM_BYTE: return "B";
- case PRIM_SHORT: return "S";
- case PRIM_CHAR: return "C";
- case PRIM_INT: return "I";
- case PRIM_LONG: return "J";
- case PRIM_FLOAT: return "F";
- case PRIM_DOUBLE: return "D";
- default: return NULL;
- }
-
- return NULL;
-}
-
-/* (documented in header) */
-const char* dexGetBoxedTypeDescriptor(PrimitiveType type) {
- switch (type) {
- case PRIM_VOID: return NULL;
- case PRIM_BOOLEAN: return "Ljava/lang/Boolean;";
- case PRIM_BYTE: return "Ljava/lang/Byte;";
- case PRIM_SHORT: return "Ljava/lang/Short;";
- case PRIM_CHAR: return "Ljava/lang/Character;";
- case PRIM_INT: return "Ljava/lang/Integer;";
- case PRIM_LONG: return "Ljava/lang/Long;";
- case PRIM_FLOAT: return "Ljava/lang/Float;";
- case PRIM_DOUBLE: return "Ljava/lang/Double;";
- default: return NULL;
- }
-}
-
-/* (documented in header) */
-PrimitiveType dexGetPrimitiveTypeFromDescriptorChar(char descriptorChar) {
- switch (descriptorChar) {
- case 'V': return PRIM_VOID;
- case 'Z': return PRIM_BOOLEAN;
- case 'B': return PRIM_BYTE;
- case 'S': return PRIM_SHORT;
- case 'C': return PRIM_CHAR;
- case 'I': return PRIM_INT;
- case 'J': return PRIM_LONG;
- case 'F': return PRIM_FLOAT;
- case 'D': return PRIM_DOUBLE;
- default: return PRIM_NOT;
- }
-}
-
-/* Return the UTF-8 encoded string with the specified string_id index,
- * also filling in the UTF-16 size (number of 16-bit code points).*/
-const char* dexStringAndSizeById(const DexFile* pDexFile, u4 idx,
- u4* utf16Size) {
- const DexStringId* pStringId = dexGetStringId(pDexFile, idx);
- const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff;
-
- *utf16Size = readUnsignedLeb128(&ptr);
- return (const char*) ptr;
-}
-
-/*
- * Format an SHA-1 digest for printing. tmpBuf must be able to hold at
- * least kSHA1DigestOutputLen bytes.
- */
-const char* dvmSHA1DigestToStr(const unsigned char digest[], char* tmpBuf);
-
-/*
- * Compute a SHA-1 digest on a range of bytes.
- */
-static void dexComputeSHA1Digest(const unsigned char* data, size_t length,
- unsigned char digest[])
-{
- SHA1_CTX context;
- SHA1Init(&context);
- SHA1Update(&context, data, length);
- SHA1Final(digest, &context);
-}
-
-/*
- * Format the SHA-1 digest into the buffer, which must be able to hold at
- * least kSHA1DigestOutputLen bytes. Returns a pointer to the buffer,
- */
-static const char* dexSHA1DigestToStr(const unsigned char digest[],char* tmpBuf)
-{
- static const char hexDigit[] = "0123456789abcdef";
- char* cp;
- int i;
-
- cp = tmpBuf;
- for (i = 0; i < kSHA1DigestLen; i++) {
- *cp++ = hexDigit[digest[i] >> 4];
- *cp++ = hexDigit[digest[i] & 0x0f];
- }
- *cp++ = '\0';
-
- assert(cp == tmpBuf + kSHA1DigestOutputLen);
-
- return tmpBuf;
-}
-
-/*
- * Compute a hash code on a UTF-8 string, for use with internal hash tables.
- *
- * This may or may not be compatible with UTF-8 hash functions used inside
- * the Dalvik VM.
- *
- * The basic "multiply by 31 and add" approach does better on class names
- * than most other things tried (e.g. adler32).
- */
-static u4 classDescriptorHash(const char* str)
-{
- u4 hash = 1;
-
- while (*str != '\0')
- hash = hash * 31 + *str++;
-
- return hash;
-}
-
-/*
- * Add an entry to the class lookup table. We hash the string and probe
- * until we find an open slot.
- */
-static void classLookupAdd(DexFile* pDexFile, DexClassLookup* pLookup,
- int stringOff, int classDefOff, int* pNumProbes)
-{
- const char* classDescriptor =
- (const char*) (pDexFile->baseAddr + stringOff);
- u4 hash = classDescriptorHash(classDescriptor);
- int mask = pLookup->numEntries-1;
- int idx = hash & mask;
-
- /*
- * Find the first empty slot. We oversized the table, so this is
- * guaranteed to finish.
- */
- int probes = 0;
- while (pLookup->table[idx].classDescriptorOffset != 0) {
- idx = (idx + 1) & mask;
- probes++;
- }
- //if (probes > 1)
- // ALOGW("classLookupAdd: probes=%d", probes);
-
- pLookup->table[idx].classDescriptorHash = hash;
- pLookup->table[idx].classDescriptorOffset = stringOff;
- pLookup->table[idx].classDefOffset = classDefOff;
- *pNumProbes = probes;
-}
-
-/*
- * Create the class lookup hash table.
- *
- * Returns newly-allocated storage.
- */
-DexClassLookup* dexCreateClassLookup(DexFile* pDexFile)
-{
- DexClassLookup* pLookup;
- int allocSize;
- int i, numEntries;
- int numProbes, totalProbes, maxProbes;
-
- numProbes = totalProbes = maxProbes = 0;
-
- assert(pDexFile != NULL);
-
- /*
- * Using a factor of 3 results in far less probing than a factor of 2,
- * but almost doubles the flash storage requirements for the bootstrap
- * DEX files. The overall impact on class loading performance seems
- * to be minor. We could probably get some performance improvement by
- * using a secondary hash.
- */
- numEntries = dexRoundUpPower2(pDexFile->pHeader->classDefsSize * 2);
- allocSize = offsetof(DexClassLookup, table)
- + numEntries * sizeof(pLookup->table[0]);
-
- pLookup = (DexClassLookup*) calloc(1, allocSize);
- if (pLookup == NULL)
- return NULL;
- pLookup->size = allocSize;
- pLookup->numEntries = numEntries;
-
- for (i = 0; i < (int)pDexFile->pHeader->classDefsSize; i++) {
- const DexClassDef* pClassDef;
- const char* pString;
-
- pClassDef = dexGetClassDef(pDexFile, i);
- pString = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
-
- classLookupAdd(pDexFile, pLookup,
- (u1*)pString - pDexFile->baseAddr,
- (u1*)pClassDef - pDexFile->baseAddr, &numProbes);
-
- if (numProbes > maxProbes)
- maxProbes = numProbes;
- totalProbes += numProbes;
- }
-
- ALOGV("Class lookup: classes=%d slots=%d (%d%% occ) alloc=%d"
- " total=%d max=%d",
- pDexFile->pHeader->classDefsSize, numEntries,
- (100 * pDexFile->pHeader->classDefsSize) / numEntries,
- allocSize, totalProbes, maxProbes);
-
- return pLookup;
-}
-
-
-/*
- * Set up the basic raw data pointers of a DexFile. This function isn't
- * meant for general use.
- */
-void dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data) {
- DexHeader *pHeader = (DexHeader*) data;
-
- pDexFile->baseAddr = data;
- pDexFile->pHeader = pHeader;
- pDexFile->pStringIds = (const DexStringId*) (data + pHeader->stringIdsOff);
- pDexFile->pTypeIds = (const DexTypeId*) (data + pHeader->typeIdsOff);
- pDexFile->pFieldIds = (const DexFieldId*) (data + pHeader->fieldIdsOff);
- pDexFile->pMethodIds = (const DexMethodId*) (data + pHeader->methodIdsOff);
- pDexFile->pProtoIds = (const DexProtoId*) (data + pHeader->protoIdsOff);
- pDexFile->pClassDefs = (const DexClassDef*) (data + pHeader->classDefsOff);
- pDexFile->pLinkData = (const DexLink*) (data + pHeader->linkOff);
-}
-
-/*
- * Parse an optimized or unoptimized .dex file sitting in memory. This is
- * called after the byte-ordering and structure alignment has been fixed up.
- *
- * On success, return a newly-allocated DexFile.
- */
-DexFile* dexFileParse(const u1* data, size_t length, int flags)
-{
- DexFile* pDexFile = NULL;
- const DexHeader* pHeader;
- const u1* magic;
- int result = -1;
-
- if (length < sizeof(DexHeader)) {
- ALOGE("too short to be a valid .dex");
- goto bail; /* bad file format */
- }
-
- pDexFile = (DexFile*) malloc(sizeof(DexFile));
- if (pDexFile == NULL)
- goto bail; /* alloc failure */
- memset(pDexFile, 0, sizeof(DexFile));
-
- /*
- * Peel off the optimized header.
- */
- if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) {
- magic = data;
- if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {
- ALOGE("bad opt version (0x%02x %02x %02x %02x)",
- magic[4], magic[5], magic[6], magic[7]);
- goto bail;
- }
-
- pDexFile->pOptHeader = (const DexOptHeader*) data;
- ALOGV("Good opt header, DEX offset is %d, flags=0x%02x",
- pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);
-
- /* parse the optimized dex file tables */
- if (!dexParseOptData(data, length, pDexFile))
- goto bail;
-
- /* ignore the opt header and appended data from here on out */
- data += pDexFile->pOptHeader->dexOffset;
- length -= pDexFile->pOptHeader->dexOffset;
- if (pDexFile->pOptHeader->dexLength > length) {
- ALOGE("File truncated? stored len=%d, rem len=%d",
- pDexFile->pOptHeader->dexLength, (int) length);
- goto bail;
- }
- length = pDexFile->pOptHeader->dexLength;
- }
-
- dexFileSetupBasicPointers(pDexFile, data);
- pHeader = pDexFile->pHeader;
-
- if (!dexHasValidMagic(pHeader)) {
- goto bail;
- }
-
- /*
- * Verify the checksum(s). This is reasonably quick, but does require
- * touching every byte in the DEX file. The base checksum changes after
- * byte-swapping and DEX optimization.
- */
- if (flags & kDexParseVerifyChecksum) {
- u4 adler = dexComputeChecksum(pHeader);
- if (adler != pHeader->checksum) {
- ALOGE("ERROR: bad checksum (%08x vs %08x)",
- adler, pHeader->checksum);
- if (!(flags & kDexParseContinueOnError))
- goto bail;
- } else {
- ALOGV("+++ adler32 checksum (%08x) verified", adler);
- }
-
- const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
- if (pOptHeader != NULL) {
- adler = dexComputeOptChecksum(pOptHeader);
- if (adler != pOptHeader->checksum) {
- ALOGE("ERROR: bad opt checksum (%08x vs %08x)",
- adler, pOptHeader->checksum);
- if (!(flags & kDexParseContinueOnError))
- goto bail;
- } else {
- ALOGV("+++ adler32 opt checksum (%08x) verified", adler);
- }
- }
- }
-
- /*
- * Verify the SHA-1 digest. (Normally we don't want to do this --
- * the digest is used to uniquely identify the original DEX file, and
- * can't be computed for verification after the DEX is byte-swapped
- * and optimized.)
- */
- if (kVerifySignature) {
- unsigned char sha1Digest[kSHA1DigestLen];
- const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) +
- kSHA1DigestLen;
-
- dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest);
- if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) {
- char tmpBuf1[kSHA1DigestOutputLen];
- char tmpBuf2[kSHA1DigestOutputLen];
- ALOGE("ERROR: bad SHA1 digest (%s vs %s)",
- dexSHA1DigestToStr(sha1Digest, tmpBuf1),
- dexSHA1DigestToStr(pHeader->signature, tmpBuf2));
- if (!(flags & kDexParseContinueOnError))
- goto bail;
- } else {
- ALOGV("+++ sha1 digest verified");
- }
- }
-
- if (pHeader->fileSize != length) {
- ALOGE("ERROR: stored file size (%d) != expected (%d)",
- (int) pHeader->fileSize, (int) length);
- if (!(flags & kDexParseContinueOnError))
- goto bail;
- }
-
- if (pHeader->classDefsSize == 0) {
- ALOGE("ERROR: DEX file has no classes in it, failing");
- goto bail;
- }
-
- /*
- * Success!
- */
- result = 0;
-
-bail:
- if (result != 0 && pDexFile != NULL) {
- dexFileFree(pDexFile);
- pDexFile = NULL;
- }
- return pDexFile;
-}
-
-/*
- * Free up the DexFile and any associated data structures.
- *
- * Note we may be called with a partially-initialized DexFile.
- */
-void dexFileFree(DexFile* pDexFile)
-{
- if (pDexFile == NULL)
- return;
-
- free(pDexFile);
-}
-
-/*
- * Look up a class definition entry by descriptor.
- *
- * "descriptor" should look like "Landroid/debug/Stuff;".
- */
-const DexClassDef* dexFindClass(const DexFile* pDexFile,
- const char* descriptor)
-{
- const DexClassLookup* pLookup = pDexFile->pClassLookup;
- u4 hash;
- int idx, mask;
-
- hash = classDescriptorHash(descriptor);
- mask = pLookup->numEntries - 1;
- idx = hash & mask;
-
- /*
- * Search until we find a matching entry or an empty slot.
- */
- while (true) {
- int offset;
-
- offset = pLookup->table[idx].classDescriptorOffset;
- if (offset == 0)
- return NULL;
-
- if (pLookup->table[idx].classDescriptorHash == hash) {
- const char* str;
-
- str = (const char*) (pDexFile->baseAddr + offset);
- if (strcmp(str, descriptor) == 0) {
- return (const DexClassDef*)
- (pDexFile->baseAddr + pLookup->table[idx].classDefOffset);
- }
- }
-
- idx = (idx + 1) & mask;
- }
-}
-
-
-/*
- * Compute the DEX file checksum for a memory-mapped DEX file.
- */
-u4 dexComputeChecksum(const DexHeader* pHeader)
-{
- const u1* start = (const u1*) pHeader;
-
- uLong adler = adler32(0L, Z_NULL, 0);
- const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
-
- return (u4) adler32(adler, start + nonSum, pHeader->fileSize - nonSum);
-}
-
-/*
- * Compute the size, in bytes, of a DexCode.
- */
-size_t dexGetDexCodeSize(const DexCode* pCode)
-{
- /*
- * The catch handler data is the last entry. It has a variable number
- * of variable-size pieces, so we need to create an iterator.
- */
- u4 handlersSize;
- u4 offset;
- u4 ui;
-
- if (pCode->triesSize != 0) {
- handlersSize = dexGetHandlersSize(pCode);
- offset = dexGetFirstHandlerOffset(pCode);
- } else {
- handlersSize = 0;
- offset = 0;
- }
-
- for (ui = 0; ui < handlersSize; ui++) {
- DexCatchIterator iterator;
- dexCatchIteratorInit(&iterator, pCode, offset);
- offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
- }
-
- const u1* handlerData = dexGetCatchHandlerData(pCode);
-
- //ALOGD("+++ pCode=%p handlerData=%p last offset=%d",
- // pCode, handlerData, offset);
-
- /* return the size of the catch handler + everything before it */
- return (handlerData - (u1*) pCode) + offset;
-}
-
-/*
- * Round up to the next highest power of 2.
- *
- * Found on http://graphics.stanford.edu/~seander/bithacks.html.
- */
-u4 dexRoundUpPower2(u4 val)
-{
- val--;
- val |= val >> 1;
- val |= val >> 2;
- val |= val >> 4;
- val |= val >> 8;
- val |= val >> 16;
- val++;
-
- return val;
-}
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
deleted file mode 100644
index 7fc7d051c..000000000
--- a/libdex/DexFile.h
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Access .dex (Dalvik Executable Format) files. The code here assumes that
- * the DEX file has been rewritten (byte-swapped, word-aligned) and that
- * the contents can be directly accessed as a collection of C arrays. Please
- * see docs/dalvik/dex-format.html for a detailed description.
- *
- * The structure and field names were chosen to match those in the DEX spec.
- *
- * It's generally assumed that the DEX file will be stored in shared memory,
- * obviating the need to copy code and constant pool entries into newly
- * allocated storage. Maintaining local pointers to items in the shared area
- * is valid and encouraged.
- *
- * All memory-mapped structures are 32-bit aligned unless otherwise noted.
- */
-
-#ifndef LIBDEX_DEXFILE_H_
-#define LIBDEX_DEXFILE_H_
-
-/*
- * Annotation to tell clang that we intend to fall through from one case to
- * another in a switch. Sourced from android-base/macros.h.
- */
-#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
-
-#ifndef LOG_TAG
-# define LOG_TAG "libdex"
-#endif
-#include <log/log.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <assert.h>
-
-/*
- * If "very verbose" logging is enabled, make it equivalent to ALOGV.
- * Otherwise, make it disappear.
- *
- * Define this above the #include "Dalvik.h" to enable for only a
- * single file.
- */
-/* #define VERY_VERBOSE_LOG */
-#if defined(VERY_VERBOSE_LOG)
-# define LOGVV ALOGV
-# define IF_LOGVV() IF_ALOGV()
-#else
-# define LOGVV(...) ((void)0)
-# define IF_LOGVV() if (false)
-#endif
-
-/*
- * These match the definitions in the VM specification.
- */
-typedef uint8_t u1;
-typedef uint16_t u2;
-typedef uint32_t u4;
-typedef uint64_t u8;
-typedef int8_t s1;
-typedef int16_t s2;
-typedef int32_t s4;
-typedef int64_t s8;
-
-#include "libdex/SysUtil.h"
-
-/*
- * gcc-style inline management -- ensures we have a copy of all functions
- * in the library, so code that links against us will work whether or not
- * it was built with optimizations enabled.
- */
-#ifndef _DEX_GEN_INLINES /* only defined by DexInlines.c */
-# define DEX_INLINE extern __inline__
-#else
-# define DEX_INLINE
-#endif
-
-/* DEX file magic number */
-#define DEX_MAGIC "dex\n"
-
-/* The version for android N, encoded in 4 bytes of ASCII. This differentiates dex files that may
- * use default methods.
- */
-#define DEX_MAGIC_VERS_37 "037\0"
-
-/* The version for android O, encoded in 4 bytes of ASCII. This differentiates dex files that may
- * contain invoke-custom, invoke-polymorphic, call-sites, and method handles.
- */
-#define DEX_MAGIC_VERS_38 "038\0"
-
-/* The version for android P, encoded in 4 bytes of ASCII. This differentiates dex files that may
- * contain const-method-handle and const-proto.
- */
-#define DEX_MAGIC_VERS_39 "039\0"
-
-/* current version, encoded in 4 bytes of ASCII */
-#define DEX_MAGIC_VERS "036\0"
-
-/*
- * older but still-recognized version (corresponding to Android API
- * levels 13 and earlier
- */
-#define DEX_MAGIC_VERS_API_13 "035\0"
-
-/* same, but for optimized DEX header */
-#define DEX_OPT_MAGIC "dey\n"
-#define DEX_OPT_MAGIC_VERS "036\0"
-
-#define DEX_DEP_MAGIC "deps"
-
-/*
- * 160-bit SHA-1 digest.
- */
-enum { kSHA1DigestLen = 20,
- kSHA1DigestOutputLen = kSHA1DigestLen*2 +1 };
-
-/* general constants */
-enum {
- kDexEndianConstant = 0x12345678, /* the endianness indicator */
- kDexNoIndex = 0xffffffff, /* not a valid index value */
-};
-
-/*
- * Enumeration of all the primitive types.
- */
-enum PrimitiveType {
- PRIM_NOT = 0, /* value is a reference type, not a primitive type */
- PRIM_VOID = 1,
- PRIM_BOOLEAN = 2,
- PRIM_BYTE = 3,
- PRIM_SHORT = 4,
- PRIM_CHAR = 5,
- PRIM_INT = 6,
- PRIM_LONG = 7,
- PRIM_FLOAT = 8,
- PRIM_DOUBLE = 9,
-};
-
-/*
- * access flags and masks; the "standard" ones are all <= 0x4000
- *
- * Note: There are related declarations in vm/oo/Object.h in the ClassFlags
- * enum.
- */
-enum {
- ACC_PUBLIC = 0x00000001, // class, field, method, ic
- ACC_PRIVATE = 0x00000002, // field, method, ic
- ACC_PROTECTED = 0x00000004, // field, method, ic
- ACC_STATIC = 0x00000008, // field, method, ic
- ACC_FINAL = 0x00000010, // class, field, method, ic
- ACC_SYNCHRONIZED = 0x00000020, // method (only allowed on natives)
- ACC_SUPER = 0x00000020, // class (not used in Dalvik)
- ACC_VOLATILE = 0x00000040, // field
- ACC_BRIDGE = 0x00000040, // method (1.5)
- ACC_TRANSIENT = 0x00000080, // field
- ACC_VARARGS = 0x00000080, // method (1.5)
- ACC_NATIVE = 0x00000100, // method
- ACC_INTERFACE = 0x00000200, // class, ic
- ACC_ABSTRACT = 0x00000400, // class, method, ic
- ACC_STRICT = 0x00000800, // method
- ACC_SYNTHETIC = 0x00001000, // field, method, ic
- ACC_ANNOTATION = 0x00002000, // class, ic (1.5)
- ACC_ENUM = 0x00004000, // class, field, ic (1.5)
- ACC_CONSTRUCTOR = 0x00010000, // method (Dalvik only)
- ACC_DECLARED_SYNCHRONIZED =
- 0x00020000, // method (Dalvik only)
- ACC_CLASS_MASK =
- (ACC_PUBLIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT
- | ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
- ACC_INNER_CLASS_MASK =
- (ACC_CLASS_MASK | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC),
- ACC_FIELD_MASK =
- (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL
- | ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM),
- ACC_METHOD_MASK =
- (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL
- | ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE
- | ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR
- | ACC_DECLARED_SYNCHRONIZED),
-};
-
-/* annotation constants */
-enum {
- kDexVisibilityBuild = 0x00, /* annotation visibility */
- kDexVisibilityRuntime = 0x01,
- kDexVisibilitySystem = 0x02,
-
- kDexAnnotationByte = 0x00,
- kDexAnnotationShort = 0x02,
- kDexAnnotationChar = 0x03,
- kDexAnnotationInt = 0x04,
- kDexAnnotationLong = 0x06,
- kDexAnnotationFloat = 0x10,
- kDexAnnotationDouble = 0x11,
- kDexAnnotationMethodType = 0x15,
- kDexAnnotationMethodHandle = 0x16,
- kDexAnnotationString = 0x17,
- kDexAnnotationType = 0x18,
- kDexAnnotationField = 0x19,
- kDexAnnotationMethod = 0x1a,
- kDexAnnotationEnum = 0x1b,
- kDexAnnotationArray = 0x1c,
- kDexAnnotationAnnotation = 0x1d,
- kDexAnnotationNull = 0x1e,
- kDexAnnotationBoolean = 0x1f,
-
- kDexAnnotationValueTypeMask = 0x1f, /* low 5 bits */
- kDexAnnotationValueArgShift = 5,
-};
-
-/* map item type codes */
-enum {
- kDexTypeHeaderItem = 0x0000,
- kDexTypeStringIdItem = 0x0001,
- kDexTypeTypeIdItem = 0x0002,
- kDexTypeProtoIdItem = 0x0003,
- kDexTypeFieldIdItem = 0x0004,
- kDexTypeMethodIdItem = 0x0005,
- kDexTypeClassDefItem = 0x0006,
- kDexTypeCallSiteIdItem = 0x0007,
- kDexTypeMethodHandleItem = 0x0008,
- kDexTypeMapList = 0x1000,
- kDexTypeTypeList = 0x1001,
- kDexTypeAnnotationSetRefList = 0x1002,
- kDexTypeAnnotationSetItem = 0x1003,
- kDexTypeClassDataItem = 0x2000,
- kDexTypeCodeItem = 0x2001,
- kDexTypeStringDataItem = 0x2002,
- kDexTypeDebugInfoItem = 0x2003,
- kDexTypeAnnotationItem = 0x2004,
- kDexTypeEncodedArrayItem = 0x2005,
- kDexTypeAnnotationsDirectoryItem = 0x2006,
-};
-
-/* auxillary data section chunk codes */
-enum {
- kDexChunkClassLookup = 0x434c4b50, /* CLKP */
- kDexChunkRegisterMaps = 0x524d4150, /* RMAP */
-
- kDexChunkEnd = 0x41454e44, /* AEND */
-};
-
-/* debug info opcodes and constants */
-enum {
- DBG_END_SEQUENCE = 0x00,
- DBG_ADVANCE_PC = 0x01,
- DBG_ADVANCE_LINE = 0x02,
- DBG_START_LOCAL = 0x03,
- DBG_START_LOCAL_EXTENDED = 0x04,
- DBG_END_LOCAL = 0x05,
- DBG_RESTART_LOCAL = 0x06,
- DBG_SET_PROLOGUE_END = 0x07,
- DBG_SET_EPILOGUE_BEGIN = 0x08,
- DBG_SET_FILE = 0x09,
- DBG_FIRST_SPECIAL = 0x0a,
- DBG_LINE_BASE = -4,
- DBG_LINE_RANGE = 15,
-};
-
-/*
- * Direct-mapped "header_item" struct.
- */
-struct DexHeader {
- u1 magic[8]; /* includes version number */
- u4 checksum; /* adler32 checksum */
- u1 signature[kSHA1DigestLen]; /* SHA-1 hash */
- u4 fileSize; /* length of entire file */
- u4 headerSize; /* offset to start of next section */
- u4 endianTag;
- u4 linkSize;
- u4 linkOff;
- u4 mapOff;
- u4 stringIdsSize;
- u4 stringIdsOff;
- u4 typeIdsSize;
- u4 typeIdsOff;
- u4 protoIdsSize;
- u4 protoIdsOff;
- u4 fieldIdsSize;
- u4 fieldIdsOff;
- u4 methodIdsSize;
- u4 methodIdsOff;
- u4 classDefsSize;
- u4 classDefsOff;
- u4 dataSize;
- u4 dataOff;
-};
-
-/*
- * Direct-mapped "map_item".
- */
-struct DexMapItem {
- u2 type; /* type code (see kDexType* above) */
- u2 unused;
- u4 size; /* count of items of the indicated type */
- u4 offset; /* file offset to the start of data */
-};
-
-/*
- * Direct-mapped "map_list".
- */
-struct DexMapList {
- u4 size; /* #of entries in list */
- DexMapItem list[1]; /* entries */
-};
-
-/*
- * Direct-mapped "string_id_item".
- */
-struct DexStringId {
- u4 stringDataOff; /* file offset to string_data_item */
-};
-
-/*
- * Direct-mapped "type_id_item".
- */
-struct DexTypeId {
- u4 descriptorIdx; /* index into stringIds list for type descriptor */
-};
-
-/*
- * Direct-mapped "field_id_item".
- */
-struct DexFieldId {
- u2 classIdx; /* index into typeIds list for defining class */
- u2 typeIdx; /* index into typeIds for field type */
- u4 nameIdx; /* index into stringIds for field name */
-};
-
-/*
- * Direct-mapped "method_id_item".
- */
-struct DexMethodId {
- u2 classIdx; /* index into typeIds list for defining class */
- u2 protoIdx; /* index into protoIds for method prototype */
- u4 nameIdx; /* index into stringIds for method name */
-};
-
-/*
- * Direct-mapped "proto_id_item".
- */
-struct DexProtoId {
- u4 shortyIdx; /* index into stringIds for shorty descriptor */
- u4 returnTypeIdx; /* index into typeIds list for return type */
- u4 parametersOff; /* file offset to type_list for parameter types */
-};
-
-/*
- * Direct-mapped "class_def_item".
- */
-struct DexClassDef {
- u4 classIdx; /* index into typeIds for this class */
- u4 accessFlags;
- u4 superclassIdx; /* index into typeIds for superclass */
- u4 interfacesOff; /* file offset to DexTypeList */
- u4 sourceFileIdx; /* index into stringIds for source file name */
- u4 annotationsOff; /* file offset to annotations_directory_item */
- u4 classDataOff; /* file offset to class_data_item */
- u4 staticValuesOff; /* file offset to DexEncodedArray */
-};
-
-/*
- * Direct-mapped "call_site_id_item"
- */
-struct DexCallSiteId {
- u4 callSiteOff; /* file offset to DexEncodedArray */
-};
-
-/*
- * Enumeration of method handle type codes.
- */
-enum MethodHandleType {
- STATIC_PUT = 0x00,
- STATIC_GET = 0x01,
- INSTANCE_PUT = 0x02,
- INSTANCE_GET = 0x03,
- INVOKE_STATIC = 0x04,
- INVOKE_INSTANCE = 0x05,
- INVOKE_CONSTRUCTOR = 0x06,
- INVOKE_DIRECT = 0x07,
- INVOKE_INTERFACE = 0x08
-};
-
-/*
- * Direct-mapped "method_handle_item"
- */
-struct DexMethodHandleItem {
- u2 methodHandleType; /* type of method handle */
- u2 reserved1; /* reserved for future use */
- u2 fieldOrMethodIdx; /* index of associated field or method */
- u2 reserved2; /* reserved for future use */
-};
-
-/*
- * Direct-mapped "type_item".
- */
-struct DexTypeItem {
- u2 typeIdx; /* index into typeIds */
-};
-
-/*
- * Direct-mapped "type_list".
- */
-struct DexTypeList {
- u4 size; /* #of entries in list */
- DexTypeItem list[1]; /* entries */
-};
-
-/*
- * Direct-mapped "code_item".
- *
- * The "catches" table is used when throwing an exception,
- * "debugInfo" is used when displaying an exception stack trace or
- * debugging. An offset of zero indicates that there are no entries.
- */
-struct DexCode {
- u2 registersSize;
- u2 insSize;
- u2 outsSize;
- u2 triesSize;
- u4 debugInfoOff; /* file offset to debug info stream */
- u4 insnsSize; /* size of the insns array, in u2 units */
- u2 insns[1];
- /* followed by optional u2 padding */
- /* followed by try_item[triesSize] */
- /* followed by uleb128 handlersSize */
- /* followed by catch_handler_item[handlersSize] */
-};
-
-/*
- * Direct-mapped "try_item".
- */
-struct DexTry {
- u4 startAddr; /* start address, in 16-bit code units */
- u2 insnCount; /* instruction count, in 16-bit code units */
- u2 handlerOff; /* offset in encoded handler data to handlers */
-};
-
-/*
- * Link table. Currently undefined.
- */
-struct DexLink {
- u1 bleargh;
-};
-
-
-/*
- * Direct-mapped "annotations_directory_item".
- */
-struct DexAnnotationsDirectoryItem {
- u4 classAnnotationsOff; /* offset to DexAnnotationSetItem */
- u4 fieldsSize; /* count of DexFieldAnnotationsItem */
- u4 methodsSize; /* count of DexMethodAnnotationsItem */
- u4 parametersSize; /* count of DexParameterAnnotationsItem */
- /* followed by DexFieldAnnotationsItem[fieldsSize] */
- /* followed by DexMethodAnnotationsItem[methodsSize] */
- /* followed by DexParameterAnnotationsItem[parametersSize] */
-};
-
-/*
- * Direct-mapped "field_annotations_item".
- */
-struct DexFieldAnnotationsItem {
- u4 fieldIdx;
- u4 annotationsOff; /* offset to DexAnnotationSetItem */
-};
-
-/*
- * Direct-mapped "method_annotations_item".
- */
-struct DexMethodAnnotationsItem {
- u4 methodIdx;
- u4 annotationsOff; /* offset to DexAnnotationSetItem */
-};
-
-/*
- * Direct-mapped "parameter_annotations_item".
- */
-struct DexParameterAnnotationsItem {
- u4 methodIdx;
- u4 annotationsOff; /* offset to DexAnotationSetRefList */
-};
-
-/*
- * Direct-mapped "annotation_set_ref_item".
- */
-struct DexAnnotationSetRefItem {
- u4 annotationsOff; /* offset to DexAnnotationSetItem */
-};
-
-/*
- * Direct-mapped "annotation_set_ref_list".
- */
-struct DexAnnotationSetRefList {
- u4 size;
- DexAnnotationSetRefItem list[1];
-};
-
-/*
- * Direct-mapped "annotation_set_item".
- */
-struct DexAnnotationSetItem {
- u4 size;
- u4 entries[1]; /* offset to DexAnnotationItem */
-};
-
-/*
- * Direct-mapped "annotation_item".
- *
- * NOTE: this structure is byte-aligned.
- */
-struct DexAnnotationItem {
- u1 visibility;
- u1 annotation[1]; /* data in encoded_annotation format */
-};
-
-/*
- * Direct-mapped "encoded_array".
- *
- * NOTE: this structure is byte-aligned.
- */
-struct DexEncodedArray {
- u1 array[1]; /* data in encoded_array format */
-};
-
-/*
- * Lookup table for classes. It provides a mapping from class name to
- * class definition. Used by dexFindClass().
- *
- * We calculate this at DEX optimization time and embed it in the file so we
- * don't need the same hash table in every VM. This is slightly slower than
- * a hash table with direct pointers to the items, but because it's shared
- * there's less of a penalty for using a fairly sparse table.
- */
-struct DexClassLookup {
- int size; // total size, including "size"
- int numEntries; // size of table[]; always power of 2
- struct {
- u4 classDescriptorHash; // class descriptor hash code
- int classDescriptorOffset; // in bytes, from start of DEX
- int classDefOffset; // in bytes, from start of DEX
- } table[1];
-};
-
-/*
- * Header added by DEX optimization pass. Values are always written in
- * local byte and structure padding. The first field (magic + version)
- * is guaranteed to be present and directly readable for all expected
- * compiler configurations; the rest is version-dependent.
- *
- * Try to keep this simple and fixed-size.
- */
-struct DexOptHeader {
- u1 magic[8]; /* includes version number */
-
- u4 dexOffset; /* file offset of DEX header */
- u4 dexLength;
- u4 depsOffset; /* offset of optimized DEX dependency table */
- u4 depsLength;
- u4 optOffset; /* file offset of optimized data tables */
- u4 optLength;
-
- u4 flags; /* some info flags */
- u4 checksum; /* adler32 checksum covering deps/opt */
-
- /* pad for 64-bit alignment if necessary */
-};
-
-#define DEX_OPT_FLAG_BIG (1<<1) /* swapped to big-endian */
-
-#define DEX_INTERFACE_CACHE_SIZE 128 /* must be power of 2 */
-
-/*
- * Structure representing a DEX file.
- *
- * Code should regard DexFile as opaque, using the API calls provided here
- * to access specific structures.
- */
-struct DexFile {
- /* directly-mapped "opt" header */
- const DexOptHeader* pOptHeader;
-
- /* pointers to directly-mapped structs and arrays in base DEX */
- const DexHeader* pHeader;
- const DexStringId* pStringIds;
- const DexTypeId* pTypeIds;
- const DexFieldId* pFieldIds;
- const DexMethodId* pMethodIds;
- const DexProtoId* pProtoIds;
- const DexClassDef* pClassDefs;
- const DexLink* pLinkData;
-
- /*
- * These are mapped out of the "auxillary" section, and may not be
- * included in the file.
- */
- const DexClassLookup* pClassLookup;
- const void* pRegisterMapPool; // RegisterMapClassPool
-
- /* points to start of DEX file data */
- const u1* baseAddr;
-
- /* track memory overhead for auxillary structures */
- int overhead;
-
- /* additional app-specific data structures associated with the DEX */
- //void* auxData;
-};
-
-/*
- * Utility function -- rounds up to the nearest power of 2.
- */
-u4 dexRoundUpPower2(u4 val);
-
-/*
- * Parse an optimized or unoptimized .dex file sitting in memory.
- *
- * On success, return a newly-allocated DexFile.
- */
-DexFile* dexFileParse(const u1* data, size_t length, int flags);
-
-/* bit values for "flags" argument to dexFileParse */
-enum {
- kDexParseDefault = 0,
- kDexParseVerifyChecksum = 1,
- kDexParseContinueOnError = (1 << 1),
-};
-
-/*
- * Fix the byte ordering of all fields in the DEX file, and do
- * structural verification. This is only required for code that opens
- * "raw" DEX files, such as the DEX optimizer.
- *
- * Return 0 on success.
- */
-int dexSwapAndVerify(u1* addr, int len);
-
-/*
- * Detect the file type of the given memory buffer via magic number.
- * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing
- * but return successfully on an optimized DEX file, and report an
- * error for all other cases.
- *
- * Return 0 on success.
- */
-int dexSwapAndVerifyIfNecessary(u1* addr, size_t len);
-
-/*
- * Check to see if the file magic and format version in the given
- * header are recognized as valid. Returns true if they are
- * acceptable.
- */
-bool dexHasValidMagic(const DexHeader* pHeader);
-
-/*
- * Compute DEX checksum.
- */
-u4 dexComputeChecksum(const DexHeader* pHeader);
-
-/*
- * Free a DexFile structure, along with any associated structures.
- */
-void dexFileFree(DexFile* pDexFile);
-
-/*
- * Create class lookup table.
- */
-DexClassLookup* dexCreateClassLookup(DexFile* pDexFile);
-
-/*
- * Find a class definition by descriptor.
- */
-const DexClassDef* dexFindClass(const DexFile* pFile, const char* descriptor);
-
-/*
- * Set up the basic raw data pointers of a DexFile. This function isn't
- * meant for general use.
- */
-void dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data);
-
-/* return the DexMapList of the file, if any */
-DEX_INLINE const DexMapList* dexGetMap(const DexFile* pDexFile) {
- u4 mapOff = pDexFile->pHeader->mapOff;
-
- if (mapOff == 0) {
- return NULL;
- } else {
- return (const DexMapList*) (pDexFile->baseAddr + mapOff);
- }
-}
-
-/* return the const char* string data referred to by the given string_id */
-DEX_INLINE const char* dexGetStringData(const DexFile* pDexFile,
- const DexStringId* pStringId) {
- const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff;
-
- // Skip the uleb128 length.
- while (*(ptr++) > 0x7f) /* empty */ ;
-
- return (const char*) ptr;
-}
-/* return the StringId with the specified index */
-DEX_INLINE const DexStringId* dexGetStringId(const DexFile* pDexFile, u4 idx) {
- assert(idx < pDexFile->pHeader->stringIdsSize);
- return &pDexFile->pStringIds[idx];
-}
-/* return the UTF-8 encoded string with the specified string_id index */
-DEX_INLINE const char* dexStringById(const DexFile* pDexFile, u4 idx) {
- const DexStringId* pStringId = dexGetStringId(pDexFile, idx);
- return dexGetStringData(pDexFile, pStringId);
-}
-
-/* Return the UTF-8 encoded string with the specified string_id index,
- * also filling in the UTF-16 size (number of 16-bit code points).*/
-const char* dexStringAndSizeById(const DexFile* pDexFile, u4 idx,
- u4* utf16Size);
-
-/* return the TypeId with the specified index */
-DEX_INLINE const DexTypeId* dexGetTypeId(const DexFile* pDexFile, u4 idx) {
- assert(idx < pDexFile->pHeader->typeIdsSize);
- return &pDexFile->pTypeIds[idx];
-}
-
-/*
- * Get the descriptor string associated with a given type index.
- * The caller should not free() the returned string.
- */
-DEX_INLINE const char* dexStringByTypeIdx(const DexFile* pDexFile, u4 idx) {
- const DexTypeId* typeId = dexGetTypeId(pDexFile, idx);
- return dexStringById(pDexFile, typeId->descriptorIdx);
-}
-
-/* return the MethodId with the specified index */
-DEX_INLINE const DexMethodId* dexGetMethodId(const DexFile* pDexFile, u4 idx) {
- assert(idx < pDexFile->pHeader->methodIdsSize);
- return &pDexFile->pMethodIds[idx];
-}
-
-/* return the FieldId with the specified index */
-DEX_INLINE const DexFieldId* dexGetFieldId(const DexFile* pDexFile, u4 idx) {
- assert(idx < pDexFile->pHeader->fieldIdsSize);
- return &pDexFile->pFieldIds[idx];
-}
-
-/* return the ProtoId with the specified index */
-DEX_INLINE const DexProtoId* dexGetProtoId(const DexFile* pDexFile, u4 idx) {
- assert(idx < pDexFile->pHeader->protoIdsSize);
- return &pDexFile->pProtoIds[idx];
-}
-
-/*
- * Get the parameter list from a ProtoId. The returns NULL if the ProtoId
- * does not have a parameter list.
- */
-DEX_INLINE const DexTypeList* dexGetProtoParameters(
- const DexFile *pDexFile, const DexProtoId* pProtoId) {
- if (pProtoId->parametersOff == 0) {
- return NULL;
- }
- return (const DexTypeList*)
- (pDexFile->baseAddr + pProtoId->parametersOff);
-}
-
-/* return the ClassDef with the specified index */
-DEX_INLINE const DexClassDef* dexGetClassDef(const DexFile* pDexFile, u4 idx) {
- assert(idx < pDexFile->pHeader->classDefsSize);
- return &pDexFile->pClassDefs[idx];
-}
-
-/* given a ClassDef pointer, recover its index */
-DEX_INLINE u4 dexGetIndexForClassDef(const DexFile* pDexFile,
- const DexClassDef* pClassDef)
-{
- assert(pClassDef >= pDexFile->pClassDefs &&
- pClassDef < pDexFile->pClassDefs + pDexFile->pHeader->classDefsSize);
- return pClassDef - pDexFile->pClassDefs;
-}
-
-/* get the interface list for a DexClass */
-DEX_INLINE const DexTypeList* dexGetInterfacesList(const DexFile* pDexFile,
- const DexClassDef* pClassDef)
-{
- if (pClassDef->interfacesOff == 0)
- return NULL;
- return (const DexTypeList*)
- (pDexFile->baseAddr + pClassDef->interfacesOff);
-}
-/* return the Nth entry in a DexTypeList. */
-DEX_INLINE const DexTypeItem* dexGetTypeItem(const DexTypeList* pList,
- u4 idx)
-{
- assert(idx < pList->size);
- return &pList->list[idx];
-}
-/* return the type_idx for the Nth entry in a TypeList */
-DEX_INLINE u4 dexTypeListGetIdx(const DexTypeList* pList, u4 idx) {
- const DexTypeItem* pItem = dexGetTypeItem(pList, idx);
- return pItem->typeIdx;
-}
-
-/* get the static values list for a DexClass */
-DEX_INLINE const DexEncodedArray* dexGetStaticValuesList(
- const DexFile* pDexFile, const DexClassDef* pClassDef)
-{
- if (pClassDef->staticValuesOff == 0)
- return NULL;
- return (const DexEncodedArray*)
- (pDexFile->baseAddr + pClassDef->staticValuesOff);
-}
-
-/* get the annotations directory item for a DexClass */
-DEX_INLINE const DexAnnotationsDirectoryItem* dexGetAnnotationsDirectoryItem(
- const DexFile* pDexFile, const DexClassDef* pClassDef)
-{
- if (pClassDef->annotationsOff == 0)
- return NULL;
- return (const DexAnnotationsDirectoryItem*)
- (pDexFile->baseAddr + pClassDef->annotationsOff);
-}
-
-/* get the source file string */
-DEX_INLINE const char* dexGetSourceFile(
- const DexFile* pDexFile, const DexClassDef* pClassDef)
-{
- if (pClassDef->sourceFileIdx == 0xffffffff)
- return NULL;
- return dexStringById(pDexFile, pClassDef->sourceFileIdx);
-}
-
-/* get the size, in bytes, of a DexCode */
-size_t dexGetDexCodeSize(const DexCode* pCode);
-
-/* Get the list of "tries" for the given DexCode. */
-DEX_INLINE const DexTry* dexGetTries(const DexCode* pCode) {
- const u2* insnsEnd = &pCode->insns[pCode->insnsSize];
-
- // Round to four bytes.
- if ((((uintptr_t) insnsEnd) & 3) != 0) {
- insnsEnd++;
- }
-
- return (const DexTry*) insnsEnd;
-}
-
-/* Get the base of the encoded data for the given DexCode. */
-DEX_INLINE const u1* dexGetCatchHandlerData(const DexCode* pCode) {
- const DexTry* pTries = dexGetTries(pCode);
- return (const u1*) &pTries[pCode->triesSize];
-}
-
-/* get a pointer to the start of the debugging data */
-DEX_INLINE const u1* dexGetDebugInfoStream(const DexFile* pDexFile,
- const DexCode* pCode)
-{
- if (pCode->debugInfoOff == 0) {
- return NULL;
- } else {
- return pDexFile->baseAddr + pCode->debugInfoOff;
- }
-}
-
-/* DexClassDef convenience - get class descriptor */
-DEX_INLINE const char* dexGetClassDescriptor(const DexFile* pDexFile,
- const DexClassDef* pClassDef)
-{
- return dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
-}
-
-/* DexClassDef convenience - get superclass descriptor */
-DEX_INLINE const char* dexGetSuperClassDescriptor(const DexFile* pDexFile,
- const DexClassDef* pClassDef)
-{
- if (pClassDef->superclassIdx == 0)
- return NULL;
- return dexStringByTypeIdx(pDexFile, pClassDef->superclassIdx);
-}
-
-/* DexClassDef convenience - get class_data_item pointer */
-DEX_INLINE const u1* dexGetClassData(const DexFile* pDexFile,
- const DexClassDef* pClassDef)
-{
- if (pClassDef->classDataOff == 0)
- return NULL;
- return (const u1*) (pDexFile->baseAddr + pClassDef->classDataOff);
-}
-
-/* Get an annotation set at a particular offset. */
-DEX_INLINE const DexAnnotationSetItem* dexGetAnnotationSetItem(
- const DexFile* pDexFile, u4 offset)
-{
- if (offset == 0) {
- return NULL;
- }
- return (const DexAnnotationSetItem*) (pDexFile->baseAddr + offset);
-}
-/* get the class' annotation set */
-DEX_INLINE const DexAnnotationSetItem* dexGetClassAnnotationSet(
- const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
-{
- return dexGetAnnotationSetItem(pDexFile, pAnnoDir->classAnnotationsOff);
-}
-
-/* get the class' field annotation list */
-DEX_INLINE const DexFieldAnnotationsItem* dexGetFieldAnnotations(
- const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
-{
- (void) pDexFile;
- if (pAnnoDir->fieldsSize == 0)
- return NULL;
-
- // Skip past the header to the start of the field annotations.
- return (const DexFieldAnnotationsItem*) &pAnnoDir[1];
-}
-
-/* get field annotation list size */
-DEX_INLINE int dexGetFieldAnnotationsSize(const DexFile* pDexFile,
- const DexAnnotationsDirectoryItem* pAnnoDir)
-{
- (void) pDexFile;
- return pAnnoDir->fieldsSize;
-}
-
-/* return a pointer to the field's annotation set */
-DEX_INLINE const DexAnnotationSetItem* dexGetFieldAnnotationSetItem(
- const DexFile* pDexFile, const DexFieldAnnotationsItem* pItem)
-{
- return dexGetAnnotationSetItem(pDexFile, pItem->annotationsOff);
-}
-
-/* get the class' method annotation list */
-DEX_INLINE const DexMethodAnnotationsItem* dexGetMethodAnnotations(
- const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
-{
- (void) pDexFile;
- if (pAnnoDir->methodsSize == 0)
- return NULL;
-
- /*
- * Skip past the header and field annotations to the start of the
- * method annotations.
- */
- const u1* addr = (const u1*) &pAnnoDir[1];
- addr += pAnnoDir->fieldsSize * sizeof (DexFieldAnnotationsItem);
- return (const DexMethodAnnotationsItem*) addr;
-}
-
-/* get method annotation list size */
-DEX_INLINE int dexGetMethodAnnotationsSize(const DexFile* pDexFile,
- const DexAnnotationsDirectoryItem* pAnnoDir)
-{
- (void) pDexFile;
- return pAnnoDir->methodsSize;
-}
-
-/* return a pointer to the method's annotation set */
-DEX_INLINE const DexAnnotationSetItem* dexGetMethodAnnotationSetItem(
- const DexFile* pDexFile, const DexMethodAnnotationsItem* pItem)
-{
- return dexGetAnnotationSetItem(pDexFile, pItem->annotationsOff);
-}
-
-/* get the class' parameter annotation list */
-DEX_INLINE const DexParameterAnnotationsItem* dexGetParameterAnnotations(
- const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
-{
- (void) pDexFile;
- if (pAnnoDir->parametersSize == 0)
- return NULL;
-
- /*
- * Skip past the header, field annotations, and method annotations
- * to the start of the parameter annotations.
- */
- const u1* addr = (const u1*) &pAnnoDir[1];
- addr += pAnnoDir->fieldsSize * sizeof (DexFieldAnnotationsItem);
- addr += pAnnoDir->methodsSize * sizeof (DexMethodAnnotationsItem);
- return (const DexParameterAnnotationsItem*) addr;
-}
-
-/* get method annotation list size */
-DEX_INLINE int dexGetParameterAnnotationsSize(const DexFile* pDexFile,
- const DexAnnotationsDirectoryItem* pAnnoDir)
-{
- (void) pDexFile;
- return pAnnoDir->parametersSize;
-}
-
-/* return the parameter annotation ref list */
-DEX_INLINE const DexAnnotationSetRefList* dexGetParameterAnnotationSetRefList(
- const DexFile* pDexFile, const DexParameterAnnotationsItem* pItem)
-{
- if (pItem->annotationsOff == 0) {
- return NULL;
- }
- return (const DexAnnotationSetRefList*) (pDexFile->baseAddr + pItem->annotationsOff);
-}
-
-/* get method annotation list size */
-DEX_INLINE int dexGetParameterAnnotationSetRefSize(const DexFile* pDexFile,
- const DexParameterAnnotationsItem* pItem)
-{
- if (pItem->annotationsOff == 0) {
- return 0;
- }
- return dexGetParameterAnnotationSetRefList(pDexFile, pItem)->size;
-}
-
-/* return the Nth entry from an annotation set ref list */
-DEX_INLINE const DexAnnotationSetRefItem* dexGetParameterAnnotationSetRef(
- const DexAnnotationSetRefList* pList, u4 idx)
-{
- assert(idx < pList->size);
- return &pList->list[idx];
-}
-
-/* given a DexAnnotationSetRefItem, return the DexAnnotationSetItem */
-DEX_INLINE const DexAnnotationSetItem* dexGetSetRefItemItem(
- const DexFile* pDexFile, const DexAnnotationSetRefItem* pItem)
-{
- return dexGetAnnotationSetItem(pDexFile, pItem->annotationsOff);
-}
-
-/* return the Nth annotation offset from a DexAnnotationSetItem */
-DEX_INLINE u4 dexGetAnnotationOff(
- const DexAnnotationSetItem* pAnnoSet, u4 idx)
-{
- assert(idx < pAnnoSet->size);
- return pAnnoSet->entries[idx];
-}
-
-/* return the Nth annotation item from a DexAnnotationSetItem */
-DEX_INLINE const DexAnnotationItem* dexGetAnnotationItem(
- const DexFile* pDexFile, const DexAnnotationSetItem* pAnnoSet, u4 idx)
-{
- u4 offset = dexGetAnnotationOff(pAnnoSet, idx);
- if (offset == 0) {
- return NULL;
- }
- return (const DexAnnotationItem*) (pDexFile->baseAddr + offset);
-}
-
-/*
- * Get the type descriptor character associated with a given primitive
- * type. This returns '\0' if the type is invalid.
- */
-char dexGetPrimitiveTypeDescriptorChar(PrimitiveType type);
-
-/*
- * Get the type descriptor string associated with a given primitive
- * type.
- */
-const char* dexGetPrimitiveTypeDescriptor(PrimitiveType type);
-
-/*
- * Get the boxed type descriptor string associated with a given
- * primitive type. This returns NULL for an invalid type, including
- * particularly for type "void". In the latter case, even though there
- * is a class Void, there's no such thing as a boxed instance of it.
- */
-const char* dexGetBoxedTypeDescriptor(PrimitiveType type);
-
-/*
- * Get the primitive type constant from the given descriptor character.
- * This returns PRIM_NOT (note: this is a 0) if the character is invalid
- * as a primitive type descriptor.
- */
-PrimitiveType dexGetPrimitiveTypeFromDescriptorChar(char descriptorChar);
-
-#endif // LIBDEX_DEXFILE_H_
diff --git a/libdex/DexInlines.cpp b/libdex/DexInlines.cpp
deleted file mode 100644
index cbedb6267..000000000
--- a/libdex/DexInlines.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Generate non-inline copies of inline functions in header files.
- */
-
-#define _DEX_GEN_INLINES
-
-#include "DexFile.h"
-
-#include "DexCatch.h"
-#include "DexClass.h"
-#include "DexDataMap.h"
-#include "DexUtf.h"
-#include "DexOpcodes.h"
-#include "DexProto.h"
-#include "InstrUtils.h"
-#include "Leb128.h"
-#include "ZipArchive.h"
diff --git a/libdex/DexOpcodes.cpp b/libdex/DexOpcodes.cpp
deleted file mode 100644
index d3db79b67..000000000
--- a/libdex/DexOpcodes.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Table of Dalvik opcode names.
- *
- * IMPORTANT NOTE: The contents of this file are mostly generated
- * automatically by the opcode-gen tool. Any edits to the generated
- * sections will get wiped out the next time the tool is run.
- */
-
-#include "DexOpcodes.h"
-#include <assert.h>
-
-/*
- * Dalvik opcode names.
- */
-static const char* gOpNames[kNumPackedOpcodes] = {
- // BEGIN(libdex-opcode-names); GENERATED AUTOMATICALLY BY opcode-gen
- "nop",
- "move",
- "move/from16",
- "move/16",
- "move-wide",
- "move-wide/from16",
- "move-wide/16",
- "move-object",
- "move-object/from16",
- "move-object/16",
- "move-result",
- "move-result-wide",
- "move-result-object",
- "move-exception",
- "return-void",
- "return",
- "return-wide",
- "return-object",
- "const/4",
- "const/16",
- "const",
- "const/high16",
- "const-wide/16",
- "const-wide/32",
- "const-wide",
- "const-wide/high16",
- "const-string",
- "const-string/jumbo",
- "const-class",
- "monitor-enter",
- "monitor-exit",
- "check-cast",
- "instance-of",
- "array-length",
- "new-instance",
- "new-array",
- "filled-new-array",
- "filled-new-array/range",
- "fill-array-data",
- "throw",
- "goto",
- "goto/16",
- "goto/32",
- "packed-switch",
- "sparse-switch",
- "cmpl-float",
- "cmpg-float",
- "cmpl-double",
- "cmpg-double",
- "cmp-long",
- "if-eq",
- "if-ne",
- "if-lt",
- "if-ge",
- "if-gt",
- "if-le",
- "if-eqz",
- "if-nez",
- "if-ltz",
- "if-gez",
- "if-gtz",
- "if-lez",
- "unused-3e",
- "unused-3f",
- "unused-40",
- "unused-41",
- "unused-42",
- "unused-43",
- "aget",
- "aget-wide",
- "aget-object",
- "aget-boolean",
- "aget-byte",
- "aget-char",
- "aget-short",
- "aput",
- "aput-wide",
- "aput-object",
- "aput-boolean",
- "aput-byte",
- "aput-char",
- "aput-short",
- "iget",
- "iget-wide",
- "iget-object",
- "iget-boolean",
- "iget-byte",
- "iget-char",
- "iget-short",
- "iput",
- "iput-wide",
- "iput-object",
- "iput-boolean",
- "iput-byte",
- "iput-char",
- "iput-short",
- "sget",
- "sget-wide",
- "sget-object",
- "sget-boolean",
- "sget-byte",
- "sget-char",
- "sget-short",
- "sput",
- "sput-wide",
- "sput-object",
- "sput-boolean",
- "sput-byte",
- "sput-char",
- "sput-short",
- "invoke-virtual",
- "invoke-super",
- "invoke-direct",
- "invoke-static",
- "invoke-interface",
- "unused-73",
- "invoke-virtual/range",
- "invoke-super/range",
- "invoke-direct/range",
- "invoke-static/range",
- "invoke-interface/range",
- "unused-79",
- "unused-7a",
- "neg-int",
- "not-int",
- "neg-long",
- "not-long",
- "neg-float",
- "neg-double",
- "int-to-long",
- "int-to-float",
- "int-to-double",
- "long-to-int",
- "long-to-float",
- "long-to-double",
- "float-to-int",
- "float-to-long",
- "float-to-double",
- "double-to-int",
- "double-to-long",
- "double-to-float",
- "int-to-byte",
- "int-to-char",
- "int-to-short",
- "add-int",
- "sub-int",
- "mul-int",
- "div-int",
- "rem-int",
- "and-int",
- "or-int",
- "xor-int",
- "shl-int",
- "shr-int",
- "ushr-int",
- "add-long",
- "sub-long",
- "mul-long",
- "div-long",
- "rem-long",
- "and-long",
- "or-long",
- "xor-long",
- "shl-long",
- "shr-long",
- "ushr-long",
- "add-float",
- "sub-float",
- "mul-float",
- "div-float",
- "rem-float",
- "add-double",
- "sub-double",
- "mul-double",
- "div-double",
- "rem-double",
- "add-int/2addr",
- "sub-int/2addr",
- "mul-int/2addr",
- "div-int/2addr",
- "rem-int/2addr",
- "and-int/2addr",
- "or-int/2addr",
- "xor-int/2addr",
- "shl-int/2addr",
- "shr-int/2addr",
- "ushr-int/2addr",
- "add-long/2addr",
- "sub-long/2addr",
- "mul-long/2addr",
- "div-long/2addr",
- "rem-long/2addr",
- "and-long/2addr",
- "or-long/2addr",
- "xor-long/2addr",
- "shl-long/2addr",
- "shr-long/2addr",
- "ushr-long/2addr",
- "add-float/2addr",
- "sub-float/2addr",
- "mul-float/2addr",
- "div-float/2addr",
- "rem-float/2addr",
- "add-double/2addr",
- "sub-double/2addr",
- "mul-double/2addr",
- "div-double/2addr",
- "rem-double/2addr",
- "add-int/lit16",
- "rsub-int",
- "mul-int/lit16",
- "div-int/lit16",
- "rem-int/lit16",
- "and-int/lit16",
- "or-int/lit16",
- "xor-int/lit16",
- "add-int/lit8",
- "rsub-int/lit8",
- "mul-int/lit8",
- "div-int/lit8",
- "rem-int/lit8",
- "and-int/lit8",
- "or-int/lit8",
- "xor-int/lit8",
- "shl-int/lit8",
- "shr-int/lit8",
- "ushr-int/lit8",
- "+iget-volatile",
- "+iput-volatile",
- "+sget-volatile",
- "+sput-volatile",
- "+iget-object-volatile",
- "+iget-wide-volatile",
- "+iput-wide-volatile",
- "+sget-wide-volatile",
- "+sput-wide-volatile",
- "^breakpoint",
- "^throw-verification-error",
- "+execute-inline",
- "+execute-inline/range",
- "+invoke-object-init/range",
- "+return-void-barrier",
- "+iget-quick",
- "unused-f3",
- "unused-f4",
- "unused-f5",
- "unused-f6",
- "unused-f7",
- "unused-f8",
- "unused-f9",
- "invoke-polymorphic",
- "invoke-polymorphic/range",
- "invoke-custom",
- "invoke-custom/range",
- "const-method-handle",
- "const-method-type",
- // END(libdex-opcode-names)
-};
-
-/*
- * Return the name of an opcode.
- */
-const char* dexGetOpcodeName(Opcode op)
-{
- assert(op >= 0 && op < kNumPackedOpcodes);
- return gOpNames[op];
-}
diff --git a/libdex/DexOpcodes.h b/libdex/DexOpcodes.h
deleted file mode 100644
index f4dcd6b51..000000000
--- a/libdex/DexOpcodes.h
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Dalvik opcode information.
- *
- * IMPORTANT NOTE: The contents of this file are mostly generated
- * automatically by the opcode-gen tool. Any edits to the generated
- * sections will get wiped out the next time the tool is run.
- *
- * See the file opcode-gen/README.txt for information about updating
- * opcodes and instruction formats.
- */
-
-#ifndef LIBDEX_DEXOPCODES_H_
-#define LIBDEX_DEXOPCODES_H_
-
-#include "DexFile.h"
-
-/*
- * kMaxOpcodeValue: the highest possible raw (unpacked) opcode value
- *
- * kNumPackedOpcodes: the highest possible packed opcode value of a
- * valid Dalvik opcode, plus one
- *
- * TODO: Change this once the rest of the code is prepared to deal with
- * extended opcodes.
- */
-// BEGIN(libdex-maximum-values); GENERATED AUTOMATICALLY BY opcode-gen
-#define kMaxOpcodeValue 0xffff
-#define kNumPackedOpcodes 0x100
-// END(libdex-maximum-values); GENERATED AUTOMATICALLY BY opcode-gen
-
-/*
- * Switch table and array data signatures are a code unit consisting
- * of "NOP" (0x00) in the low-order byte and a non-zero identifying
- * code in the high-order byte. (A true NOP is 0x0000.)
- */
-#define kPackedSwitchSignature 0x0100
-#define kSparseSwitchSignature 0x0200
-#define kArrayDataSignature 0x0300
-
-/*
- * Enumeration of all Dalvik opcodes, where the enumeration value
- * associated with each is the corresponding packed opcode number.
- * This is different than the opcode value from the Dalvik bytecode
- * spec for opcode values >= 0xff; see dexOpcodeFromCodeUnit() below.
- *
- * A note about the "breakpoint" opcode. This instruction is special,
- * in that it should never be seen by anything but the debug
- * interpreter. During debugging it takes the place of an arbitrary
- * opcode, which means operations like "tell me the opcode width so I
- * can find the next instruction" aren't possible. (This is
- * correctable, but probably not useful.)
- */
-enum Opcode {
- // BEGIN(libdex-opcode-enum); GENERATED AUTOMATICALLY BY opcode-gen
- OP_NOP = 0x00,
- OP_MOVE = 0x01,
- OP_MOVE_FROM16 = 0x02,
- OP_MOVE_16 = 0x03,
- OP_MOVE_WIDE = 0x04,
- OP_MOVE_WIDE_FROM16 = 0x05,
- OP_MOVE_WIDE_16 = 0x06,
- OP_MOVE_OBJECT = 0x07,
- OP_MOVE_OBJECT_FROM16 = 0x08,
- OP_MOVE_OBJECT_16 = 0x09,
- OP_MOVE_RESULT = 0x0a,
- OP_MOVE_RESULT_WIDE = 0x0b,
- OP_MOVE_RESULT_OBJECT = 0x0c,
- OP_MOVE_EXCEPTION = 0x0d,
- OP_RETURN_VOID = 0x0e,
- OP_RETURN = 0x0f,
- OP_RETURN_WIDE = 0x10,
- OP_RETURN_OBJECT = 0x11,
- OP_CONST_4 = 0x12,
- OP_CONST_16 = 0x13,
- OP_CONST = 0x14,
- OP_CONST_HIGH16 = 0x15,
- OP_CONST_WIDE_16 = 0x16,
- OP_CONST_WIDE_32 = 0x17,
- OP_CONST_WIDE = 0x18,
- OP_CONST_WIDE_HIGH16 = 0x19,
- OP_CONST_STRING = 0x1a,
- OP_CONST_STRING_JUMBO = 0x1b,
- OP_CONST_CLASS = 0x1c,
- OP_MONITOR_ENTER = 0x1d,
- OP_MONITOR_EXIT = 0x1e,
- OP_CHECK_CAST = 0x1f,
- OP_INSTANCE_OF = 0x20,
- OP_ARRAY_LENGTH = 0x21,
- OP_NEW_INSTANCE = 0x22,
- OP_NEW_ARRAY = 0x23,
- OP_FILLED_NEW_ARRAY = 0x24,
- OP_FILLED_NEW_ARRAY_RANGE = 0x25,
- OP_FILL_ARRAY_DATA = 0x26,
- OP_THROW = 0x27,
- OP_GOTO = 0x28,
- OP_GOTO_16 = 0x29,
- OP_GOTO_32 = 0x2a,
- OP_PACKED_SWITCH = 0x2b,
- OP_SPARSE_SWITCH = 0x2c,
- OP_CMPL_FLOAT = 0x2d,
- OP_CMPG_FLOAT = 0x2e,
- OP_CMPL_DOUBLE = 0x2f,
- OP_CMPG_DOUBLE = 0x30,
- OP_CMP_LONG = 0x31,
- OP_IF_EQ = 0x32,
- OP_IF_NE = 0x33,
- OP_IF_LT = 0x34,
- OP_IF_GE = 0x35,
- OP_IF_GT = 0x36,
- OP_IF_LE = 0x37,
- OP_IF_EQZ = 0x38,
- OP_IF_NEZ = 0x39,
- OP_IF_LTZ = 0x3a,
- OP_IF_GEZ = 0x3b,
- OP_IF_GTZ = 0x3c,
- OP_IF_LEZ = 0x3d,
- OP_UNUSED_3E = 0x3e,
- OP_UNUSED_3F = 0x3f,
- OP_UNUSED_40 = 0x40,
- OP_UNUSED_41 = 0x41,
- OP_UNUSED_42 = 0x42,
- OP_UNUSED_43 = 0x43,
- OP_AGET = 0x44,
- OP_AGET_WIDE = 0x45,
- OP_AGET_OBJECT = 0x46,
- OP_AGET_BOOLEAN = 0x47,
- OP_AGET_BYTE = 0x48,
- OP_AGET_CHAR = 0x49,
- OP_AGET_SHORT = 0x4a,
- OP_APUT = 0x4b,
- OP_APUT_WIDE = 0x4c,
- OP_APUT_OBJECT = 0x4d,
- OP_APUT_BOOLEAN = 0x4e,
- OP_APUT_BYTE = 0x4f,
- OP_APUT_CHAR = 0x50,
- OP_APUT_SHORT = 0x51,
- OP_IGET = 0x52,
- OP_IGET_WIDE = 0x53,
- OP_IGET_OBJECT = 0x54,
- OP_IGET_BOOLEAN = 0x55,
- OP_IGET_BYTE = 0x56,
- OP_IGET_CHAR = 0x57,
- OP_IGET_SHORT = 0x58,
- OP_IPUT = 0x59,
- OP_IPUT_WIDE = 0x5a,
- OP_IPUT_OBJECT = 0x5b,
- OP_IPUT_BOOLEAN = 0x5c,
- OP_IPUT_BYTE = 0x5d,
- OP_IPUT_CHAR = 0x5e,
- OP_IPUT_SHORT = 0x5f,
- OP_SGET = 0x60,
- OP_SGET_WIDE = 0x61,
- OP_SGET_OBJECT = 0x62,
- OP_SGET_BOOLEAN = 0x63,
- OP_SGET_BYTE = 0x64,
- OP_SGET_CHAR = 0x65,
- OP_SGET_SHORT = 0x66,
- OP_SPUT = 0x67,
- OP_SPUT_WIDE = 0x68,
- OP_SPUT_OBJECT = 0x69,
- OP_SPUT_BOOLEAN = 0x6a,
- OP_SPUT_BYTE = 0x6b,
- OP_SPUT_CHAR = 0x6c,
- OP_SPUT_SHORT = 0x6d,
- OP_INVOKE_VIRTUAL = 0x6e,
- OP_INVOKE_SUPER = 0x6f,
- OP_INVOKE_DIRECT = 0x70,
- OP_INVOKE_STATIC = 0x71,
- OP_INVOKE_INTERFACE = 0x72,
- OP_UNUSED_73 = 0x73,
- OP_INVOKE_VIRTUAL_RANGE = 0x74,
- OP_INVOKE_SUPER_RANGE = 0x75,
- OP_INVOKE_DIRECT_RANGE = 0x76,
- OP_INVOKE_STATIC_RANGE = 0x77,
- OP_INVOKE_INTERFACE_RANGE = 0x78,
- OP_UNUSED_79 = 0x79,
- OP_UNUSED_7A = 0x7a,
- OP_NEG_INT = 0x7b,
- OP_NOT_INT = 0x7c,
- OP_NEG_LONG = 0x7d,
- OP_NOT_LONG = 0x7e,
- OP_NEG_FLOAT = 0x7f,
- OP_NEG_DOUBLE = 0x80,
- OP_INT_TO_LONG = 0x81,
- OP_INT_TO_FLOAT = 0x82,
- OP_INT_TO_DOUBLE = 0x83,
- OP_LONG_TO_INT = 0x84,
- OP_LONG_TO_FLOAT = 0x85,
- OP_LONG_TO_DOUBLE = 0x86,
- OP_FLOAT_TO_INT = 0x87,
- OP_FLOAT_TO_LONG = 0x88,
- OP_FLOAT_TO_DOUBLE = 0x89,
- OP_DOUBLE_TO_INT = 0x8a,
- OP_DOUBLE_TO_LONG = 0x8b,
- OP_DOUBLE_TO_FLOAT = 0x8c,
- OP_INT_TO_BYTE = 0x8d,
- OP_INT_TO_CHAR = 0x8e,
- OP_INT_TO_SHORT = 0x8f,
- OP_ADD_INT = 0x90,
- OP_SUB_INT = 0x91,
- OP_MUL_INT = 0x92,
- OP_DIV_INT = 0x93,
- OP_REM_INT = 0x94,
- OP_AND_INT = 0x95,
- OP_OR_INT = 0x96,
- OP_XOR_INT = 0x97,
- OP_SHL_INT = 0x98,
- OP_SHR_INT = 0x99,
- OP_USHR_INT = 0x9a,
- OP_ADD_LONG = 0x9b,
- OP_SUB_LONG = 0x9c,
- OP_MUL_LONG = 0x9d,
- OP_DIV_LONG = 0x9e,
- OP_REM_LONG = 0x9f,
- OP_AND_LONG = 0xa0,
- OP_OR_LONG = 0xa1,
- OP_XOR_LONG = 0xa2,
- OP_SHL_LONG = 0xa3,
- OP_SHR_LONG = 0xa4,
- OP_USHR_LONG = 0xa5,
- OP_ADD_FLOAT = 0xa6,
- OP_SUB_FLOAT = 0xa7,
- OP_MUL_FLOAT = 0xa8,
- OP_DIV_FLOAT = 0xa9,
- OP_REM_FLOAT = 0xaa,
- OP_ADD_DOUBLE = 0xab,
- OP_SUB_DOUBLE = 0xac,
- OP_MUL_DOUBLE = 0xad,
- OP_DIV_DOUBLE = 0xae,
- OP_REM_DOUBLE = 0xaf,
- OP_ADD_INT_2ADDR = 0xb0,
- OP_SUB_INT_2ADDR = 0xb1,
- OP_MUL_INT_2ADDR = 0xb2,
- OP_DIV_INT_2ADDR = 0xb3,
- OP_REM_INT_2ADDR = 0xb4,
- OP_AND_INT_2ADDR = 0xb5,
- OP_OR_INT_2ADDR = 0xb6,
- OP_XOR_INT_2ADDR = 0xb7,
- OP_SHL_INT_2ADDR = 0xb8,
- OP_SHR_INT_2ADDR = 0xb9,
- OP_USHR_INT_2ADDR = 0xba,
- OP_ADD_LONG_2ADDR = 0xbb,
- OP_SUB_LONG_2ADDR = 0xbc,
- OP_MUL_LONG_2ADDR = 0xbd,
- OP_DIV_LONG_2ADDR = 0xbe,
- OP_REM_LONG_2ADDR = 0xbf,
- OP_AND_LONG_2ADDR = 0xc0,
- OP_OR_LONG_2ADDR = 0xc1,
- OP_XOR_LONG_2ADDR = 0xc2,
- OP_SHL_LONG_2ADDR = 0xc3,
- OP_SHR_LONG_2ADDR = 0xc4,
- OP_USHR_LONG_2ADDR = 0xc5,
- OP_ADD_FLOAT_2ADDR = 0xc6,
- OP_SUB_FLOAT_2ADDR = 0xc7,
- OP_MUL_FLOAT_2ADDR = 0xc8,
- OP_DIV_FLOAT_2ADDR = 0xc9,
- OP_REM_FLOAT_2ADDR = 0xca,
- OP_ADD_DOUBLE_2ADDR = 0xcb,
- OP_SUB_DOUBLE_2ADDR = 0xcc,
- OP_MUL_DOUBLE_2ADDR = 0xcd,
- OP_DIV_DOUBLE_2ADDR = 0xce,
- OP_REM_DOUBLE_2ADDR = 0xcf,
- OP_ADD_INT_LIT16 = 0xd0,
- OP_RSUB_INT = 0xd1,
- OP_MUL_INT_LIT16 = 0xd2,
- OP_DIV_INT_LIT16 = 0xd3,
- OP_REM_INT_LIT16 = 0xd4,
- OP_AND_INT_LIT16 = 0xd5,
- OP_OR_INT_LIT16 = 0xd6,
- OP_XOR_INT_LIT16 = 0xd7,
- OP_ADD_INT_LIT8 = 0xd8,
- OP_RSUB_INT_LIT8 = 0xd9,
- OP_MUL_INT_LIT8 = 0xda,
- OP_DIV_INT_LIT8 = 0xdb,
- OP_REM_INT_LIT8 = 0xdc,
- OP_AND_INT_LIT8 = 0xdd,
- OP_OR_INT_LIT8 = 0xde,
- OP_XOR_INT_LIT8 = 0xdf,
- OP_SHL_INT_LIT8 = 0xe0,
- OP_SHR_INT_LIT8 = 0xe1,
- OP_USHR_INT_LIT8 = 0xe2,
- OP_IGET_VOLATILE = 0xe3,
- OP_IPUT_VOLATILE = 0xe4,
- OP_SGET_VOLATILE = 0xe5,
- OP_SPUT_VOLATILE = 0xe6,
- OP_IGET_OBJECT_VOLATILE = 0xe7,
- OP_IGET_WIDE_VOLATILE = 0xe8,
- OP_IPUT_WIDE_VOLATILE = 0xe9,
- OP_SGET_WIDE_VOLATILE = 0xea,
- OP_SPUT_WIDE_VOLATILE = 0xeb,
- OP_BREAKPOINT = 0xec,
- OP_THROW_VERIFICATION_ERROR = 0xed,
- OP_EXECUTE_INLINE = 0xee,
- OP_EXECUTE_INLINE_RANGE = 0xef,
- OP_INVOKE_OBJECT_INIT_RANGE = 0xf0,
- OP_RETURN_VOID_BARRIER = 0xf1,
- OP_IGET_QUICK = 0xf2,
- OP_UNUSED_F3 = 0xf3,
- OP_UNUSED_F4 = 0xf4,
- OP_UNUSED_F5 = 0xf5,
- OP_UNUSED_F6 = 0xf6,
- OP_UNUSED_F7 = 0xf7,
- OP_UNUSED_F8 = 0xf8,
- OP_UNUSED_F9 = 0xf9,
- OP_INVOKE_POLYMORPHIC = 0xfa,
- OP_INVOKE_POLYMORPHIC_RANGE = 0xfb,
- OP_INVOKE_CUSTOM = 0xfc,
- OP_INVOKE_CUSTOM_RANGE = 0xfd,
- OP_CONST_METHOD_HANDLE = 0xfe,
- OP_CONST_METHOD_TYPE = 0xff,
- // END(libdex-opcode-enum)
-};
-
-/*
- * Macro used to generate a computed goto table for use in implementing
- * an interpreter in C.
- */
-#define DEFINE_GOTO_TABLE(_name) \
- static const void* (_name)[kNumPackedOpcodes] = { \
- /* BEGIN(libdex-goto-table); GENERATED AUTOMATICALLY BY opcode-gen */ \
- H(OP_NOP), \
- H(OP_MOVE), \
- H(OP_MOVE_FROM16), \
- H(OP_MOVE_16), \
- H(OP_MOVE_WIDE), \
- H(OP_MOVE_WIDE_FROM16), \
- H(OP_MOVE_WIDE_16), \
- H(OP_MOVE_OBJECT), \
- H(OP_MOVE_OBJECT_FROM16), \
- H(OP_MOVE_OBJECT_16), \
- H(OP_MOVE_RESULT), \
- H(OP_MOVE_RESULT_WIDE), \
- H(OP_MOVE_RESULT_OBJECT), \
- H(OP_MOVE_EXCEPTION), \
- H(OP_RETURN_VOID), \
- H(OP_RETURN), \
- H(OP_RETURN_WIDE), \
- H(OP_RETURN_OBJECT), \
- H(OP_CONST_4), \
- H(OP_CONST_16), \
- H(OP_CONST), \
- H(OP_CONST_HIGH16), \
- H(OP_CONST_WIDE_16), \
- H(OP_CONST_WIDE_32), \
- H(OP_CONST_WIDE), \
- H(OP_CONST_WIDE_HIGH16), \
- H(OP_CONST_STRING), \
- H(OP_CONST_STRING_JUMBO), \
- H(OP_CONST_CLASS), \
- H(OP_MONITOR_ENTER), \
- H(OP_MONITOR_EXIT), \
- H(OP_CHECK_CAST), \
- H(OP_INSTANCE_OF), \
- H(OP_ARRAY_LENGTH), \
- H(OP_NEW_INSTANCE), \
- H(OP_NEW_ARRAY), \
- H(OP_FILLED_NEW_ARRAY), \
- H(OP_FILLED_NEW_ARRAY_RANGE), \
- H(OP_FILL_ARRAY_DATA), \
- H(OP_THROW), \
- H(OP_GOTO), \
- H(OP_GOTO_16), \
- H(OP_GOTO_32), \
- H(OP_PACKED_SWITCH), \
- H(OP_SPARSE_SWITCH), \
- H(OP_CMPL_FLOAT), \
- H(OP_CMPG_FLOAT), \
- H(OP_CMPL_DOUBLE), \
- H(OP_CMPG_DOUBLE), \
- H(OP_CMP_LONG), \
- H(OP_IF_EQ), \
- H(OP_IF_NE), \
- H(OP_IF_LT), \
- H(OP_IF_GE), \
- H(OP_IF_GT), \
- H(OP_IF_LE), \
- H(OP_IF_EQZ), \
- H(OP_IF_NEZ), \
- H(OP_IF_LTZ), \
- H(OP_IF_GEZ), \
- H(OP_IF_GTZ), \
- H(OP_IF_LEZ), \
- H(OP_UNUSED_3E), \
- H(OP_UNUSED_3F), \
- H(OP_UNUSED_40), \
- H(OP_UNUSED_41), \
- H(OP_UNUSED_42), \
- H(OP_UNUSED_43), \
- H(OP_AGET), \
- H(OP_AGET_WIDE), \
- H(OP_AGET_OBJECT), \
- H(OP_AGET_BOOLEAN), \
- H(OP_AGET_BYTE), \
- H(OP_AGET_CHAR), \
- H(OP_AGET_SHORT), \
- H(OP_APUT), \
- H(OP_APUT_WIDE), \
- H(OP_APUT_OBJECT), \
- H(OP_APUT_BOOLEAN), \
- H(OP_APUT_BYTE), \
- H(OP_APUT_CHAR), \
- H(OP_APUT_SHORT), \
- H(OP_IGET), \
- H(OP_IGET_WIDE), \
- H(OP_IGET_OBJECT), \
- H(OP_IGET_BOOLEAN), \
- H(OP_IGET_BYTE), \
- H(OP_IGET_CHAR), \
- H(OP_IGET_SHORT), \
- H(OP_IPUT), \
- H(OP_IPUT_WIDE), \
- H(OP_IPUT_OBJECT), \
- H(OP_IPUT_BOOLEAN), \
- H(OP_IPUT_BYTE), \
- H(OP_IPUT_CHAR), \
- H(OP_IPUT_SHORT), \
- H(OP_SGET), \
- H(OP_SGET_WIDE), \
- H(OP_SGET_OBJECT), \
- H(OP_SGET_BOOLEAN), \
- H(OP_SGET_BYTE), \
- H(OP_SGET_CHAR), \
- H(OP_SGET_SHORT), \
- H(OP_SPUT), \
- H(OP_SPUT_WIDE), \
- H(OP_SPUT_OBJECT), \
- H(OP_SPUT_BOOLEAN), \
- H(OP_SPUT_BYTE), \
- H(OP_SPUT_CHAR), \
- H(OP_SPUT_SHORT), \
- H(OP_INVOKE_VIRTUAL), \
- H(OP_INVOKE_SUPER), \
- H(OP_INVOKE_DIRECT), \
- H(OP_INVOKE_STATIC), \
- H(OP_INVOKE_INTERFACE), \
- H(OP_UNUSED_73), \
- H(OP_INVOKE_VIRTUAL_RANGE), \
- H(OP_INVOKE_SUPER_RANGE), \
- H(OP_INVOKE_DIRECT_RANGE), \
- H(OP_INVOKE_STATIC_RANGE), \
- H(OP_INVOKE_INTERFACE_RANGE), \
- H(OP_UNUSED_79), \
- H(OP_UNUSED_7A), \
- H(OP_NEG_INT), \
- H(OP_NOT_INT), \
- H(OP_NEG_LONG), \
- H(OP_NOT_LONG), \
- H(OP_NEG_FLOAT), \
- H(OP_NEG_DOUBLE), \
- H(OP_INT_TO_LONG), \
- H(OP_INT_TO_FLOAT), \
- H(OP_INT_TO_DOUBLE), \
- H(OP_LONG_TO_INT), \
- H(OP_LONG_TO_FLOAT), \
- H(OP_LONG_TO_DOUBLE), \
- H(OP_FLOAT_TO_INT), \
- H(OP_FLOAT_TO_LONG), \
- H(OP_FLOAT_TO_DOUBLE), \
- H(OP_DOUBLE_TO_INT), \
- H(OP_DOUBLE_TO_LONG), \
- H(OP_DOUBLE_TO_FLOAT), \
- H(OP_INT_TO_BYTE), \
- H(OP_INT_TO_CHAR), \
- H(OP_INT_TO_SHORT), \
- H(OP_ADD_INT), \
- H(OP_SUB_INT), \
- H(OP_MUL_INT), \
- H(OP_DIV_INT), \
- H(OP_REM_INT), \
- H(OP_AND_INT), \
- H(OP_OR_INT), \
- H(OP_XOR_INT), \
- H(OP_SHL_INT), \
- H(OP_SHR_INT), \
- H(OP_USHR_INT), \
- H(OP_ADD_LONG), \
- H(OP_SUB_LONG), \
- H(OP_MUL_LONG), \
- H(OP_DIV_LONG), \
- H(OP_REM_LONG), \
- H(OP_AND_LONG), \
- H(OP_OR_LONG), \
- H(OP_XOR_LONG), \
- H(OP_SHL_LONG), \
- H(OP_SHR_LONG), \
- H(OP_USHR_LONG), \
- H(OP_ADD_FLOAT), \
- H(OP_SUB_FLOAT), \
- H(OP_MUL_FLOAT), \
- H(OP_DIV_FLOAT), \
- H(OP_REM_FLOAT), \
- H(OP_ADD_DOUBLE), \
- H(OP_SUB_DOUBLE), \
- H(OP_MUL_DOUBLE), \
- H(OP_DIV_DOUBLE), \
- H(OP_REM_DOUBLE), \
- H(OP_ADD_INT_2ADDR), \
- H(OP_SUB_INT_2ADDR), \
- H(OP_MUL_INT_2ADDR), \
- H(OP_DIV_INT_2ADDR), \
- H(OP_REM_INT_2ADDR), \
- H(OP_AND_INT_2ADDR), \
- H(OP_OR_INT_2ADDR), \
- H(OP_XOR_INT_2ADDR), \
- H(OP_SHL_INT_2ADDR), \
- H(OP_SHR_INT_2ADDR), \
- H(OP_USHR_INT_2ADDR), \
- H(OP_ADD_LONG_2ADDR), \
- H(OP_SUB_LONG_2ADDR), \
- H(OP_MUL_LONG_2ADDR), \
- H(OP_DIV_LONG_2ADDR), \
- H(OP_REM_LONG_2ADDR), \
- H(OP_AND_LONG_2ADDR), \
- H(OP_OR_LONG_2ADDR), \
- H(OP_XOR_LONG_2ADDR), \
- H(OP_SHL_LONG_2ADDR), \
- H(OP_SHR_LONG_2ADDR), \
- H(OP_USHR_LONG_2ADDR), \
- H(OP_ADD_FLOAT_2ADDR), \
- H(OP_SUB_FLOAT_2ADDR), \
- H(OP_MUL_FLOAT_2ADDR), \
- H(OP_DIV_FLOAT_2ADDR), \
- H(OP_REM_FLOAT_2ADDR), \
- H(OP_ADD_DOUBLE_2ADDR), \
- H(OP_SUB_DOUBLE_2ADDR), \
- H(OP_MUL_DOUBLE_2ADDR), \
- H(OP_DIV_DOUBLE_2ADDR), \
- H(OP_REM_DOUBLE_2ADDR), \
- H(OP_ADD_INT_LIT16), \
- H(OP_RSUB_INT), \
- H(OP_MUL_INT_LIT16), \
- H(OP_DIV_INT_LIT16), \
- H(OP_REM_INT_LIT16), \
- H(OP_AND_INT_LIT16), \
- H(OP_OR_INT_LIT16), \
- H(OP_XOR_INT_LIT16), \
- H(OP_ADD_INT_LIT8), \
- H(OP_RSUB_INT_LIT8), \
- H(OP_MUL_INT_LIT8), \
- H(OP_DIV_INT_LIT8), \
- H(OP_REM_INT_LIT8), \
- H(OP_AND_INT_LIT8), \
- H(OP_OR_INT_LIT8), \
- H(OP_XOR_INT_LIT8), \
- H(OP_SHL_INT_LIT8), \
- H(OP_SHR_INT_LIT8), \
- H(OP_USHR_INT_LIT8), \
- H(OP_IGET_VOLATILE), \
- H(OP_IPUT_VOLATILE), \
- H(OP_SGET_VOLATILE), \
- H(OP_SPUT_VOLATILE), \
- H(OP_IGET_OBJECT_VOLATILE), \
- H(OP_IGET_WIDE_VOLATILE), \
- H(OP_IPUT_WIDE_VOLATILE), \
- H(OP_SGET_WIDE_VOLATILE), \
- H(OP_SPUT_WIDE_VOLATILE), \
- H(OP_BREAKPOINT), \
- H(OP_THROW_VERIFICATION_ERROR), \
- H(OP_EXECUTE_INLINE), \
- H(OP_EXECUTE_INLINE_RANGE), \
- H(OP_INVOKE_OBJECT_INIT_RANGE), \
- H(OP_RETURN_VOID_BARRIER), \
- H(OP_IGET_QUICK), \
- H(OP_UNUSED_F3), \
- H(OP_UNUSED_F4), \
- H(OP_UNUSED_F5), \
- H(OP_UNUSED_F6), \
- H(OP_UNUSED_F7), \
- H(OP_UNUSED_F8), \
- H(OP_UNUSED_F9), \
- H(OP_INVOKE_POLYMORPHIC), \
- H(OP_INVOKE_POLYMORPHIC_RANGE), \
- H(OP_INVOKE_CUSTOM), \
- H(OP_INVOKE_CUSTOM_RANGE), \
- H(OP_CONST_METHOD_HANDLE), \
- H(OP_CONST_METHOD_TYPE), \
- /* END(libdex-goto-table) */ \
- };
-
-/*
- * Return the Opcode for a given raw opcode code unit (which may
- * include data payload). The packed index is a zero-based index which
- * can be used to point into various opcode-related tables. The Dalvik
- * opcode space is inherently sparse, in that the opcode unit is 16
- * bits wide, but for most opcodes, eight of those bits are for data.
- */
-DEX_INLINE Opcode dexOpcodeFromCodeUnit(u2 codeUnit) {
- /*
- * This will want to become table-driven should the opcode layout
- * get more complicated.
- *
- * Note: This has to match the corresponding code in opcode-gen, so
- * that data tables get generated in a consistent way.
- */
- int lowByte = codeUnit & 0xff;
- return (Opcode) lowByte;
-}
-
-/*
- * Return the name of an opcode.
- */
-const char* dexGetOpcodeName(Opcode op);
-
-#endif // LIBDEX_DEXOPCODES_H_
diff --git a/libdex/DexOptData.cpp b/libdex/DexOptData.cpp
deleted file mode 100644
index 109e851f9..000000000
--- a/libdex/DexOptData.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions to parse and manipulate the additional data tables added
- * to optimized .dex files.
- */
-
-#include <zlib.h>
-
-#include "DexOptData.h"
-
-/*
- * Check to see if a given data pointer is a valid double-word-aligned
- * pointer into the given memory range (from start inclusive to end
- * exclusive). Returns true if valid.
- */
-static bool isValidPointer(const void* ptr, const void* start, const void* end)
-{
- return (ptr >= start) && (ptr < end) && (((uintptr_t) ptr & 7) == 0);
-}
-
-/* (documented in header file) */
-u4 dexComputeOptChecksum(const DexOptHeader* pOptHeader)
-{
- const u1* start = (const u1*) pOptHeader + pOptHeader->depsOffset;
- const u1* end = (const u1*) pOptHeader +
- pOptHeader->optOffset + pOptHeader->optLength;
-
- uLong adler = adler32(0L, Z_NULL, 0);
-
- return (u4) adler32(adler, start, end - start);
-}
-
-/* (documented in header file) */
-bool dexParseOptData(const u1* data, size_t length, DexFile* pDexFile)
-{
- const void* pOptStart = data + pDexFile->pOptHeader->optOffset;
- const void* pOptEnd = data + length;
- const u4* pOpt = (const u4*) pOptStart;
- u4 optLength = (const u1*) pOptEnd - (const u1*) pOptStart;
-
- /*
- * Make sure the opt data start is in range and aligned. This may
- * seem like a superfluous check, but (a) if the file got
- * truncated, it might turn out that pOpt >= pOptEnd; and (b)
- * if the opt data header got corrupted, pOpt might not be
- * properly aligned. This test will catch both of these cases.
- */
- if (!isValidPointer(pOpt, pOptStart, pOptEnd)) {
- ALOGE("Bogus opt data start pointer");
- return false;
- }
-
- /* Make sure that the opt data length is a whole number of words. */
- if ((optLength & 3) != 0) {
- ALOGE("Unaligned opt data area end");
- return false;
- }
-
- /*
- * Make sure that the opt data area is large enough to have at least
- * one chunk header.
- */
- if (optLength < 8) {
- ALOGE("Undersized opt data area (%u)", optLength);
- return false;
- }
-
- /* Process chunks until we see the end marker. */
- while (*pOpt != kDexChunkEnd) {
- if (!isValidPointer(pOpt + 2, pOptStart, pOptEnd)) {
- const u4 offset = ((const u1*) pOpt) - data;
- ALOGE("Bogus opt data content pointer at offset %u", offset);
- return false;
- }
-
- u4 size = *(pOpt + 1);
- const u1* pOptData = (const u1*) (pOpt + 2);
-
- /*
- * The rounded size is 64-bit aligned and includes +8 for the
- * type/size header (which was extracted immediately above).
- */
- u4 roundedSize = (size + 8 + 7) & ~7;
- const u4* pNextOpt = pOpt + (roundedSize / sizeof(u4));
-
- if (!isValidPointer(pNextOpt, pOptStart, pOptEnd)) {
- const u4 offset = ((const u1*) pOpt) - data;
- ALOGE("Opt data area problem for chunk of size %u at offset %u", size, offset);
- return false;
- }
-
- switch (*pOpt) {
- case kDexChunkClassLookup:
- pDexFile->pClassLookup = (const DexClassLookup*) pOptData;
- break;
- case kDexChunkRegisterMaps:
- ALOGV("+++ found register maps, size=%u", size);
- pDexFile->pRegisterMapPool = pOptData;
- break;
- default:
- ALOGI("Unknown chunk 0x%08x (%c%c%c%c), size=%d in opt data area",
- *pOpt,
- (char) ((*pOpt) >> 24), (char) ((*pOpt) >> 16),
- (char) ((*pOpt) >> 8), (char) (*pOpt),
- size);
- break;
- }
-
- pOpt = pNextOpt;
- }
-
- return true;
-}
diff --git a/libdex/DexOptData.h b/libdex/DexOptData.h
deleted file mode 100644
index 69eda0142..000000000
--- a/libdex/DexOptData.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions to parse and manipulate the additional data tables added
- * to optimized .dex files.
- */
-
-#ifndef _LIBDEX_DEXOPTDATA
-#define _LIBDEX_DEXOPTDATA
-
-#include "libdex/DexFile.h"
-
-/*
- * Parse the optimized data tables in the given dex file.
- *
- * @param data pointer to the start of the entire dex file
- * @param length length of the entire dex file, in bytes
- * @param pDexFile pointer to the associated dex file structure
- */
-bool dexParseOptData(const u1* data, size_t length, DexFile* pDexFile);
-
-/*
- * Compute the checksum of the optimized data tables pointed at by the given
- * header.
- */
-u4 dexComputeOptChecksum(const DexOptHeader* pOptHeader);
-
-#endif /* def _LIBDEX_DEXOPTDATA */
diff --git a/libdex/DexProto.cpp b/libdex/DexProto.cpp
deleted file mode 100644
index 06c59b37d..000000000
--- a/libdex/DexProto.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions for dealing with method prototypes
- */
-
-#include "DexProto.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * ===========================================================================
- * String Cache
- * ===========================================================================
- */
-
-/*
- * Make sure that the given cache can hold a string of the given length,
- * including the final '\0' byte.
- */
-void dexStringCacheAlloc(DexStringCache* pCache, size_t length) {
- if (pCache->allocatedSize != 0) {
- if (pCache->allocatedSize >= length) {
- return;
- }
- free((void*) pCache->value);
- }
-
- if (length <= sizeof(pCache->buffer)) {
- pCache->value = pCache->buffer;
- pCache->allocatedSize = 0;
- } else {
- pCache->value = (char*) malloc(length);
- pCache->allocatedSize = length;
- }
-}
-
-/*
- * Initialize the given DexStringCache. Use this function before passing
- * one into any other function.
- */
-void dexStringCacheInit(DexStringCache* pCache) {
- pCache->value = pCache->buffer;
- pCache->allocatedSize = 0;
- pCache->buffer[0] = '\0';
-}
-
-/*
- * Release the allocated contents of the given DexStringCache, if any.
- * Use this function after your last use of a DexStringCache.
- */
-void dexStringCacheRelease(DexStringCache* pCache) {
- if (pCache->allocatedSize != 0) {
- free((void*) pCache->value);
- pCache->value = pCache->buffer;
- pCache->allocatedSize = 0;
- }
-}
-
-/*
- * If the given DexStringCache doesn't already point at the given value,
- * make a copy of it into the cache. This always returns a writable
- * pointer to the contents (whether or not a copy had to be made). This
- * function is intended to be used after making a call that at least
- * sometimes doesn't populate a DexStringCache.
- */
-char* dexStringCacheEnsureCopy(DexStringCache* pCache, const char* value) {
- if (value != pCache->value) {
- size_t length = strlen(value) + 1;
- dexStringCacheAlloc(pCache, length);
- memcpy(pCache->value, value, length);
- }
-
- return pCache->value;
-}
-
-/*
- * Abandon the given DexStringCache, and return a writable copy of the
- * given value (reusing the string cache's allocation if possible).
- * The return value must be free()d by the caller. Use this instead of
- * dexStringCacheRelease() if you want the buffer to survive past the
- * scope of the DexStringCache.
- */
-char* dexStringCacheAbandon(DexStringCache* pCache, const char* value) {
- if ((value == pCache->value) && (pCache->allocatedSize != 0)) {
- char* result = pCache->value;
- pCache->allocatedSize = 0;
- pCache->value = pCache->buffer;
- return result;
- } else {
- return strdup(value);
- }
-}
-
-
-/*
- * ===========================================================================
- * Method Prototypes
- * ===========================================================================
- */
-
-/*
- * Return the DexProtoId from the given DexProto. The DexProto must
- * actually refer to a DexProtoId.
- */
-static inline const DexProtoId* getProtoId(const DexProto* pProto) {
- return dexGetProtoId(pProto->dexFile, pProto->protoIdx);
-}
-
-/* (documented in header file) */
-const char* dexProtoGetShorty(const DexProto* pProto) {
- const DexProtoId* protoId = getProtoId(pProto);
-
- return dexStringById(pProto->dexFile, protoId->shortyIdx);
-}
-
-/* (documented in header file) */
-const char* dexProtoGetMethodDescriptor(const DexProto* pProto,
- DexStringCache* pCache) {
- const DexFile* dexFile = pProto->dexFile;
- const DexProtoId* protoId = getProtoId(pProto);
- const DexTypeList* typeList = dexGetProtoParameters(dexFile, protoId);
- size_t length = 3; // parens and terminating '\0'
- u4 paramCount = (typeList == NULL) ? 0 : typeList->size;
- u4 i;
-
- for (i = 0; i < paramCount; i++) {
- u4 idx = dexTypeListGetIdx(typeList, i);
- length += strlen(dexStringByTypeIdx(dexFile, idx));
- }
-
- length += strlen(dexStringByTypeIdx(dexFile, protoId->returnTypeIdx));
-
- dexStringCacheAlloc(pCache, length);
-
- char *at = (char*) pCache->value;
- *(at++) = '(';
-
- for (i = 0; i < paramCount; i++) {
- u4 idx = dexTypeListGetIdx(typeList, i);
- const char* desc = dexStringByTypeIdx(dexFile, idx);
- strcpy(at, desc);
- at += strlen(desc);
- }
-
- *(at++) = ')';
-
- strcpy(at, dexStringByTypeIdx(dexFile, protoId->returnTypeIdx));
- return pCache->value;
-}
-
-/* (documented in header file) */
-char* dexProtoCopyMethodDescriptor(const DexProto* pProto) {
- DexStringCache cache;
-
- dexStringCacheInit(&cache);
- return dexStringCacheAbandon(&cache,
- dexProtoGetMethodDescriptor(pProto, &cache));
-}
-
-/* (documented in header file) */
-const char* dexProtoGetParameterDescriptors(const DexProto* pProto,
- DexStringCache* pCache) {
- DexParameterIterator iterator;
- size_t length = 1; /* +1 for the terminating '\0' */
-
- dexParameterIteratorInit(&iterator, pProto);
-
- for (;;) {
- const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
- if (descriptor == NULL) {
- break;
- }
-
- length += strlen(descriptor);
- }
-
- dexParameterIteratorInit(&iterator, pProto);
-
- dexStringCacheAlloc(pCache, length);
- char *at = (char*) pCache->value;
-
- for (;;) {
- const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
- if (descriptor == NULL) {
- break;
- }
-
- strcpy(at, descriptor);
- at += strlen(descriptor);
- }
-
- return pCache->value;
-}
-
-/* (documented in header file) */
-const char* dexProtoGetReturnType(const DexProto* pProto) {
- const DexProtoId* protoId = getProtoId(pProto);
- return dexStringByTypeIdx(pProto->dexFile, protoId->returnTypeIdx);
-}
-
-/* (documented in header file) */
-size_t dexProtoGetParameterCount(const DexProto* pProto) {
- const DexProtoId* protoId = getProtoId(pProto);
- const DexTypeList* typeList =
- dexGetProtoParameters(pProto->dexFile, protoId);
- return (typeList == NULL) ? 0 : typeList->size;
-}
-
-/* (documented in header file) */
-int dexProtoComputeArgsSize(const DexProto* pProto) {
- const char* shorty = dexProtoGetShorty(pProto);
- int count = 0;
-
- /* Skip the return type. */
- shorty++;
-
- for (;;) {
- switch (*(shorty++)) {
- case '\0': {
- return count;
- }
- case 'D':
- case 'J': {
- count += 2;
- break;
- }
- default: {
- count++;
- break;
- }
- }
- }
-}
-
-/*
- * Common implementation for dexProtoCompare() and dexProtoCompareParameters().
- */
-static int protoCompare(const DexProto* pProto1, const DexProto* pProto2,
- bool compareReturnType) {
-
- if (pProto1 == pProto2) {
- // Easy out.
- return 0;
- } else {
- const DexFile* dexFile1 = pProto1->dexFile;
- const DexProtoId* protoId1 = getProtoId(pProto1);
- const DexTypeList* typeList1 =
- dexGetProtoParameters(dexFile1, protoId1);
- int paramCount1 = (typeList1 == NULL) ? 0 : typeList1->size;
-
- const DexFile* dexFile2 = pProto2->dexFile;
- const DexProtoId* protoId2 = getProtoId(pProto2);
- const DexTypeList* typeList2 =
- dexGetProtoParameters(dexFile2, protoId2);
- int paramCount2 = (typeList2 == NULL) ? 0 : typeList2->size;
-
- if (protoId1 == protoId2) {
- // Another easy out.
- return 0;
- }
-
- // Compare return types.
-
- if (compareReturnType) {
- int result =
- strcmp(dexStringByTypeIdx(dexFile1, protoId1->returnTypeIdx),
- dexStringByTypeIdx(dexFile2, protoId2->returnTypeIdx));
-
- if (result != 0) {
- return result;
- }
- }
-
- // Compare parameters.
-
- int minParam = (paramCount1 > paramCount2) ? paramCount2 : paramCount1;
- int i;
-
- for (i = 0; i < minParam; i++) {
- u4 idx1 = dexTypeListGetIdx(typeList1, i);
- u4 idx2 = dexTypeListGetIdx(typeList2, i);
- int result =
- strcmp(dexStringByTypeIdx(dexFile1, idx1),
- dexStringByTypeIdx(dexFile2, idx2));
-
- if (result != 0) {
- return result;
- }
- }
-
- if (paramCount1 < paramCount2) {
- return -1;
- } else if (paramCount1 > paramCount2) {
- return 1;
- } else {
- return 0;
- }
- }
-}
-
-/* (documented in header file) */
-int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2) {
- return protoCompare(pProto1, pProto2, true);
-}
-
-/* (documented in header file) */
-int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2){
- return protoCompare(pProto1, pProto2, false);
-}
-
-
-/*
- * Helper for dexProtoCompareToDescriptor(), which gets the return type
- * descriptor from a method descriptor string.
- */
-static const char* methodDescriptorReturnType(const char* descriptor) {
- const char* result = strchr(descriptor, ')');
-
- if (result == NULL) {
- return NULL;
- }
-
- // The return type is the character just past the ')'.
- return result + 1;
-}
-
-/*
- * Helper for dexProtoCompareToDescriptor(), which indicates the end
- * of an embedded argument type descriptor, which is also the
- * beginning of the next argument type descriptor. Since this is for
- * argument types, it doesn't accept 'V' as a valid type descriptor.
- */
-static const char* methodDescriptorNextType(const char* descriptor) {
- // Skip any array references.
-
- while (*descriptor == '[') {
- descriptor++;
- }
-
- switch (*descriptor) {
- case 'B': case 'C': case 'D': case 'F':
- case 'I': case 'J': case 'S': case 'Z': {
- return descriptor + 1;
- }
- case 'L': {
- const char* result = strchr(descriptor + 1, ';');
- if (result != NULL) {
- // The type ends just past the ';'.
- return result + 1;
- }
- }
- }
-
- return NULL;
-}
-
-/*
- * Common implementation for dexProtoCompareToDescriptor() and
- * dexProtoCompareToParameterDescriptors(). The descriptor argument
- * can be either a full method descriptor (with parens and a return
- * type) or an unadorned concatenation of types (e.g. a list of
- * argument types).
- */
-static int protoCompareToParameterDescriptors(const DexProto* proto,
- const char* descriptor, bool expectParens) {
- char expectedEndChar = expectParens ? ')' : '\0';
- DexParameterIterator iterator;
- dexParameterIteratorInit(&iterator, proto);
-
- if (expectParens) {
- // Skip the '('.
- assert (*descriptor == '(');
- descriptor++;
- }
-
- for (;;) {
- const char* protoDesc = dexParameterIteratorNextDescriptor(&iterator);
-
- if (*descriptor == expectedEndChar) {
- // It's the end of the descriptor string.
- if (protoDesc == NULL) {
- // It's also the end of the prototype's arguments.
- return 0;
- } else {
- // The prototype still has more arguments.
- return 1;
- }
- }
-
- if (protoDesc == NULL) {
- /*
- * The prototype doesn't have arguments left, but the
- * descriptor string does.
- */
- return -1;
- }
-
- // Both prototype and descriptor have arguments. Compare them.
-
- const char* nextDesc = methodDescriptorNextType(descriptor);
- assert(nextDesc != NULL);
-
- for (;;) {
- char c1 = *(protoDesc++);
- char c2 = (descriptor < nextDesc) ? *(descriptor++) : '\0';
-
- if (c1 < c2) {
- // This includes the case where the proto is shorter.
- return -1;
- } else if (c1 > c2) {
- // This includes the case where the desc is shorter.
- return 1;
- } else if (c1 == '\0') {
- // The two types are equal in length. (c2 necessarily == '\0'.)
- break;
- }
- }
-
- /*
- * If we made it here, the two arguments matched, and
- * descriptor == nextDesc.
- */
- }
-}
-
-/* (documented in header file) */
-int dexProtoCompareToDescriptor(const DexProto* proto,
- const char* descriptor) {
- // First compare the return types.
-
- const char *returnType = methodDescriptorReturnType(descriptor);
- assert(returnType != NULL);
-
- int result = strcmp(dexProtoGetReturnType(proto), returnType);
-
- if (result != 0) {
- return result;
- }
-
- // The return types match, so we have to check arguments.
- return protoCompareToParameterDescriptors(proto, descriptor, true);
-}
-
-/* (documented in header file) */
-int dexProtoCompareToParameterDescriptors(const DexProto* proto,
- const char* descriptors) {
- return protoCompareToParameterDescriptors(proto, descriptors, false);
-}
-
-
-
-
-
-
-/*
- * ===========================================================================
- * Parameter Iterators
- * ===========================================================================
- */
-
-/*
- * Initialize the given DexParameterIterator to be at the start of the
- * parameters of the given prototype.
- */
-void dexParameterIteratorInit(DexParameterIterator* pIterator,
- const DexProto* pProto) {
- pIterator->proto = pProto;
- pIterator->cursor = 0;
-
- pIterator->parameters =
- dexGetProtoParameters(pProto->dexFile, getProtoId(pProto));
- pIterator->parameterCount = (pIterator->parameters == NULL) ? 0
- : pIterator->parameters->size;
-}
-
-/*
- * Get the type_id index for the next parameter, if any. This returns
- * kDexNoIndex if the last parameter has already been consumed.
- */
-u4 dexParameterIteratorNextIndex(DexParameterIterator* pIterator) {
- int cursor = pIterator->cursor;
- int parameterCount = pIterator->parameterCount;
-
- if (cursor >= parameterCount) {
- // The iteration is complete.
- return kDexNoIndex;
- } else {
- u4 idx = dexTypeListGetIdx(pIterator->parameters, cursor);
- pIterator->cursor++;
- return idx;
- }
-}
-
-/*
- * Get the type descriptor for the next parameter, if any. This returns
- * NULL if the last parameter has already been consumed.
- */
-const char* dexParameterIteratorNextDescriptor(
- DexParameterIterator* pIterator) {
- u4 idx = dexParameterIteratorNextIndex(pIterator);
-
- if (idx == kDexNoIndex) {
- return NULL;
- }
-
- return dexStringByTypeIdx(pIterator->proto->dexFile, idx);
-}
diff --git a/libdex/DexProto.h b/libdex/DexProto.h
deleted file mode 100644
index dccae6c04..000000000
--- a/libdex/DexProto.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions for dealing with method prototypes
- */
-
-#ifndef LIBDEX_DEXPROTO_H_
-#define LIBDEX_DEXPROTO_H_
-
-#include "DexFile.h"
-
-/*
- * Single-thread single-string cache. This structure holds a pointer to
- * a string which is semi-automatically manipulated by some of the
- * method prototype functions. Functions which use in this struct
- * generally return a string that is valid until the next
- * time the same DexStringCache is used.
- */
-struct DexStringCache {
- char* value; /* the latest value */
- size_t allocatedSize; /* size of the allocated buffer, if allocated */
- char buffer[120]; /* buffer used to hold small-enough results */
-};
-
-/*
- * Make sure that the given cache can hold a string of the given length,
- * including the final '\0' byte.
- */
-void dexStringCacheAlloc(DexStringCache* pCache, size_t length);
-
-/*
- * Initialize the given DexStringCache. Use this function before passing
- * one into any other function.
- */
-void dexStringCacheInit(DexStringCache* pCache);
-
-/*
- * Release the allocated contents of the given DexStringCache, if any.
- * Use this function after your last use of a DexStringCache.
- */
-void dexStringCacheRelease(DexStringCache* pCache);
-
-/*
- * If the given DexStringCache doesn't already point at the given value,
- * make a copy of it into the cache. This always returns a writable
- * pointer to the contents (whether or not a copy had to be made). This
- * function is intended to be used after making a call that at least
- * sometimes doesn't populate a DexStringCache.
- */
-char* dexStringCacheEnsureCopy(DexStringCache* pCache, const char* value);
-
-/*
- * Abandon the given DexStringCache, and return a writable copy of the
- * given value (reusing the string cache's allocation if possible).
- * The return value must be free()d by the caller. Use this instead of
- * dexStringCacheRelease() if you want the buffer to survive past the
- * scope of the DexStringCache.
- */
-char* dexStringCacheAbandon(DexStringCache* pCache, const char* value);
-
-/*
- * Method prototype structure, which refers to a protoIdx in a
- * particular DexFile.
- */
-struct DexProto {
- const DexFile* dexFile; /* file the idx refers to */
- u4 protoIdx; /* index into proto_ids table of dexFile */
-};
-
-/*
- * Set the given DexProto to refer to the prototype of the given MethodId.
- */
-DEX_INLINE void dexProtoSetFromMethodId(DexProto* pProto,
- const DexFile* pDexFile, const DexMethodId* pMethodId)
-{
- pProto->dexFile = pDexFile;
- pProto->protoIdx = pMethodId->protoIdx;
-}
-
-/*
- * Get the short-form method descriptor for the given prototype. The
- * prototype must be protoIdx-based.
- */
-const char* dexProtoGetShorty(const DexProto* pProto);
-
-/*
- * Get the full method descriptor for the given prototype.
- */
-const char* dexProtoGetMethodDescriptor(const DexProto* pProto,
- DexStringCache* pCache);
-
-/*
- * Get a copy of the descriptor string associated with the given prototype.
- * The returned pointer must be free()ed by the caller.
- */
-char* dexProtoCopyMethodDescriptor(const DexProto* pProto);
-
-/*
- * Get the parameter descriptors for the given prototype. This is the
- * concatenation of all the descriptors for all the parameters, in
- * order, with no other adornment.
- */
-const char* dexProtoGetParameterDescriptors(const DexProto* pProto,
- DexStringCache* pCache);
-
-/*
- * Return the utf-8 encoded descriptor string from the proto of a MethodId.
- */
-DEX_INLINE const char* dexGetDescriptorFromMethodId(const DexFile* pDexFile,
- const DexMethodId* pMethodId, DexStringCache* pCache)
-{
- DexProto proto;
-
- dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
- return dexProtoGetMethodDescriptor(&proto, pCache);
-}
-
-/*
- * Get a copy of the utf-8 encoded method descriptor string from the
- * proto of a MethodId. The returned pointer must be free()ed by the
- * caller.
- */
-DEX_INLINE char* dexCopyDescriptorFromMethodId(const DexFile* pDexFile,
- const DexMethodId* pMethodId)
-{
- DexProto proto;
-
- dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
- return dexProtoCopyMethodDescriptor(&proto);
-}
-
-/*
- * Get the type descriptor for the return type of the given prototype.
- */
-const char* dexProtoGetReturnType(const DexProto* pProto);
-
-/*
- * Get the parameter count of the given prototype.
- */
-size_t dexProtoGetParameterCount(const DexProto* pProto);
-
-/*
- * Compute the number of parameter words (u4 units) required by the
- * given prototype. For example, if the method takes (int, long) and
- * returns double, this would return 3 (one for the int, two for the
- * long, and the return type isn't relevant).
- */
-int dexProtoComputeArgsSize(const DexProto* pProto);
-
-/*
- * Compare the two prototypes. The two prototypes are compared
- * with the return type as the major order, then the first arguments,
- * then second, etc. If two prototypes are identical except that one
- * has extra arguments, then the shorter argument is considered the
- * earlier one in sort order (similar to strcmp()).
- */
-int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2);
-
-/*
- * Compare the two prototypes, ignoring return type. The two
- * prototypes are compared with the first argument as the major order,
- * then second, etc. If two prototypes are identical except that one
- * has extra arguments, then the shorter argument is considered the
- * earlier one in sort order (similar to strcmp()).
- */
-int dexProtoCompareParameters(const DexProto* pProto1,
- const DexProto* pProto2);
-
-/*
- * Compare a prototype and a string method descriptor. The comparison
- * is done as if the descriptor were converted to a prototype and compared
- * with dexProtoCompare().
- */
-int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor);
-
-/*
- * Compare a prototype and a concatenation of type descriptors. The
- * comparison is done as if the descriptors were converted to a
- * prototype and compared with dexProtoCompareParameters().
- */
-int dexProtoCompareToParameterDescriptors(const DexProto* proto,
- const char* descriptors);
-
-/*
- * Single-thread prototype parameter iterator. This structure holds a
- * pointer to a prototype and its parts, along with a cursor.
- */
-struct DexParameterIterator {
- const DexProto* proto;
- const DexTypeList* parameters;
- int parameterCount;
- int cursor;
-};
-
-/*
- * Initialize the given DexParameterIterator to be at the start of the
- * parameters of the given prototype.
- */
-void dexParameterIteratorInit(DexParameterIterator* pIterator,
- const DexProto* pProto);
-
-/*
- * Get the type_id index for the next parameter, if any. This returns
- * kDexNoIndex if the last parameter has already been consumed.
- */
-u4 dexParameterIteratorNextIndex(DexParameterIterator* pIterator);
-
-/*
- * Get the type descriptor for the next parameter, if any. This returns
- * NULL if the last parameter has already been consumed.
- */
-const char* dexParameterIteratorNextDescriptor(
- DexParameterIterator* pIterator);
-
-#endif // LIBDEX_DEXPROTO_H_
diff --git a/libdex/DexSwapVerify.cpp b/libdex/DexSwapVerify.cpp
deleted file mode 100644
index 8ffc74371..000000000
--- a/libdex/DexSwapVerify.cpp
+++ /dev/null
@@ -1,3070 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Byte-swapping and verification of dex files.
- */
-
-#include "DexFile.h"
-#include "DexClass.h"
-#include "DexDataMap.h"
-#include "DexProto.h"
-#include "DexUtf.h"
-#include "Leb128.h"
-
-#include <zlib.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#define SWAP2(_value) (_value)
-#define SWAP4(_value) (_value)
-#define SWAP8(_value) (_value)
-
-#define SWAP_FIELD2(_field) (_field) = SWAP2(_field)
-#define SWAP_FIELD4(_field) (_field) = SWAP4(_field)
-#define SWAP_FIELD8(_field) (_field) = SWAP8(_field)
-
-/*
- * Some information we pass around to help verify values.
- */
-struct CheckState {
- const DexHeader* pHeader;
- const u1* fileStart;
- const u1* fileEnd; // points to fileStart + fileLen
- u4 fileLen;
- DexDataMap* pDataMap; // set after map verification
- const DexFile* pDexFile; // set after intraitem verification
- const DexMapItem* pCallSiteIds; // set after intraitem verification
- const DexMapItem* pMethodHandleItems; // set after intraitem verification
-
- /*
- * bitmap of type_id indices that have been used to define classes;
- * initialized immediately before class_def cross-verification, and
- * freed immediately after it
- */
- u4* pDefinedClassBits;
-
- const void* previousItem; // set during section iteration
-};
-
-/*
- * Return the file offset of the given pointer.
- */
-static inline u4 fileOffset(const CheckState* state, const void* ptr) {
- return ((const u1*) ptr) - state->fileStart;
-}
-
-/*
- * Return a pointer for the given file offset.
- */
-static inline void* filePointer(const CheckState* state, u4 offset) {
- return (void*) (state->fileStart + offset);
-}
-
-/*
- * Verify that a pointer range, start inclusive to end exclusive, only
- * covers bytes in the file and doesn't point beyond the end of the
- * file. That is, the start must indicate a valid byte or may point at
- * the byte just past the end of the file (but no further), and the
- * end must be no less than the start and must also not point beyond
- * the byte just past the end of the file.
- */
-static inline bool checkPtrRange(const CheckState* state,
- const void* start, const void* end, const char* label) {
- const void* fileStart = state->fileStart;
- const void* fileEnd = state->fileEnd;
- if ((start < fileStart) || (start > fileEnd)
- || (end < start) || (end > fileEnd)) {
- ALOGW("Bad offset range for %s: %#x..%#x", label,
- fileOffset(state, start), fileOffset(state, end));
- return false;
- }
- return true;
-}
-
-/*
- * Verify that a range of offsets, start inclusive to end exclusive,
- * are all valid. That is, the start must indicate a valid byte or may
- * point at the byte just past the end of the file (but no further),
- * and the end must be no less than the start and must also not point
- * beyond the byte just past the end of the file.
- *
- * Assumes "const CheckState* state".
- */
-#define CHECK_OFFSET_RANGE(_start, _end) { \
- const u1* _startPtr = (const u1*) filePointer(state, (_start)); \
- const u1* _endPtr = (const u1*) filePointer(state, (_end)); \
- if (!checkPtrRange(state, _startPtr, _endPtr, \
- #_start ".." #_end)) { \
- return 0; \
- } \
- }
-
-/*
- * Verify that a pointer range, start inclusive to end exclusive, only
- * covers bytes in the file and doesn't point beyond the end of the
- * file. That is, the start must indicate a valid byte or may point at
- * the byte just past the end of the file (but no further), and the
- * end must be no less than the start and must also not point beyond
- * the byte just past the end of the file.
- *
- * Assumes "const CheckState* state".
- */
-#define CHECK_PTR_RANGE(_start, _end) { \
- if (!checkPtrRange(state, (_start), (_end), #_start ".." #_end)) { \
- return 0; \
- } \
- }
-
-/*
- * Make sure a list of items fits entirely within the file.
- *
- * Assumes "const CheckState* state" and "typeof(_count) == typeof(_elemSize)"
- * If the type sizes or signs are mismatched, this will return 0.
- */
-#define CHECK_LIST_SIZE(_ptr, _count, _elemSize) { \
- const u1* _start = (const u1*) (_ptr); \
- const u1* _end = _start + ((_count) * (_elemSize)); \
- u4 _dummy; \
- if (__builtin_mul_overflow((_count), (_elemSize), &_dummy) || \
- !checkPtrRange(state, _start, _end, #_ptr)) { \
- return 0; \
- } \
- }
-
-/*
- * Swap a field that is known to hold an absolute DEX file offset. Note:
- * This does not check to see that the swapped offset points within the
- * mapped file, since that should be handled (with even more rigor) by
- * the cross-verification phase.
- *
- * Assumes "const CheckState* state".
- */
-#define SWAP_OFFSET4(_field) { \
- SWAP_FIELD4((_field)); \
- }
-
-/*
- * Verify that an index falls in a valid range.
- */
-#define CHECK_INDEX(_field, _limit) { \
- if ((_field) >= (_limit)) { \
- ALOGW("Bad index: %s(%u) > %s(%u)", \
- #_field, (u4)(_field), #_limit, (u4)(_limit)); \
- return 0; \
- } \
- }
-
-/*
- * Swap an index, and verify that it falls in a valid range.
- */
-#define SWAP_INDEX2(_field, _limit) { \
- SWAP_FIELD2((_field)); \
- CHECK_INDEX((_field), (_limit)); \
- }
-
-/*
- * Verify that an index falls in a valid range or is kDexNoIndex.
- */
-#define CHECK_INDEX_OR_NOINDEX(_field, _limit) { \
- if ((_field) != kDexNoIndex && (_field) >= (_limit)) { \
- ALOGW("Bad index: %s(%u) > %s(%u)", \
- #_field, (u4)(_field), #_limit, (u4)(_limit)); \
- return 0; \
- } \
- }
-
-/*
- * Swap an index, and verify that it falls in a valid range.
- */
-#define SWAP_INDEX4(_field, _limit) { \
- SWAP_FIELD4((_field)); \
- CHECK_INDEX((_field), (_limit)); \
- }
-
-/*
- * Swap an index, and verify that it falls in a valid range or is
- * kDexNoIndex.
- */
-#define SWAP_INDEX4_OR_NOINDEX(_field, _limit) { \
- SWAP_FIELD4((_field)); \
- CHECK_INDEX_OR_NOINDEX((_field), (_limit)); \
- }
-
-/* Verify the definer of a given field_idx. */
-static bool verifyFieldDefiner(const CheckState* state, u4 definingClass,
- u4 fieldIdx) {
- const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx);
- return field->classIdx == definingClass;
-}
-
-/* Verify the definer of a given method_idx. */
-static bool verifyMethodDefiner(const CheckState* state, u4 definingClass,
- u4 methodIdx) {
- const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx);
- return meth->classIdx == definingClass;
-}
-
-/*
- * Calculate the required size (in elements) of the array pointed at by
- * pDefinedClassBits.
- */
-static size_t calcDefinedClassBitsSize(const CheckState* state)
-{
- // Divide typeIdsSize by 32 (0x20), rounding up.
- return (state->pHeader->typeIdsSize + 0x1f) >> 5;
-}
-
-/*
- * Set the given bit in pDefinedClassBits, returning its former value.
- */
-static bool setDefinedClassBit(const CheckState* state, u4 typeIdx) {
- u4 arrayIdx = typeIdx >> 5;
- u4 bit = 1 << (typeIdx & 0x1f);
- u4* element = &state->pDefinedClassBits[arrayIdx];
- bool result = (*element & bit) != 0;
-
- *element |= bit;
-
- return result;
-}
-
-/*
- * Swap the header_item.
- */
-static bool swapDexHeader(const CheckState* state, DexHeader* pHeader)
-{
- CHECK_PTR_RANGE(pHeader, pHeader + 1);
-
- // magic is ok
- SWAP_FIELD4(pHeader->checksum);
- // signature is ok
- SWAP_FIELD4(pHeader->fileSize);
- SWAP_FIELD4(pHeader->headerSize);
- SWAP_FIELD4(pHeader->endianTag);
- SWAP_FIELD4(pHeader->linkSize);
- SWAP_OFFSET4(pHeader->linkOff);
- SWAP_OFFSET4(pHeader->mapOff);
- SWAP_FIELD4(pHeader->stringIdsSize);
- SWAP_OFFSET4(pHeader->stringIdsOff);
- SWAP_FIELD4(pHeader->typeIdsSize);
- SWAP_OFFSET4(pHeader->typeIdsOff);
- SWAP_FIELD4(pHeader->fieldIdsSize);
- SWAP_OFFSET4(pHeader->fieldIdsOff);
- SWAP_FIELD4(pHeader->methodIdsSize);
- SWAP_OFFSET4(pHeader->methodIdsOff);
- SWAP_FIELD4(pHeader->protoIdsSize);
- SWAP_OFFSET4(pHeader->protoIdsOff);
- SWAP_FIELD4(pHeader->classDefsSize);
- SWAP_OFFSET4(pHeader->classDefsOff);
- SWAP_FIELD4(pHeader->dataSize);
- SWAP_OFFSET4(pHeader->dataOff);
-
- if (pHeader->endianTag != kDexEndianConstant) {
- ALOGE("Unexpected endian_tag: %#x", pHeader->endianTag);
- return false;
- }
-
- // Assign variables so the diagnostic is prettier. (Hooray for macros.)
- u4 linkOff = pHeader->linkOff;
- u4 linkEnd = linkOff + pHeader->linkSize;
- u4 dataOff = pHeader->dataOff;
- u4 dataEnd = dataOff + pHeader->dataSize;
- CHECK_OFFSET_RANGE(linkOff, linkEnd);
- CHECK_OFFSET_RANGE(dataOff, dataEnd);
-
- /*
- * Note: The offsets and ranges of the other header items end up getting
- * checked during the first iteration over the map.
- */
-
- return true;
-}
-
-/* Check the header section for sanity. */
-static bool checkHeaderSection(const CheckState* state, u4 sectionOffset,
- u4 sectionCount, u4* endOffset) {
- if (sectionCount != 1) {
- ALOGE("Multiple header items");
- return false;
- }
-
- if (sectionOffset != 0) {
- ALOGE("Header at %#x; not at start of file", sectionOffset);
- return false;
- }
-
- const DexHeader* pHeader = (const DexHeader*) filePointer(state, 0);
- *endOffset = pHeader->headerSize;
- return true;
-}
-
-/*
- * Helper for swapMap(), which turns a map type constant into a small
- * one-bit-on integer, suitable for use in an int-sized bit set.
- */
-static u4 mapTypeToBitMask(int mapType) {
- switch (mapType) {
- case kDexTypeHeaderItem: return 1 << 0;
- case kDexTypeStringIdItem: return 1 << 1;
- case kDexTypeTypeIdItem: return 1 << 2;
- case kDexTypeProtoIdItem: return 1 << 3;
- case kDexTypeFieldIdItem: return 1 << 4;
- case kDexTypeMethodIdItem: return 1 << 5;
- case kDexTypeClassDefItem: return 1 << 6;
- case kDexTypeMapList: return 1 << 7;
- case kDexTypeTypeList: return 1 << 8;
- case kDexTypeAnnotationSetRefList: return 1 << 9;
- case kDexTypeAnnotationSetItem: return 1 << 10;
- case kDexTypeClassDataItem: return 1 << 11;
- case kDexTypeCodeItem: return 1 << 12;
- case kDexTypeStringDataItem: return 1 << 13;
- case kDexTypeDebugInfoItem: return 1 << 14;
- case kDexTypeAnnotationItem: return 1 << 15;
- case kDexTypeEncodedArrayItem: return 1 << 16;
- case kDexTypeAnnotationsDirectoryItem: return 1 << 17;
- case kDexTypeCallSiteIdItem: return 1 << 18;
- case kDexTypeMethodHandleItem: return 1 << 19;
- default: {
- ALOGE("Unknown map item type %04x", mapType);
- return 0;
- }
- }
-}
-
-/*
- * Helper for swapMap(), which indicates if an item type should appear
- * in the data section.
- */
-static bool isDataSectionType(int mapType) {
- switch (mapType) {
- case kDexTypeHeaderItem:
- case kDexTypeStringIdItem:
- case kDexTypeTypeIdItem:
- case kDexTypeProtoIdItem:
- case kDexTypeFieldIdItem:
- case kDexTypeMethodIdItem:
- case kDexTypeClassDefItem: {
- return false;
- }
- }
-
- return true;
-}
-
-/*
- * Swap the map_list and verify what we can about it. Also, if verification
- * passes, allocate the state's DexDataMap.
- */
-static bool swapMap(CheckState* state, DexMapList* pMap)
-{
- DexMapItem* item = pMap->list;
- u4 count;
- u4 dataItemCount = 0; // Total count of items in the data section.
- u4 dataItemsLeft = state->pHeader->dataSize; // See use below.
- u4 usedBits = 0; // Bit set: one bit per section
- bool first = true;
- u4 lastOffset = 0;
-
- SWAP_FIELD4(pMap->size);
- count = pMap->size;
- const u4 sizeOfItem = (u4) sizeof(DexMapItem);
- CHECK_LIST_SIZE(item, count, sizeOfItem);
-
- while (count--) {
- SWAP_FIELD2(item->type);
- SWAP_FIELD2(item->unused);
- SWAP_FIELD4(item->size);
- SWAP_OFFSET4(item->offset);
-
- if (first) {
- first = false;
- } else if (lastOffset >= item->offset) {
- ALOGE("Out-of-order map item: %#x then %#x",
- lastOffset, item->offset);
- return false;
- }
-
- if (item->offset >= state->pHeader->fileSize) {
- ALOGE("Map item after end of file: %x, size %#x",
- item->offset, state->pHeader->fileSize);
- return false;
- }
-
- if (isDataSectionType(item->type)) {
- u4 icount = item->size;
-
- /*
- * This sanity check on the data section items ensures that
- * there are no more items than the number of bytes in
- * the data section.
- */
- if (icount > dataItemsLeft) {
- ALOGE("Unrealistically many items in the data section: "
- "at least %d", dataItemCount + icount);
- return false;
- }
-
- dataItemsLeft -= icount;
- dataItemCount += icount;
- }
-
- u4 bit = mapTypeToBitMask(item->type);
-
- if (bit == 0) {
- return false;
- }
-
- if ((usedBits & bit) != 0) {
- ALOGE("Duplicate map section of type %#x", item->type);
- return false;
- }
-
- if (item->type == kDexTypeCallSiteIdItem) {
- state->pCallSiteIds = item;
- } else if (item->type == kDexTypeMethodHandleItem) {
- state->pMethodHandleItems = item;
- }
-
- usedBits |= bit;
- lastOffset = item->offset;
- item++;
- }
-
- if ((usedBits & mapTypeToBitMask(kDexTypeHeaderItem)) == 0) {
- ALOGE("Map is missing header entry");
- return false;
- }
-
- if ((usedBits & mapTypeToBitMask(kDexTypeMapList)) == 0) {
- ALOGE("Map is missing map_list entry");
- return false;
- }
-
- if (((usedBits & mapTypeToBitMask(kDexTypeStringIdItem)) == 0)
- && ((state->pHeader->stringIdsOff != 0)
- || (state->pHeader->stringIdsSize != 0))) {
- ALOGE("Map is missing string_ids entry");
- return false;
- }
-
- if (((usedBits & mapTypeToBitMask(kDexTypeTypeIdItem)) == 0)
- && ((state->pHeader->typeIdsOff != 0)
- || (state->pHeader->typeIdsSize != 0))) {
- ALOGE("Map is missing type_ids entry");
- return false;
- }
-
- if (((usedBits & mapTypeToBitMask(kDexTypeProtoIdItem)) == 0)
- && ((state->pHeader->protoIdsOff != 0)
- || (state->pHeader->protoIdsSize != 0))) {
- ALOGE("Map is missing proto_ids entry");
- return false;
- }
-
- if (((usedBits & mapTypeToBitMask(kDexTypeFieldIdItem)) == 0)
- && ((state->pHeader->fieldIdsOff != 0)
- || (state->pHeader->fieldIdsSize != 0))) {
- ALOGE("Map is missing field_ids entry");
- return false;
- }
-
- if (((usedBits & mapTypeToBitMask(kDexTypeMethodIdItem)) == 0)
- && ((state->pHeader->methodIdsOff != 0)
- || (state->pHeader->methodIdsSize != 0))) {
- ALOGE("Map is missing method_ids entry");
- return false;
- }
-
- if (((usedBits & mapTypeToBitMask(kDexTypeClassDefItem)) == 0)
- && ((state->pHeader->classDefsOff != 0)
- || (state->pHeader->classDefsSize != 0))) {
- ALOGE("Map is missing class_defs entry");
- return false;
- }
-
- state->pDataMap = dexDataMapAlloc(dataItemCount);
- if (state->pDataMap == NULL) {
- ALOGE("Unable to allocate data map (size %#x)", dataItemCount);
- return false;
- }
-
- return true;
-}
-
-/* Check the map section for sanity. */
-static bool checkMapSection(const CheckState* state, u4 sectionOffset,
- u4 sectionCount, u4* endOffset) {
- if (sectionCount != 1) {
- ALOGE("Multiple map list items");
- return false;
- }
-
- if (sectionOffset != state->pHeader->mapOff) {
- ALOGE("Map not at header-defined offset: %#x, expected %#x",
- sectionOffset, state->pHeader->mapOff);
- return false;
- }
-
- const DexMapList* pMap = (const DexMapList*) filePointer(state, sectionOffset);
-
- *endOffset =
- sectionOffset + sizeof(u4) + (pMap->size * sizeof(DexMapItem));
- return true;
-}
-
-/* Perform byte-swapping and intra-item verification on string_id_item. */
-static void* swapStringIdItem(const CheckState* state, void* ptr) {
- DexStringId* item = (DexStringId*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_OFFSET4(item->stringDataOff);
-
- return item + 1;
-}
-
-/* Perform cross-item verification of string_id_item. */
-static void* crossVerifyStringIdItem(const CheckState* state, void* ptr) {
- const DexStringId* item = (const DexStringId*) ptr;
-
- if (!dexDataMapVerify(state->pDataMap,
- item->stringDataOff, kDexTypeStringDataItem)) {
- return NULL;
- }
-
- const DexStringId* item0 = (const DexStringId*) state->previousItem;
- if (item0 != NULL) {
- // Check ordering.
- const char* s0 = dexGetStringData(state->pDexFile, item0);
- const char* s1 = dexGetStringData(state->pDexFile, item);
- if (dexUtf8Cmp(s0, s1) >= 0) {
- ALOGE("Out-of-order string_ids: '%s' then '%s'", s0, s1);
- return NULL;
- }
- }
-
- return (void*) (item + 1);
-}
-
-/* Perform byte-swapping and intra-item verification on type_id_item. */
-static void* swapTypeIdItem(const CheckState* state, void* ptr) {
- DexTypeId* item = (DexTypeId*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_INDEX4(item->descriptorIdx, state->pHeader->stringIdsSize);
-
- return item + 1;
-}
-
-/* Perform cross-item verification of type_id_item. */
-static void* crossVerifyTypeIdItem(const CheckState* state, void* ptr) {
- const DexTypeId* item = (const DexTypeId*) ptr;
- const char* descriptor =
- dexStringById(state->pDexFile, item->descriptorIdx);
-
- if (!dexIsValidTypeDescriptor(descriptor)) {
- ALOGE("Invalid type descriptor: '%s'", descriptor);
- return NULL;
- }
-
- const DexTypeId* item0 = (const DexTypeId*) state->previousItem;
- if (item0 != NULL) {
- // Check ordering. This relies on string_ids being in order.
- if (item0->descriptorIdx >= item->descriptorIdx) {
- ALOGE("Out-of-order type_ids: %#x then %#x",
- item0->descriptorIdx, item->descriptorIdx);
- return NULL;
- }
- }
-
- return (void*) (item + 1);
-}
-
-/* Perform byte-swapping and intra-item verification on proto_id_item. */
-static void* swapProtoIdItem(const CheckState* state, void* ptr) {
- DexProtoId* item = (DexProtoId*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_INDEX4(item->shortyIdx, state->pHeader->stringIdsSize);
- SWAP_INDEX4(item->returnTypeIdx, state->pHeader->typeIdsSize);
- SWAP_OFFSET4(item->parametersOff);
-
- return item + 1;
-}
-
-/* Helper for crossVerifyProtoIdItem(), which checks a shorty character
- * to see if it is compatible with a type descriptor. Returns true if
- * so, false if not. */
-static bool shortyDescMatch(char shorty, const char* descriptor, bool
- isReturnType) {
- switch (shorty) {
- case 'V': {
- if (!isReturnType) {
- ALOGE("Invalid use of void");
- return false;
- }
- FALLTHROUGH_INTENDED;
- }
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'I':
- case 'J':
- case 'S':
- case 'Z': {
- if ((descriptor[0] != shorty) || (descriptor[1] != '\0')) {
- ALOGE("Shorty vs. primitive type mismatch: '%c', '%s'",
- shorty, descriptor);
- return false;
- }
- break;
- }
- case 'L': {
- if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
- ALOGE("Shorty vs. type mismatch: '%c', '%s'",
- shorty, descriptor);
- return false;
- }
- break;
- }
- default: {
- ALOGE("Bogus shorty: '%c'", shorty);
- return false;
- }
- }
-
- return true;
-}
-
-/* Perform cross-item verification of proto_id_item. */
-static void* crossVerifyProtoIdItem(const CheckState* state, void* ptr) {
- const DexProtoId* item = (const DexProtoId*) ptr;
- const char* shorty =
- dexStringById(state->pDexFile, item->shortyIdx);
-
- if (!dexDataMapVerify0Ok(state->pDataMap,
- item->parametersOff, kDexTypeTypeList)) {
- return NULL;
- }
-
- if (!shortyDescMatch(*shorty,
- dexStringByTypeIdx(state->pDexFile, item->returnTypeIdx),
- true)) {
- return NULL;
- }
-
- u4 protoIdx = item - state->pDexFile->pProtoIds;
- DexProto proto = { state->pDexFile, protoIdx };
- DexParameterIterator iterator;
-
- dexParameterIteratorInit(&iterator, &proto);
- shorty++; // Skip the return type.
-
- for (;;) {
- const char *desc = dexParameterIteratorNextDescriptor(&iterator);
-
- if (desc == NULL) {
- break;
- }
-
- if (*shorty == '\0') {
- ALOGE("Shorty is too short");
- return NULL;
- }
-
- if (!shortyDescMatch(*shorty, desc, false)) {
- return NULL;
- }
-
- shorty++;
- }
-
- if (*shorty != '\0') {
- ALOGE("Shorty is too long");
- return NULL;
- }
-
- const DexProtoId* item0 = (const DexProtoId*) state->previousItem;
- if (item0 != NULL) {
- // Check ordering. This relies on type_ids being in order.
- if (item0->returnTypeIdx > item->returnTypeIdx) {
- ALOGE("Out-of-order proto_id return types");
- return NULL;
- } else if (item0->returnTypeIdx == item->returnTypeIdx) {
- bool badOrder = false;
- DexProto proto0 = { state->pDexFile, protoIdx - 1 };
- DexParameterIterator iterator0;
-
- dexParameterIteratorInit(&iterator, &proto);
- dexParameterIteratorInit(&iterator0, &proto0);
-
- for (;;) {
- u4 idx0 = dexParameterIteratorNextIndex(&iterator0);
- u4 idx1 = dexParameterIteratorNextIndex(&iterator);
-
- if (idx1 == kDexNoIndex) {
- badOrder = true;
- break;
- }
-
- if (idx0 == kDexNoIndex) {
- break;
- }
-
- if (idx0 < idx1) {
- break;
- } else if (idx0 > idx1) {
- badOrder = true;
- break;
- }
- }
-
- if (badOrder) {
- ALOGE("Out-of-order proto_id arguments");
- return NULL;
- }
- }
- }
-
- return (void*) (item + 1);
-}
-
-/* Perform byte-swapping and intra-item verification on field_id_item. */
-static void* swapFieldIdItem(const CheckState* state, void* ptr) {
- DexFieldId* item = (DexFieldId*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize);
- SWAP_INDEX2(item->typeIdx, state->pHeader->typeIdsSize);
- SWAP_INDEX4(item->nameIdx, state->pHeader->stringIdsSize);
-
- return item + 1;
-}
-
-/* Perform cross-item verification of field_id_item. */
-static void* crossVerifyFieldIdItem(const CheckState* state, void* ptr) {
- const DexFieldId* item = (const DexFieldId*) ptr;
- const char* s;
-
- s = dexStringByTypeIdx(state->pDexFile, item->classIdx);
- if (!dexIsClassDescriptor(s)) {
- ALOGE("Invalid descriptor for class_idx: '%s'", s);
- return NULL;
- }
-
- s = dexStringByTypeIdx(state->pDexFile, item->typeIdx);
- if (!dexIsFieldDescriptor(s)) {
- ALOGE("Invalid descriptor for type_idx: '%s'", s);
- return NULL;
- }
-
- s = dexStringById(state->pDexFile, item->nameIdx);
- if (!dexIsValidMemberName(s)) {
- ALOGE("Invalid name: '%s'", s);
- return NULL;
- }
-
- const DexFieldId* item0 = (const DexFieldId*) state->previousItem;
- if (item0 != NULL) {
- // Check ordering. This relies on the other sections being in order.
- bool done = false;
- bool bogus = false;
-
- if (item0->classIdx > item->classIdx) {
- bogus = true;
- done = true;
- } else if (item0->classIdx < item->classIdx) {
- done = true;
- }
-
- if (!done) {
- if (item0->nameIdx > item->nameIdx) {
- bogus = true;
- done = true;
- } else if (item0->nameIdx < item->nameIdx) {
- done = true;
- }
- }
-
- if (!done) {
- if (item0->typeIdx >= item->typeIdx) {
- bogus = true;
- }
- }
-
- if (bogus) {
- ALOGE("Out-of-order field_ids");
- return NULL;
- }
- }
-
- return (void*) (item + 1);
-}
-
-/* Perform byte-swapping and intra-item verification on method_id_item. */
-static void* swapMethodIdItem(const CheckState* state, void* ptr) {
- DexMethodId* item = (DexMethodId*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize);
- SWAP_INDEX2(item->protoIdx, state->pHeader->protoIdsSize);
- SWAP_INDEX4(item->nameIdx, state->pHeader->stringIdsSize);
-
- return item + 1;
-}
-
-/* Perform cross-item verification of method_id_item. */
-static void* crossVerifyMethodIdItem(const CheckState* state, void* ptr) {
- const DexMethodId* item = (const DexMethodId*) ptr;
- const char* s;
-
- s = dexStringByTypeIdx(state->pDexFile, item->classIdx);
- if (!dexIsReferenceDescriptor(s)) {
- ALOGE("Invalid descriptor for class_idx: '%s'", s);
- return NULL;
- }
-
- s = dexStringById(state->pDexFile, item->nameIdx);
- if (!dexIsValidMemberName(s)) {
- ALOGE("Invalid name: '%s'", s);
- return NULL;
- }
-
- const DexMethodId* item0 = (const DexMethodId*) state->previousItem;
- if (item0 != NULL) {
- // Check ordering. This relies on the other sections being in order.
- bool done = false;
- bool bogus = false;
-
- if (item0->classIdx > item->classIdx) {
- bogus = true;
- done = true;
- } else if (item0->classIdx < item->classIdx) {
- done = true;
- }
-
- if (!done) {
- if (item0->nameIdx > item->nameIdx) {
- bogus = true;
- done = true;
- } else if (item0->nameIdx < item->nameIdx) {
- done = true;
- }
- }
-
- if (!done) {
- if (item0->protoIdx >= item->protoIdx) {
- bogus = true;
- }
- }
-
- if (bogus) {
- ALOGE("Out-of-order method_ids");
- return NULL;
- }
- }
-
- return (void*) (item + 1);
-}
-
-/* Perform byte-swapping and intra-item verification on class_def_item. */
-static void* swapClassDefItem(const CheckState* state, void* ptr) {
- DexClassDef* item = (DexClassDef*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_INDEX4(item->classIdx, state->pHeader->typeIdsSize);
- SWAP_FIELD4(item->accessFlags);
- SWAP_INDEX4_OR_NOINDEX(item->superclassIdx, state->pHeader->typeIdsSize);
- SWAP_OFFSET4(item->interfacesOff);
- SWAP_INDEX4_OR_NOINDEX(item->sourceFileIdx, state->pHeader->stringIdsSize);
- SWAP_OFFSET4(item->annotationsOff);
- SWAP_OFFSET4(item->classDataOff);
-
- if ((item->accessFlags & ~ACC_CLASS_MASK) != 0) {
- // The VM specification says that unknown flags should be ignored.
- ALOGV("Bogus class access flags %x", item->accessFlags);
- item->accessFlags &= ACC_CLASS_MASK;
- }
-
- return item + 1;
-}
-
-/* defined below */
-static u4 findFirstClassDataDefiner(const CheckState* state,
- DexClassData* classData);
-static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state,
- const DexAnnotationsDirectoryItem* dir);
-
-/* Helper for crossVerifyClassDefItem(), which checks a class_data_item to
- * make sure all its references are to a given class. */
-static bool verifyClassDataIsForDef(const CheckState* state, u4 offset,
- u4 definerIdx) {
- if (offset == 0) {
- return true;
- }
-
- const u1* data = (const u1*) filePointer(state, offset);
- DexClassData* classData = dexReadAndVerifyClassData(&data, NULL);
-
- if (classData == NULL) {
- // Shouldn't happen, but bail here just in case.
- return false;
- }
-
- /*
- * The class_data_item verification ensures that
- * it consistently refers to the same definer, so all we need to
- * do is check the first one.
- */
- u4 dataDefiner = findFirstClassDataDefiner(state, classData);
- bool result = (dataDefiner == definerIdx) || (dataDefiner == kDexNoIndex);
-
- free(classData);
- return result;
-}
-
-/* Helper for crossVerifyClassDefItem(), which checks an
- * annotations_directory_item to make sure all its references are to a
- * given class. */
-static bool verifyAnnotationsDirectoryIsForDef(const CheckState* state,
- u4 offset, u4 definerIdx) {
- if (offset == 0) {
- return true;
- }
-
- const DexAnnotationsDirectoryItem* dir =
- (const DexAnnotationsDirectoryItem*) filePointer(state, offset);
- u4 annoDefiner = findFirstAnnotationsDirectoryDefiner(state, dir);
-
- return (annoDefiner == definerIdx) || (annoDefiner == kDexNoIndex);
-}
-
-/* Perform cross-item verification of class_def_item. */
-static void* crossVerifyClassDefItem(const CheckState* state, void* ptr) {
- const DexClassDef* item = (const DexClassDef*) ptr;
- u4 classIdx = item->classIdx;
- const char* descriptor = dexStringByTypeIdx(state->pDexFile, classIdx);
-
- if (!dexIsClassDescriptor(descriptor)) {
- ALOGE("Invalid class: '%s'", descriptor);
- return NULL;
- }
-
- if (setDefinedClassBit(state, classIdx)) {
- ALOGE("Duplicate class definition: '%s'", descriptor);
- return NULL;
- }
-
- bool okay =
- dexDataMapVerify0Ok(state->pDataMap,
- item->interfacesOff, kDexTypeTypeList)
- && dexDataMapVerify0Ok(state->pDataMap,
- item->annotationsOff, kDexTypeAnnotationsDirectoryItem)
- && dexDataMapVerify0Ok(state->pDataMap,
- item->classDataOff, kDexTypeClassDataItem)
- && dexDataMapVerify0Ok(state->pDataMap,
- item->staticValuesOff, kDexTypeEncodedArrayItem);
-
- if (!okay) {
- return NULL;
- }
-
- if (item->superclassIdx != kDexNoIndex) {
- descriptor = dexStringByTypeIdx(state->pDexFile, item->superclassIdx);
- if (!dexIsClassDescriptor(descriptor)) {
- ALOGE("Invalid superclass: '%s'", descriptor);
- return NULL;
- }
- }
-
- const DexTypeList* interfaces =
- dexGetInterfacesList(state->pDexFile, item);
- if (interfaces != NULL) {
- u4 size = interfaces->size;
- u4 i;
-
- /*
- * Ensure that all interfaces refer to classes (not arrays or
- * primitives).
- */
- for (i = 0; i < size; i++) {
- descriptor = dexStringByTypeIdx(state->pDexFile,
- dexTypeListGetIdx(interfaces, i));
- if (!dexIsClassDescriptor(descriptor)) {
- ALOGE("Invalid interface: '%s'", descriptor);
- return NULL;
- }
- }
-
- /*
- * Ensure that there are no duplicates. This is an O(N^2) test,
- * but in practice the number of interfaces implemented by any
- * given class is low. I will buy a milkshake for the
- * first person to show me a realistic case for which this test
- * would be unacceptably slow.
- */
- for (i = 1; i < size; i++) {
- u4 idx1 = dexTypeListGetIdx(interfaces, i);
- u4 j;
- for (j = 0; j < i; j++) {
- u4 idx2 = dexTypeListGetIdx(interfaces, j);
- if (idx1 == idx2) {
- ALOGE("Duplicate interface: '%s'",
- dexStringByTypeIdx(state->pDexFile, idx1));
- return NULL;
- }
- }
- }
- }
-
- if (!verifyClassDataIsForDef(state, item->classDataOff, item->classIdx)) {
- ALOGE("Invalid class_data_item");
- return NULL;
- }
-
- if (!verifyAnnotationsDirectoryIsForDef(state, item->annotationsOff,
- item->classIdx)) {
- ALOGE("Invalid annotations_directory_item");
- return NULL;
- }
-
- return (void*) (item + 1);
-}
-
-/* Perform cross-item verification of call_site_id. */
-static void* crossVerifyCallSiteId(const CheckState* state, void* ptr) {
- const DexCallSiteId* item = (const DexCallSiteId*) ptr;
- if (state->pCallSiteIds == nullptr) {
- ALOGE("Verifying call site but expecting none");
- return NULL;
- }
- if (item->callSiteOff < state->pHeader->dataOff ||
- item->callSiteOff >= state->pHeader->dataOff + state->pHeader->dataSize) {
- ALOGE("Bad call site offset: %u", item->callSiteOff);
- return NULL;
- }
- return (void*) (item + 1);
-}
-
-/* Perform cross-item verification of method_handle_item. */
-static void* crossVerifyMethodHandleItem(const CheckState* state, void* ptr) {
- const DexMethodHandleItem* item = (const DexMethodHandleItem*) ptr;
- if (state->pMethodHandleItems == nullptr) {
- ALOGE("Verifying method handle but expecting none");
- return NULL;
- }
- if (item->methodHandleType > (u2) MethodHandleType::INVOKE_INTERFACE) {
- ALOGE("Unknown method handle type: %u", item->methodHandleType);
- return NULL;
- }
- switch ((MethodHandleType) item->methodHandleType) {
- case MethodHandleType::STATIC_PUT:
- case MethodHandleType::STATIC_GET:
- case MethodHandleType::INSTANCE_PUT:
- case MethodHandleType::INSTANCE_GET:
- if (item->fieldOrMethodIdx >= state->pHeader->fieldIdsSize) {
- ALOGE("Method handle has invalid field id: %u\n", item->fieldOrMethodIdx);
- return NULL;
- }
- break;
- case MethodHandleType::INVOKE_STATIC:
- case MethodHandleType::INVOKE_INSTANCE:
- case MethodHandleType::INVOKE_CONSTRUCTOR:
- case MethodHandleType::INVOKE_DIRECT:
- case MethodHandleType::INVOKE_INTERFACE:
- if (item->fieldOrMethodIdx >= state->pHeader->methodIdsSize) {
- ALOGE("Method handle has invalid method id: %u\n", item->fieldOrMethodIdx);
- return NULL;
- }
- break;
- }
- return (void*) (item + 1);
-}
-
-/* Helper for swapAnnotationsDirectoryItem(), which performs
- * byte-swapping and intra-item verification on an
- * annotation_directory_item's field elements. */
-static u1* swapFieldAnnotations(const CheckState* state, u4 count, u1* addr) {
- DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr;
- bool first = true;
- u4 lastIdx = 0;
-
- const u4 sizeOfItem = (u4) sizeof(DexFieldAnnotationsItem);
- CHECK_LIST_SIZE(item, count, sizeOfItem);
-
- while (count--) {
- SWAP_INDEX4(item->fieldIdx, state->pHeader->fieldIdsSize);
- SWAP_OFFSET4(item->annotationsOff);
-
- if (first) {
- first = false;
- } else if (lastIdx >= item->fieldIdx) {
- ALOGE("Out-of-order field_idx: %#x then %#x", lastIdx,
- item->fieldIdx);
- return NULL;
- }
-
- lastIdx = item->fieldIdx;
- item++;
- }
-
- return (u1*) item;
-}
-
-/* Helper for swapAnnotationsDirectoryItem(), which performs
- * byte-swapping and intra-item verification on an
- * annotation_directory_item's method elements. */
-static u1* swapMethodAnnotations(const CheckState* state, u4 count, u1* addr) {
- DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr;
- bool first = true;
- u4 lastIdx = 0;
-
- const u4 sizeOfItem = (u4) sizeof(DexMethodAnnotationsItem);
- CHECK_LIST_SIZE(item, count, sizeOfItem);
-
- while (count--) {
- SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize);
- SWAP_OFFSET4(item->annotationsOff);
-
- if (first) {
- first = false;
- } else if (lastIdx >= item->methodIdx) {
- ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx,
- item->methodIdx);
- return NULL;
- }
-
- lastIdx = item->methodIdx;
- item++;
- }
-
- return (u1*) item;
-}
-
-/* Helper for swapAnnotationsDirectoryItem(), which performs
- * byte-swapping and intra-item verification on an
- * annotation_directory_item's parameter elements. */
-static u1* swapParameterAnnotations(const CheckState* state, u4 count,
- u1* addr) {
- DexParameterAnnotationsItem* item = (DexParameterAnnotationsItem*) addr;
- bool first = true;
- u4 lastIdx = 0;
-
- const u4 sizeOfItem = (u4) sizeof(DexParameterAnnotationsItem);
- CHECK_LIST_SIZE(item, count, sizeOfItem);
-
- while (count--) {
- SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize);
- SWAP_OFFSET4(item->annotationsOff);
-
- if (first) {
- first = false;
- } else if (lastIdx >= item->methodIdx) {
- ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx,
- item->methodIdx);
- return NULL;
- }
-
- lastIdx = item->methodIdx;
- item++;
- }
-
- return (u1*) item;
-}
-
-/* Perform byte-swapping and intra-item verification on
- * annotations_directory_item. */
-static void* swapAnnotationsDirectoryItem(const CheckState* state, void* ptr) {
- DexAnnotationsDirectoryItem* item = (DexAnnotationsDirectoryItem*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_OFFSET4(item->classAnnotationsOff);
- SWAP_FIELD4(item->fieldsSize);
- SWAP_FIELD4(item->methodsSize);
- SWAP_FIELD4(item->parametersSize);
-
- u1* addr = (u1*) (item + 1);
-
- if (item->fieldsSize != 0) {
- addr = swapFieldAnnotations(state, item->fieldsSize, addr);
- if (addr == NULL) {
- return NULL;
- }
- }
-
- if (item->methodsSize != 0) {
- addr = swapMethodAnnotations(state, item->methodsSize, addr);
- if (addr == NULL) {
- return NULL;
- }
- }
-
- if (item->parametersSize != 0) {
- addr = swapParameterAnnotations(state, item->parametersSize, addr);
- if (addr == NULL) {
- return NULL;
- }
- }
-
- return addr;
-}
-
-static void* swapCallSiteId(const CheckState* state, void* ptr) {
- DexCallSiteId* item = (DexCallSiteId*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_OFFSET4(item->callSiteOff);
-
- return (item + 1);
-}
-
-static void* swapMethodHandleItem(const CheckState* state, void* ptr) {
- DexMethodHandleItem* item = (DexMethodHandleItem*) ptr;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_FIELD2(item->methodHandleType);
- SWAP_FIELD2(item->fieldOrMethodIdx);
-
- return (item + 1);
-}
-
-
-/* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the
- * field elements. */
-static const u1* crossVerifyFieldAnnotations(const CheckState* state, u4 count,
- const u1* addr, u4 definingClass) {
- const DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr;
-
- while (count--) {
- if (!verifyFieldDefiner(state, definingClass, item->fieldIdx)) {
- return NULL;
- }
- if (!dexDataMapVerify(state->pDataMap, item->annotationsOff,
- kDexTypeAnnotationSetItem)) {
- return NULL;
- }
- item++;
- }
-
- return (const u1*) item;
-}
-
-/* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the
- * method elements. */
-static const u1* crossVerifyMethodAnnotations(const CheckState* state,
- u4 count, const u1* addr, u4 definingClass) {
- const DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr;
-
- while (count--) {
- if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) {
- return NULL;
- }
- if (!dexDataMapVerify(state->pDataMap, item->annotationsOff,
- kDexTypeAnnotationSetItem)) {
- return NULL;
- }
- item++;
- }
-
- return (const u1*) item;
-}
-
-/* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the
- * parameter elements. */
-static const u1* crossVerifyParameterAnnotations(const CheckState* state,
- u4 count, const u1* addr, u4 definingClass) {
- const DexParameterAnnotationsItem* item =
- (DexParameterAnnotationsItem*) addr;
-
- while (count--) {
- if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) {
- return NULL;
- }
- if (!dexDataMapVerify(state->pDataMap, item->annotationsOff,
- kDexTypeAnnotationSetRefList)) {
- return NULL;
- }
- item++;
- }
-
- return (const u1*) item;
-}
-
-/* Helper for crossVerifyClassDefItem() and
- * crossVerifyAnnotationsDirectoryItem(), which finds the type_idx of
- * the definer of the first item in the data. */
-static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state,
- const DexAnnotationsDirectoryItem* dir) {
- if (dir->fieldsSize != 0) {
- const DexFieldAnnotationsItem* fields =
- dexGetFieldAnnotations(state->pDexFile, dir);
- const DexFieldId* field =
- dexGetFieldId(state->pDexFile, fields[0].fieldIdx);
- return field->classIdx;
- }
-
- if (dir->methodsSize != 0) {
- const DexMethodAnnotationsItem* methods =
- dexGetMethodAnnotations(state->pDexFile, dir);
- const DexMethodId* method =
- dexGetMethodId(state->pDexFile, methods[0].methodIdx);
- return method->classIdx;
- }
-
- if (dir->parametersSize != 0) {
- const DexParameterAnnotationsItem* parameters =
- dexGetParameterAnnotations(state->pDexFile, dir);
- const DexMethodId* method =
- dexGetMethodId(state->pDexFile, parameters[0].methodIdx);
- return method->classIdx;
- }
-
- return kDexNoIndex;
-}
-
-/* Perform cross-item verification of annotations_directory_item. */
-static void* crossVerifyAnnotationsDirectoryItem(const CheckState* state,
- void* ptr) {
- const DexAnnotationsDirectoryItem* item = (const DexAnnotationsDirectoryItem*) ptr;
- u4 definingClass = findFirstAnnotationsDirectoryDefiner(state, item);
-
- if (!dexDataMapVerify0Ok(state->pDataMap,
- item->classAnnotationsOff, kDexTypeAnnotationSetItem)) {
- return NULL;
- }
-
- const u1* addr = (const u1*) (item + 1);
-
- if (item->fieldsSize != 0) {
- addr = crossVerifyFieldAnnotations(state, item->fieldsSize, addr,
- definingClass);
- if (addr == NULL) {
- return NULL;
- }
- }
-
- if (item->methodsSize != 0) {
- addr = crossVerifyMethodAnnotations(state, item->methodsSize, addr,
- definingClass);
- if (addr == NULL) {
- return NULL;
- }
- }
-
- if (item->parametersSize != 0) {
- addr = crossVerifyParameterAnnotations(state, item->parametersSize,
- addr, definingClass);
- if (addr == NULL) {
- return NULL;
- }
- }
-
- return (void*) addr;
-}
-
-/* Perform byte-swapping and intra-item verification on type_list. */
-static void* swapTypeList(const CheckState* state, void* ptr)
-{
- DexTypeList* pTypeList = (DexTypeList*) ptr;
- DexTypeItem* pType;
- u4 count;
-
- CHECK_PTR_RANGE(pTypeList, pTypeList + 1);
- SWAP_FIELD4(pTypeList->size);
- count = pTypeList->size;
- pType = pTypeList->list;
-
- const u4 sizeOfItem = (u4) sizeof(DexTypeItem);
- CHECK_LIST_SIZE(pType, count, sizeOfItem);
-
- while (count--) {
- SWAP_INDEX2(pType->typeIdx, state->pHeader->typeIdsSize);
- pType++;
- }
-
- return pType;
-}
-
-/* Perform byte-swapping and intra-item verification on
- * annotation_set_ref_list. */
-static void* swapAnnotationSetRefList(const CheckState* state, void* ptr) {
- DexAnnotationSetRefList* list = (DexAnnotationSetRefList*) ptr;
- DexAnnotationSetRefItem* item;
- u4 count;
-
- CHECK_PTR_RANGE(list, list + 1);
- SWAP_FIELD4(list->size);
- count = list->size;
- item = list->list;
-
- const u4 sizeOfItem = (u4) sizeof(DexAnnotationSetRefItem);
- CHECK_LIST_SIZE(item, count, sizeOfItem);
-
- while (count--) {
- SWAP_OFFSET4(item->annotationsOff);
- item++;
- }
-
- return item;
-}
-
-/* Perform cross-item verification of annotation_set_ref_list. */
-static void* crossVerifyAnnotationSetRefList(const CheckState* state,
- void* ptr) {
- const DexAnnotationSetRefList* list = (const DexAnnotationSetRefList*) ptr;
- const DexAnnotationSetRefItem* item = list->list;
- int count = list->size;
-
- while (count--) {
- if (!dexDataMapVerify0Ok(state->pDataMap,
- item->annotationsOff, kDexTypeAnnotationSetItem)) {
- return NULL;
- }
- item++;
- }
-
- return (void*) item;
-}
-
-/* Perform byte-swapping and intra-item verification on
- * annotation_set_item. */
-static void* swapAnnotationSetItem(const CheckState* state, void* ptr) {
- DexAnnotationSetItem* set = (DexAnnotationSetItem*) ptr;
- u4* item;
- u4 count;
-
- CHECK_PTR_RANGE(set, set + 1);
- SWAP_FIELD4(set->size);
- count = set->size;
- item = set->entries;
-
- const u4 sizeOfItem = (u4) sizeof(u4);
- CHECK_LIST_SIZE(item, count, sizeOfItem);
-
- while (count--) {
- SWAP_OFFSET4(*item);
- item++;
- }
-
- return item;
-}
-
-/* Helper for crossVerifyAnnotationSetItem(), which extracts the type_idx
- * out of an annotation_item. */
-static u4 annotationItemTypeIdx(const DexAnnotationItem* item) {
- const u1* data = item->annotation;
- return readUnsignedLeb128(&data);
-}
-
-/* Perform cross-item verification of annotation_set_item. */
-static void* crossVerifyAnnotationSetItem(const CheckState* state, void* ptr) {
- const DexAnnotationSetItem* set = (const DexAnnotationSetItem*) ptr;
- int count = set->size;
- u4 lastIdx = 0;
- bool first = true;
- int i;
-
- for (i = 0; i < count; i++) {
- if (!dexDataMapVerify0Ok(state->pDataMap,
- dexGetAnnotationOff(set, i), kDexTypeAnnotationItem)) {
- return NULL;
- }
-
- const DexAnnotationItem* annotation =
- dexGetAnnotationItem(state->pDexFile, set, i);
- u4 idx = annotationItemTypeIdx(annotation);
-
- if (first) {
- first = false;
- } else if (lastIdx >= idx) {
- ALOGE("Out-of-order entry types: %#x then %#x",
- lastIdx, idx);
- return NULL;
- }
-
- lastIdx = idx;
- }
-
- return (void*) (set->entries + count);
-}
-
-/* Helper for verifyClassDataItem(), which checks a list of fields. */
-static bool verifyFields(const CheckState* state, u4 size,
- DexField* fields, bool expectStatic) {
- u4 i;
-
- for (i = 0; i < size; i++) {
- DexField* field = &fields[i];
- u4 accessFlags = field->accessFlags;
- bool isStatic = (accessFlags & ACC_STATIC) != 0;
-
- CHECK_INDEX(field->fieldIdx, state->pHeader->fieldIdsSize);
-
- if (isStatic != expectStatic) {
- ALOGE("Field in wrong list @ %d", i);
- return false;
- }
-
- if ((accessFlags & ~ACC_FIELD_MASK) != 0) {
- // The VM specification says that unknown flags should be ignored.
- ALOGV("Bogus field access flags %x @ %d", accessFlags, i);
- field->accessFlags &= ACC_FIELD_MASK;
- }
- }
-
- return true;
-}
-
-/* Helper for verifyClassDataItem(), which checks a list of methods. */
-static bool verifyMethods(const CheckState* state, u4 size,
- DexMethod* methods, bool expectDirect) {
- u4 i;
-
- for (i = 0; i < size; i++) {
- DexMethod* method = &methods[i];
-
- CHECK_INDEX(method->methodIdx, state->pHeader->methodIdsSize);
-
- u4 accessFlags = method->accessFlags;
- bool isDirect =
- (accessFlags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0;
- bool expectCode = (accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0;
- bool isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0;
- bool allowSynchronized = (accessFlags & ACC_NATIVE) != 0;
-
- if (isDirect != expectDirect) {
- ALOGE("Method in wrong list @ %d", i);
- return false;
- }
-
- if (isSynchronized && !allowSynchronized) {
- ALOGE("Bogus method access flags (synchronization) %x @ %d", accessFlags, i);
- return false;
- }
-
- if ((accessFlags & ~ACC_METHOD_MASK) != 0) {
- // The VM specification says that unknown flags should be ignored.
- ALOGV("Bogus method access flags %x @ %d", accessFlags, i);
- method->accessFlags &= ACC_METHOD_MASK;
- }
-
- if (expectCode) {
- if (method->codeOff == 0) {
- ALOGE("Unexpected zero code_off for access_flags %x",
- accessFlags);
- return false;
- }
- } else if (method->codeOff != 0) {
- ALOGE("Unexpected non-zero code_off %#x for access_flags %x",
- method->codeOff, accessFlags);
- return false;
- }
- }
-
- return true;
-}
-
-/* Helper for verifyClassDataItem(), which does most of the work. */
-static bool verifyClassDataItem0(const CheckState* state,
- DexClassData* classData) {
- bool okay;
-
- okay = verifyFields(state, classData->header.staticFieldsSize,
- classData->staticFields, true);
-
- if (!okay) {
- ALOGE("Trouble with static fields");
- return false;
- }
-
- verifyFields(state, classData->header.instanceFieldsSize,
- classData->instanceFields, false);
-
- if (!okay) {
- ALOGE("Trouble with instance fields");
- return false;
- }
-
- okay = verifyMethods(state, classData->header.directMethodsSize,
- classData->directMethods, true);
-
- if (!okay) {
- ALOGE("Trouble with direct methods");
- return false;
- }
-
- okay = verifyMethods(state, classData->header.virtualMethodsSize,
- classData->virtualMethods, false);
-
- if (!okay) {
- ALOGE("Trouble with virtual methods");
- return false;
- }
-
- return true;
-}
-
-/* Perform intra-item verification on class_data_item. */
-static void* intraVerifyClassDataItem(const CheckState* state, void* ptr) {
- const u1* data = (const u1*) ptr;
- DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd);
-
- if (classData == NULL) {
- ALOGE("Unable to parse class_data_item");
- return NULL;
- }
-
- bool okay = verifyClassDataItem0(state, classData);
-
- free(classData);
-
- if (!okay) {
- return NULL;
- }
-
- return (void*) data;
-}
-
-/* Helper for crossVerifyClassDefItem() and
- * crossVerifyClassDataItem(), which finds the type_idx of the definer
- * of the first item in the data. */
-static u4 findFirstClassDataDefiner(const CheckState* state,
- DexClassData* classData) {
- if (classData->header.staticFieldsSize != 0) {
- u4 fieldIdx = classData->staticFields[0].fieldIdx;
- const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx);
- return field->classIdx;
- }
-
- if (classData->header.instanceFieldsSize != 0) {
- u4 fieldIdx = classData->instanceFields[0].fieldIdx;
- const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx);
- return field->classIdx;
- }
-
- if (classData->header.directMethodsSize != 0) {
- u4 methodIdx = classData->directMethods[0].methodIdx;
- const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx);
- return meth->classIdx;
- }
-
- if (classData->header.virtualMethodsSize != 0) {
- u4 methodIdx = classData->virtualMethods[0].methodIdx;
- const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx);
- return meth->classIdx;
- }
-
- return kDexNoIndex;
-}
-
-/* Perform cross-item verification of class_data_item. */
-static void* crossVerifyClassDataItem(const CheckState* state, void* ptr) {
- const u1* data = (const u1*) ptr;
- DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd);
- u4 definingClass = findFirstClassDataDefiner(state, classData);
- bool okay = true;
- u4 i;
-
- for (i = classData->header.staticFieldsSize; okay && (i > 0); /*i*/) {
- i--;
- const DexField* field = &classData->staticFields[i];
- okay = verifyFieldDefiner(state, definingClass, field->fieldIdx);
- }
-
- for (i = classData->header.instanceFieldsSize; okay && (i > 0); /*i*/) {
- i--;
- const DexField* field = &classData->instanceFields[i];
- okay = verifyFieldDefiner(state, definingClass, field->fieldIdx);
- }
-
- for (i = classData->header.directMethodsSize; okay && (i > 0); /*i*/) {
- i--;
- const DexMethod* meth = &classData->directMethods[i];
- okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff,
- kDexTypeCodeItem)
- && verifyMethodDefiner(state, definingClass, meth->methodIdx);
- }
-
- for (i = classData->header.virtualMethodsSize; okay && (i > 0); /*i*/) {
- i--;
- const DexMethod* meth = &classData->virtualMethods[i];
- okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff,
- kDexTypeCodeItem)
- && verifyMethodDefiner(state, definingClass, meth->methodIdx);
- }
-
- free(classData);
-
- if (!okay) {
- return NULL;
- }
-
- return (void*) data;
-}
-
-/* Helper for swapCodeItem(), which fills an array with all the valid
- * handlerOff values for catch handlers and also verifies the handler
- * contents. */
-static u4 setHandlerOffsAndVerify(const CheckState* state,
- DexCode* code, u4 firstOffset, u4 handlersSize, u4* handlerOffs) {
- const u1* fileEnd = state->fileEnd;
- const u1* handlersBase = dexGetCatchHandlerData(code);
- u4 offset = firstOffset;
- bool okay = true;
- u4 i;
-
- for (i = 0; i < handlersSize; i++) {
- const u1* ptr = handlersBase + offset;
- int size = readAndVerifySignedLeb128(&ptr, fileEnd, &okay);
- bool catchAll;
-
- if (!okay) {
- ALOGE("Bogus size");
- return 0;
- }
-
- if ((size < -65536) || (size > 65536)) {
- ALOGE("Invalid size: %d", size);
- return 0;
- }
-
- if (size <= 0) {
- catchAll = true;
- size = -size;
- } else {
- catchAll = false;
- }
-
- handlerOffs[i] = offset;
-
- while (size-- > 0) {
- u4 typeIdx =
- readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus type_idx");
- return 0;
- }
-
- CHECK_INDEX(typeIdx, state->pHeader->typeIdsSize);
-
- u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus addr");
- return 0;
- }
-
- if (addr >= code->insnsSize) {
- ALOGE("Invalid addr: %#x", addr);
- return 0;
- }
- }
-
- if (catchAll) {
- u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus catch_all_addr");
- return 0;
- }
-
- if (addr >= code->insnsSize) {
- ALOGE("Invalid catch_all_addr: %#x", addr);
- return 0;
- }
- }
-
- offset = ptr - handlersBase;
- }
-
- return offset;
-}
-
-/* Helper for swapCodeItem(), which does all the try-catch related
- * swapping and verification. */
-static void* swapTriesAndCatches(const CheckState* state, DexCode* code) {
- const u1* encodedHandlers = dexGetCatchHandlerData(code);
- const u1* encodedPtr = encodedHandlers;
- bool okay = true;
- u4 handlersSize =
- readAndVerifyUnsignedLeb128(&encodedPtr, state->fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus handlers_size");
- return NULL;
- }
-
- if ((handlersSize == 0) || (handlersSize >= 65536)) {
- ALOGE("Invalid handlers_size: %d", handlersSize);
- return NULL;
- }
-
- u4 handlerOffs[handlersSize]; // list of valid handlerOff values
- u4 endOffset = setHandlerOffsAndVerify(state, code,
- encodedPtr - encodedHandlers,
- handlersSize, handlerOffs);
-
- if (endOffset == 0) {
- return NULL;
- }
-
- DexTry* tries = (DexTry*) dexGetTries(code);
- u4 count = code->triesSize;
- u4 lastEnd = 0;
-
- const u4 sizeOfItem = (u4) sizeof(DexTry);
- CHECK_LIST_SIZE(tries, count, sizeOfItem);
-
- while (count--) {
- u4 i;
-
- SWAP_FIELD4(tries->startAddr);
- SWAP_FIELD2(tries->insnCount);
- SWAP_FIELD2(tries->handlerOff);
-
- if (tries->startAddr < lastEnd) {
- ALOGE("Out-of-order try");
- return NULL;
- }
-
- if (tries->startAddr >= code->insnsSize) {
- ALOGE("Invalid start_addr: %#x", tries->startAddr);
- return NULL;
- }
-
- for (i = 0; i < handlersSize; i++) {
- if (tries->handlerOff == handlerOffs[i]) {
- break;
- }
- }
-
- if (i == handlersSize) {
- ALOGE("Bogus handler offset: %#x", tries->handlerOff);
- return NULL;
- }
-
- lastEnd = tries->startAddr + tries->insnCount;
-
- if (lastEnd > code->insnsSize) {
- ALOGE("Invalid insn_count: %#x (end addr %#x)",
- tries->insnCount, lastEnd);
- return NULL;
- }
-
- tries++;
- }
-
- return (u1*) encodedHandlers + endOffset;
-}
-
-/* Perform byte-swapping and intra-item verification on code_item. */
-static void* swapCodeItem(const CheckState* state, void* ptr) {
- DexCode* item = (DexCode*) ptr;
- u2* insns;
- u4 count;
-
- CHECK_PTR_RANGE(item, item + 1);
- SWAP_FIELD2(item->registersSize);
- SWAP_FIELD2(item->insSize);
- SWAP_FIELD2(item->outsSize);
- SWAP_FIELD2(item->triesSize);
- SWAP_OFFSET4(item->debugInfoOff);
- SWAP_FIELD4(item->insnsSize);
-
- if (item->insSize > item->registersSize) {
- ALOGE("insSize (%u) > registersSize (%u)", item->insSize,
- item->registersSize);
- return NULL;
- }
-
- if ((item->outsSize > 5) && (item->outsSize > item->registersSize)) {
- /*
- * It's okay for outsSize to be up to five, even if registersSize
- * is smaller, since the short forms of method invocation allow
- * repetition of a register multiple times within a single parameter
- * list. Longer parameter lists, though, need to be represented
- * in-order in the register file.
- */
- ALOGE("outsSize (%u) > registersSize (%u)", item->outsSize,
- item->registersSize);
- return NULL;
- }
-
- count = item->insnsSize;
- insns = item->insns;
-
- const u4 sizeOfItem = (u4) sizeof(u2);
- CHECK_LIST_SIZE(insns, count, sizeOfItem);
-
- while (count--) {
- *insns = SWAP2(*insns);
- insns++;
- }
-
- if (item->triesSize == 0) {
- ptr = insns;
- } else {
- if ((((uintptr_t) insns) & 3) != 0) {
- // Four-byte alignment for the tries. Verify the spacer is a 0.
- if (*insns != 0) {
- ALOGE("Non-zero padding: %#x", (u4) *insns);
- return NULL;
- }
- }
-
- ptr = swapTriesAndCatches(state, item);
- }
-
- return ptr;
-}
-
-/* Perform intra-item verification on string_data_item. */
-static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) {
- const u1* fileEnd = state->fileEnd;
- const u1* data = (const u1*) ptr;
- bool okay = true;
- u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- u4 i;
-
- if (!okay) {
- ALOGE("Bogus utf16_size");
- return NULL;
- }
-
- for (i = 0; i < utf16Size; i++) {
- if (data >= fileEnd) {
- ALOGE("String data would go beyond end-of-file");
- return NULL;
- }
-
- u1 byte1 = *(data++);
-
- // Switch on the high four bits.
- switch (byte1 >> 4) {
- case 0x00: {
- // Special case of bit pattern 0xxx.
- if (byte1 == 0) {
- ALOGE("String shorter than indicated utf16_size %#x",
- utf16Size);
- return NULL;
- }
- break;
- }
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07: {
- // Bit pattern 0xxx. No need for any extra bytes or checks.
- break;
- }
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0f: {
- /*
- * Bit pattern 10xx or 1111, which are illegal start bytes.
- * Note: 1111 is valid for normal UTF-8, but not the
- * modified UTF-8 used here.
- */
- ALOGE("Illegal start byte %#x", byte1);
- return NULL;
- }
- case 0x0e: {
- // Bit pattern 1110, so there are two additional bytes.
- u1 byte2 = *(data++);
- if ((byte2 & 0xc0) != 0x80) {
- ALOGE("Illegal continuation byte %#x", byte2);
- return NULL;
- }
- u1 byte3 = *(data++);
- if ((byte3 & 0xc0) != 0x80) {
- ALOGE("Illegal continuation byte %#x", byte3);
- return NULL;
- }
- u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6)
- | (byte3 & 0x3f);
- if (value < 0x800) {
- ALOGE("Illegal representation for value %x", value);
- return NULL;
- }
- break;
- }
- case 0x0c:
- case 0x0d: {
- // Bit pattern 110x, so there is one additional byte.
- u1 byte2 = *(data++);
- if ((byte2 & 0xc0) != 0x80) {
- ALOGE("Illegal continuation byte %#x", byte2);
- return NULL;
- }
- u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f);
- if ((value != 0) && (value < 0x80)) {
- ALOGE("Illegal representation for value %x", value);
- return NULL;
- }
- break;
- }
- }
- }
-
- if (*(data++) != '\0') {
- ALOGE("String longer than indicated utf16_size %#x", utf16Size);
- return NULL;
- }
-
- return (void*) data;
-}
-
-/* Perform intra-item verification on debug_info_item. */
-static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) {
- const u1* fileEnd = state->fileEnd;
- const u1* data = (const u1*) ptr;
- bool okay = true;
- u4 i;
-
- readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus line_start");
- return NULL;
- }
-
- u4 parametersSize =
- readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus parameters_size");
- return NULL;
- }
-
- if (parametersSize > 65536) {
- ALOGE("Invalid parameters_size: %#x", parametersSize);
- return NULL;
- }
-
- for (i = 0; i < parametersSize; i++) {
- u4 parameterName =
- readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus parameter_name");
- return NULL;
- }
-
- if (parameterName != 0) {
- parameterName--;
- CHECK_INDEX(parameterName, state->pHeader->stringIdsSize);
- }
- }
-
- bool done = false;
- while (!done) {
- u1 opcode = *(data++);
-
- switch (opcode) {
- case DBG_END_SEQUENCE: {
- done = true;
- break;
- }
- case DBG_ADVANCE_PC: {
- readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- break;
- }
- case DBG_ADVANCE_LINE: {
- readAndVerifySignedLeb128(&data, fileEnd, &okay);
- break;
- }
- case DBG_START_LOCAL: {
- u4 idx;
- u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (regNum >= 65536) {
- okay = false;
- break;
- }
- idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (idx != 0) {
- idx--;
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
- }
- idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (idx != 0) {
- idx--;
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
- }
- break;
- }
- case DBG_END_LOCAL:
- case DBG_RESTART_LOCAL: {
- u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (regNum >= 65536) {
- okay = false;
- break;
- }
- break;
- }
- case DBG_START_LOCAL_EXTENDED: {
- u4 idx;
- u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (regNum >= 65536) {
- okay = false;
- break;
- }
- idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (idx != 0) {
- idx--;
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
- }
- idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (idx != 0) {
- idx--;
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
- }
- idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (idx != 0) {
- idx--;
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
- }
- break;
- }
- case DBG_SET_FILE: {
- u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- if (!okay) break;
- if (idx != 0) {
- idx--;
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
- }
- break;
- }
- default: {
- // No arguments to parse for anything else.
- }
- }
-
- if (!okay) {
- ALOGE("Bogus syntax for opcode %02x", opcode);
- return NULL;
- }
- }
-
- return (void*) data;
-}
-
-/* defined below */
-static const u1* verifyEncodedValue(const CheckState* state, const u1* data,
- bool crossVerify);
-static const u1* verifyEncodedAnnotation(const CheckState* state,
- const u1* data, bool crossVerify);
-
-/* Helper for verifyEncodedValue(), which reads a 1- to 4- byte unsigned
- * little endian value. */
-static u4 readUnsignedLittleEndian(const CheckState* state, const u1** pData,
- u4 size) {
- const u1* data = *pData;
- u4 result = 0;
- u4 i;
-
- CHECK_PTR_RANGE(data, data + size);
-
- for (i = 0; i < size; i++) {
- result |= ((u4) *(data++)) << (i * 8);
- }
-
- *pData = data;
- return result;
-}
-
-/* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
- * verifies an encoded_array. */
-static const u1* verifyEncodedArray(const CheckState* state,
- const u1* data, bool crossVerify) {
- bool okay = true;
- u4 size = readAndVerifyUnsignedLeb128(&data, state->fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus encoded_array size");
- return NULL;
- }
-
- while (size--) {
- data = verifyEncodedValue(state, data, crossVerify);
- if (data == NULL) {
- ALOGE("Bogus encoded_array value");
- return NULL;
- }
- }
-
- return data;
-}
-
-static u4 numberOfMethodHandles(const CheckState* state) {
- if (state->pMethodHandleItems != nullptr) {
- return state->pMethodHandleItems->size;
- }
- return 0;
-}
-
-/* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
- * verifies an encoded_value. */
-static const u1* verifyEncodedValue(const CheckState* state,
- const u1* data, bool crossVerify) {
- CHECK_PTR_RANGE(data, data + 1);
-
- u1 headerByte = *(data++);
- u4 valueType = headerByte & kDexAnnotationValueTypeMask;
- u4 valueArg = headerByte >> kDexAnnotationValueArgShift;
-
- switch (valueType) {
- case kDexAnnotationByte: {
- if (valueArg != 0) {
- ALOGE("Bogus byte size %#x", valueArg);
- return NULL;
- }
- data++;
- break;
- }
- case kDexAnnotationShort:
- case kDexAnnotationChar: {
- if (valueArg > 1) {
- ALOGE("Bogus char/short size %#x", valueArg);
- return NULL;
- }
- data += valueArg + 1;
- break;
- }
- case kDexAnnotationInt:
- case kDexAnnotationFloat: {
- if (valueArg > 3) {
- ALOGE("Bogus int/float size %#x", valueArg);
- return NULL;
- }
- data += valueArg + 1;
- break;
- }
- case kDexAnnotationLong:
- case kDexAnnotationDouble: {
- data += valueArg + 1;
- break;
- }
- case kDexAnnotationMethodType: {
- if (valueArg > 3) {
- ALOGE("Bogus method type size %#x", valueArg);
- return NULL;
- }
- u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
- CHECK_INDEX(idx, state->pHeader->protoIdsSize);
- break;
- }
- case kDexAnnotationMethodHandle: {
- if (valueArg > 3) {
- ALOGE("Bogus method type size %#x", valueArg);
- return NULL;
- }
- u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
- CHECK_INDEX(idx, numberOfMethodHandles(state));
- break;
- }
- case kDexAnnotationString: {
- if (valueArg > 3) {
- ALOGE("Bogus string size %#x", valueArg);
- return NULL;
- }
- u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
- break;
- }
- case kDexAnnotationType: {
- if (valueArg > 3) {
- ALOGE("Bogus type size %#x", valueArg);
- return NULL;
- }
- u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
- CHECK_INDEX(idx, state->pHeader->typeIdsSize);
- break;
- }
- case kDexAnnotationField:
- case kDexAnnotationEnum: {
- if (valueArg > 3) {
- ALOGE("Bogus field/enum size %#x", valueArg);
- return NULL;
- }
- u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
- CHECK_INDEX(idx, state->pHeader->fieldIdsSize);
- break;
- }
- case kDexAnnotationMethod: {
- if (valueArg > 3) {
- ALOGE("Bogus method size %#x", valueArg);
- return NULL;
- }
- u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
- CHECK_INDEX(idx, state->pHeader->methodIdsSize);
- break;
- }
- case kDexAnnotationArray: {
- if (valueArg != 0) {
- ALOGE("Bogus array value_arg %#x", valueArg);
- return NULL;
- }
- data = verifyEncodedArray(state, data, crossVerify);
- break;
- }
- case kDexAnnotationAnnotation: {
- if (valueArg != 0) {
- ALOGE("Bogus annotation value_arg %#x", valueArg);
- return NULL;
- }
- data = verifyEncodedAnnotation(state, data, crossVerify);
- break;
- }
- case kDexAnnotationNull: {
- if (valueArg != 0) {
- ALOGE("Bogus null value_arg %#x", valueArg);
- return NULL;
- }
- // Nothing else to do for this type.
- break;
- }
- case kDexAnnotationBoolean: {
- if (valueArg > 1) {
- ALOGE("Bogus boolean value_arg %#x", valueArg);
- return NULL;
- }
- // Nothing else to do for this type.
- break;
- }
- default: {
- ALOGE("Bogus value_type %#x", valueType);
- return NULL;
- }
- }
-
- return data;
-}
-
-/* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
- * verifies an encoded_annotation. */
-static const u1* verifyEncodedAnnotation(const CheckState* state,
- const u1* data, bool crossVerify) {
- const u1* fileEnd = state->fileEnd;
- bool okay = true;
- u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus encoded_annotation type_idx");
- return NULL;
- }
-
- CHECK_INDEX(idx, state->pHeader->typeIdsSize);
-
- if (crossVerify) {
- const char* descriptor = dexStringByTypeIdx(state->pDexFile, idx);
- if (!dexIsClassDescriptor(descriptor)) {
- ALOGE("Bogus annotation type: '%s'", descriptor);
- return NULL;
- }
- }
-
- u4 size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
- u4 lastIdx = 0;
- bool first = true;
-
- if (!okay) {
- ALOGE("Bogus encoded_annotation size");
- return NULL;
- }
-
- while (size--) {
- idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
-
- if (!okay) {
- ALOGE("Bogus encoded_annotation name_idx");
- return NULL;
- }
-
- CHECK_INDEX(idx, state->pHeader->stringIdsSize);
-
- if (crossVerify) {
- const char* name = dexStringById(state->pDexFile, idx);
- if (!dexIsValidMemberName(name)) {
- ALOGE("Bogus annotation member name: '%s'", name);
- return NULL;
- }
- }
-
- if (first) {
- first = false;
- } else if (lastIdx >= idx) {
- ALOGE("Out-of-order encoded_annotation name_idx: %#x then %#x",
- lastIdx, idx);
- return NULL;
- }
-
- data = verifyEncodedValue(state, data, crossVerify);
- lastIdx = idx;
-
- if (data == NULL) {
- return NULL;
- }
- }
-
- return data;
-}
-
-/* Perform intra-item verification on encoded_array_item. */
-static void* intraVerifyEncodedArrayItem(const CheckState* state, void* ptr) {
- return (void*) verifyEncodedArray(state, (const u1*) ptr, false);
-}
-
-/* Perform intra-item verification on annotation_item. */
-static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) {
- const u1* data = (const u1*) ptr;
-
- CHECK_PTR_RANGE(data, data + 1);
-
- switch (*(data++)) {
- case kDexVisibilityBuild:
- case kDexVisibilityRuntime:
- case kDexVisibilitySystem: {
- break;
- }
- default: {
- ALOGE("Bogus annotation visibility: %#x", *data);
- return NULL;
- }
- }
-
- return (void*) verifyEncodedAnnotation(state, data, false);
-}
-
-/*
- * Function to visit an individual top-level item type.
- */
-typedef void* ItemVisitorFunction(const CheckState* state, void* ptr);
-
-/*
- * Iterate over all the items in a section, optionally updating the
- * data map (done if mapType is passed as non-negative). The section
- * must consist of concatenated items of the same type.
- */
-static bool iterateSectionWithOptionalUpdate(CheckState* state,
- u4 offset, u4 count, ItemVisitorFunction* func, u4 alignment,
- u4* nextOffset, int mapType) {
- u4 alignmentMask = alignment - 1;
- u4 i;
-
- state->previousItem = NULL;
-
- for (i = 0; i < count; i++) {
- u4 newOffset = (offset + alignmentMask) & ~alignmentMask;
- u1* ptr = (u1*) filePointer(state, newOffset);
-
- if (offset < newOffset) {
- ptr = (u1*) filePointer(state, offset);
- if (offset < newOffset) {
- CHECK_OFFSET_RANGE(offset, newOffset);
- while (offset < newOffset) {
- if (*ptr != '\0') {
- ALOGE("Non-zero padding 0x%02x @ %x", *ptr, offset);
- return false;
- }
- ptr++;
- offset++;
- }
- }
- }
-
- u1* newPtr = (u1*) func(state, ptr);
- newOffset = fileOffset(state, newPtr);
-
- if (newPtr == NULL) {
- ALOGE("Trouble with item %d @ offset %#x", i, offset);
- return false;
- }
-
- if (newOffset > state->fileLen) {
- ALOGE("Item %d @ offset %#x ends out of bounds", i, offset);
- return false;
- }
-
- if (mapType >= 0) {
- dexDataMapAdd(state->pDataMap, offset, mapType);
- }
-
- state->previousItem = ptr;
- offset = newOffset;
- }
-
- if (nextOffset != NULL) {
- *nextOffset = offset;
- }
-
- return true;
-}
-
-/*
- * Iterate over all the items in a section. The section must consist of
- * concatenated items of the same type. This variant will not update the data
- * map.
- */
-static bool iterateSection(CheckState* state, u4 offset, u4 count,
- ItemVisitorFunction* func, u4 alignment, u4* nextOffset) {
- return iterateSectionWithOptionalUpdate(state, offset, count, func,
- alignment, nextOffset, -1);
-}
-
-/*
- * Like iterateSection(), but also check that the offset and count match
- * a given pair of expected values.
- */
-static bool checkBoundsAndIterateSection(CheckState* state,
- u4 offset, u4 count, u4 expectedOffset, u4 expectedCount,
- ItemVisitorFunction* func, u4 alignment, u4* nextOffset) {
- if (offset != expectedOffset) {
- ALOGE("Bogus offset for section: got %#x; expected %#x",
- offset, expectedOffset);
- return false;
- }
-
- if (count != expectedCount) {
- ALOGE("Bogus size for section: got %#x; expected %#x",
- count, expectedCount);
- return false;
- }
-
- return iterateSection(state, offset, count, func, alignment, nextOffset);
-}
-
-/*
- * Like iterateSection(), but also update the data section map and
- * check that all the items fall within the data section.
- */
-static bool iterateDataSection(CheckState* state, u4 offset, u4 count,
- ItemVisitorFunction* func, u4 alignment, u4* nextOffset, int mapType) {
- u4 dataStart = state->pHeader->dataOff;
- u4 dataEnd = dataStart + state->pHeader->dataSize;
-
- assert(nextOffset != NULL);
-
- if ((offset < dataStart) || (offset >= dataEnd)) {
- ALOGE("Bogus offset for data subsection: %#x", offset);
- return false;
- }
-
- if (!iterateSectionWithOptionalUpdate(state, offset, count, func,
- alignment, nextOffset, mapType)) {
- return false;
- }
-
- if (*nextOffset > dataEnd) {
- ALOGE("Out-of-bounds end of data subsection: %#x", *nextOffset);
- return false;
- }
-
- return true;
-}
-
-/*
- * Byte-swap all items in the given map except the header and the map
- * itself, both of which should have already gotten swapped. This also
- * does all possible intra-item verification, that is, verification
- * that doesn't need to assume the sanctity of the contents of *other*
- * items. The intra-item limitation is because at the time an item is
- * asked to verify itself, it can't assume that the items it refers to
- * have been byte-swapped and verified.
- */
-static bool swapEverythingButHeaderAndMap(CheckState* state,
- DexMapList* pMap) {
- const DexMapItem* item = pMap->list;
- u4 lastOffset = 0;
- u4 count = pMap->size;
- bool okay = true;
-
- while (okay && count--) {
- u4 sectionOffset = item->offset;
- u4 sectionCount = item->size;
- u2 type = item->type;
-
- if (lastOffset < sectionOffset) {
- CHECK_OFFSET_RANGE(lastOffset, sectionOffset);
- const u1* ptr = (const u1*) filePointer(state, lastOffset);
- while (lastOffset < sectionOffset) {
- if (*ptr != '\0') {
- ALOGE("Non-zero padding 0x%02x before section start @ %x",
- *ptr, lastOffset);
- okay = false;
- break;
- }
- ptr++;
- lastOffset++;
- }
- } else if (lastOffset > sectionOffset) {
- ALOGE("Section overlap or out-of-order map: %x, %x",
- lastOffset, sectionOffset);
- okay = false;
- }
-
- if (!okay) {
- break;
- }
-
- switch (type) {
- case kDexTypeHeaderItem: {
- /*
- * The header got swapped very early on, but do some
- * additional sanity checking here.
- */
- okay = checkHeaderSection(state, sectionOffset, sectionCount,
- &lastOffset);
- break;
- }
- case kDexTypeStringIdItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, state->pHeader->stringIdsOff,
- state->pHeader->stringIdsSize, swapStringIdItem,
- sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeTypeIdItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, state->pHeader->typeIdsOff,
- state->pHeader->typeIdsSize, swapTypeIdItem,
- sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeProtoIdItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, state->pHeader->protoIdsOff,
- state->pHeader->protoIdsSize, swapProtoIdItem,
- sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeFieldIdItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, state->pHeader->fieldIdsOff,
- state->pHeader->fieldIdsSize, swapFieldIdItem,
- sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeMethodIdItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, state->pHeader->methodIdsOff,
- state->pHeader->methodIdsSize, swapMethodIdItem,
- sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeClassDefItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, state->pHeader->classDefsOff,
- state->pHeader->classDefsSize, swapClassDefItem,
- sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeCallSiteIdItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, sectionOffset, sectionCount,
- swapCallSiteId, sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeMethodHandleItem: {
- okay = checkBoundsAndIterateSection(state, sectionOffset,
- sectionCount, sectionOffset, sectionCount,
- swapMethodHandleItem, sizeof(u4), &lastOffset);
- break;
- }
- case kDexTypeMapList: {
- /*
- * The map section was swapped early on, but do some
- * additional sanity checking here.
- */
- okay = checkMapSection(state, sectionOffset, sectionCount,
- &lastOffset);
- break;
- }
- case kDexTypeTypeList: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- swapTypeList, sizeof(u4), &lastOffset, type);
- break;
- }
- case kDexTypeAnnotationSetRefList: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- swapAnnotationSetRefList, sizeof(u4), &lastOffset,
- type);
- break;
- }
- case kDexTypeAnnotationSetItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- swapAnnotationSetItem, sizeof(u4), &lastOffset, type);
- break;
- }
- case kDexTypeClassDataItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- intraVerifyClassDataItem, sizeof(u1), &lastOffset,
- type);
- break;
- }
- case kDexTypeCodeItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- swapCodeItem, sizeof(u4), &lastOffset, type);
- break;
- }
- case kDexTypeStringDataItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- intraVerifyStringDataItem, sizeof(u1), &lastOffset,
- type);
- break;
- }
- case kDexTypeDebugInfoItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- intraVerifyDebugInfoItem, sizeof(u1), &lastOffset,
- type);
- break;
- }
- case kDexTypeAnnotationItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- intraVerifyAnnotationItem, sizeof(u1), &lastOffset,
- type);
- break;
- }
- case kDexTypeEncodedArrayItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- intraVerifyEncodedArrayItem, sizeof(u1), &lastOffset,
- type);
- break;
- }
- case kDexTypeAnnotationsDirectoryItem: {
- okay = iterateDataSection(state, sectionOffset, sectionCount,
- swapAnnotationsDirectoryItem, sizeof(u4), &lastOffset,
- type);
- break;
- }
- default: {
- ALOGE("Unknown map item type %04x", type);
- return false;
- }
- }
-
- if (!okay) {
- ALOGE("Swap of section type %04x failed", type);
- }
-
- item++;
- }
-
- return okay;
-}
-
-/*
- * Perform cross-item verification on everything that needs it. This
- * pass is only called after all items are byte-swapped and
- * intra-verified (checked for internal consistency).
- */
-static bool crossVerifyEverything(CheckState* state, DexMapList* pMap)
-{
- const DexMapItem* item = pMap->list;
- u4 count = pMap->size;
- bool okay = true;
-
- while (okay && count--) {
- u4 sectionOffset = item->offset;
- u4 sectionCount = item->size;
-
- switch (item->type) {
- case kDexTypeHeaderItem:
- case kDexTypeMapList:
- case kDexTypeTypeList:
- case kDexTypeCodeItem:
- case kDexTypeStringDataItem:
- case kDexTypeDebugInfoItem:
- case kDexTypeAnnotationItem:
- case kDexTypeEncodedArrayItem: {
- // There is no need for cross-item verification for these.
- break;
- }
- case kDexTypeStringIdItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyStringIdItem, sizeof(u4), NULL);
- break;
- }
- case kDexTypeTypeIdItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyTypeIdItem, sizeof(u4), NULL);
- break;
- }
- case kDexTypeProtoIdItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyProtoIdItem, sizeof(u4), NULL);
- break;
- }
- case kDexTypeFieldIdItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyFieldIdItem, sizeof(u4), NULL);
- break;
- }
- case kDexTypeMethodIdItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyMethodIdItem, sizeof(u4), NULL);
- break;
- }
- case kDexTypeClassDefItem: {
- // Allocate (on the stack) the "observed class_def" bits.
- size_t arraySize = calcDefinedClassBitsSize(state);
- u4 definedClassBits[arraySize];
- memset(definedClassBits, 0, arraySize * sizeof(u4));
- state->pDefinedClassBits = definedClassBits;
-
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyClassDefItem, sizeof(u4), NULL);
-
- state->pDefinedClassBits = NULL;
- break;
- }
- case kDexTypeCallSiteIdItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyCallSiteId, sizeof(u4), NULL);
- break;
- }
- case kDexTypeMethodHandleItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyMethodHandleItem, sizeof(u4), NULL);
- break;
- }
- case kDexTypeAnnotationSetRefList: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyAnnotationSetRefList, sizeof(u4), NULL);
- break;
- }
- case kDexTypeAnnotationSetItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyAnnotationSetItem, sizeof(u4), NULL);
- break;
- }
- case kDexTypeClassDataItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyClassDataItem, sizeof(u1), NULL);
- break;
- }
- case kDexTypeAnnotationsDirectoryItem: {
- okay = iterateSection(state, sectionOffset, sectionCount,
- crossVerifyAnnotationsDirectoryItem, sizeof(u4), NULL);
- break;
- }
- default: {
- ALOGE("Unknown map item type %04x", item->type);
- return false;
- }
- }
-
- if (!okay) {
- ALOGE("Cross-item verify of section type %04x failed",
- item->type);
- }
-
- item++;
- }
-
- return okay;
-}
-
-/* (documented in header file) */
-bool dexHasValidMagic(const DexHeader* pHeader)
-{
- const u1* magic = pHeader->magic;
- const u1* version = &magic[4];
-
- if (memcmp(magic, DEX_MAGIC, 4) != 0) {
- ALOGE("ERROR: unrecognized magic number (%02x %02x %02x %02x)",
- magic[0], magic[1], magic[2], magic[3]);
- return false;
- }
-
- if ((memcmp(version, DEX_MAGIC_VERS, 4) != 0) &&
- (memcmp(version, DEX_MAGIC_VERS_API_13, 4) != 0) &&
- (memcmp(version, DEX_MAGIC_VERS_37, 4) != 0) &&
- (memcmp(version, DEX_MAGIC_VERS_38, 4) != 0) &&
- (memcmp(version, DEX_MAGIC_VERS_39, 4) != 0)) {
- /*
- * Magic was correct, but this is an unsupported older or
- * newer format variant.
- */
- ALOGE("ERROR: unsupported dex version (%02x %02x %02x %02x)",
- version[0], version[1], version[2], version[3]);
- return false;
- }
-
- return true;
-}
-
-/*
- * Fix the byte ordering of all fields in the DEX file, and do
- * structural verification. This is only required for code that opens
- * "raw" DEX files, such as the DEX optimizer.
- *
- * Returns 0 on success, nonzero on failure.
- */
-int dexSwapAndVerify(u1* addr, size_t len)
-{
- DexHeader* pHeader;
- CheckState state;
- bool okay = true;
-
- memset(&state, 0, sizeof(state));
- ALOGV("+++ swapping and verifying");
-
- /*
- * Note: The caller must have verified that "len" is at least as
- * large as a dex file header.
- */
- pHeader = (DexHeader*) addr;
-
- if (!dexHasValidMagic(pHeader)) {
- okay = false;
- }
-
- if (okay) {
- u4 expectedLen = SWAP4(pHeader->fileSize);
- if (len != expectedLen) {
- ALOGE("ERROR: Bad length: expected %u, got %zu", expectedLen, len);
- okay = false;
- }
- }
-
- if (okay) {
- /*
- * Compute the adler32 checksum and compare it to what's stored in
- * the file. This isn't free, but chances are good that we just
- * unpacked this from a jar file and have all of the pages sitting
- * in memory, so it's pretty quick.
- *
- * This might be a big-endian system, so we need to do this before
- * we byte-swap the header.
- */
- uLong adler = adler32(0L, Z_NULL, 0);
- const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
- u4 storedFileSize = SWAP4(pHeader->fileSize);
- u4 expectedChecksum = SWAP4(pHeader->checksum);
-
- adler = adler32(adler, ((const u1*) pHeader) + nonSum,
- storedFileSize - nonSum);
-
- if (adler != expectedChecksum) {
- ALOGE("ERROR: bad checksum (%08lx, expected %08x)",
- adler, expectedChecksum);
- okay = false;
- }
- }
-
- if (okay) {
- state.fileStart = addr;
- state.fileEnd = addr + len;
- state.fileLen = len;
- state.pDexFile = NULL;
- state.pDataMap = NULL;
- state.pDefinedClassBits = NULL;
- state.previousItem = NULL;
-
- /*
- * Swap the header and check the contents.
- */
- okay = swapDexHeader(&state, pHeader);
- }
-
- if (okay) {
- state.pHeader = pHeader;
-
- if (pHeader->headerSize < sizeof(DexHeader)) {
- ALOGE("ERROR: Small header size %d, struct %d",
- pHeader->headerSize, (int) sizeof(DexHeader));
- okay = false;
- } else if (pHeader->headerSize > sizeof(DexHeader)) {
- ALOGW("WARNING: Large header size %d, struct %d",
- pHeader->headerSize, (int) sizeof(DexHeader));
- // keep going?
- }
- }
-
- if (okay) {
- /*
- * Look for the map. Swap it and then use it to find and swap
- * everything else.
- */
- if (pHeader->mapOff != 0) {
- DexFile dexFile;
- DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff);
-
- okay = okay && swapMap(&state, pDexMap);
- okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap);
-
- dexFileSetupBasicPointers(&dexFile, addr);
- state.pDexFile = &dexFile;
-
- okay = okay && crossVerifyEverything(&state, pDexMap);
- } else {
- ALOGE("ERROR: No map found; impossible to byte-swap and verify");
- okay = false;
- }
- }
-
- if (!okay) {
- ALOGE("ERROR: Byte swap + verify failed");
- }
-
- if (state.pDataMap != NULL) {
- dexDataMapFree(state.pDataMap);
- }
-
- return !okay; // 0 == success
-}
-
-/*
- * Detect the file type of the given memory buffer via magic number.
- * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing
- * but return successfully on an optimized DEX file, and report an
- * error for all other cases.
- *
- * Returns 0 on success, nonzero on failure.
- */
-int dexSwapAndVerifyIfNecessary(u1* addr, size_t len)
-{
- if (memcmp(addr, DEX_OPT_MAGIC, 4) == 0) {
- // It is an optimized dex file.
- return 0;
- }
-
- if (memcmp(addr, DEX_MAGIC, 4) == 0) {
- // It is an unoptimized dex file.
- return dexSwapAndVerify(addr, len);
- }
-
- ALOGE("ERROR: Bad magic number (0x%02x %02x %02x %02x)",
- addr[0], addr[1], addr[2], addr[3]);
-
- return 1;
-}
diff --git a/libdex/DexUtf.cpp b/libdex/DexUtf.cpp
deleted file mode 100644
index df49d1831..000000000
--- a/libdex/DexUtf.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Validate and manipulate MUTF-8 encoded string data.
- */
-
-#include "DexUtf.h"
-
-/* Compare two '\0'-terminated modified UTF-8 strings, using Unicode
- * code point values for comparison. This treats different encodings
- * for the same code point as equivalent, except that only a real '\0'
- * byte is considered the string terminator. The return value is as
- * for strcmp(). */
-int dexUtf8Cmp(const char* s1, const char* s2) {
- for (;;) {
- if (*s1 == '\0') {
- if (*s2 == '\0') {
- return 0;
- }
- return -1;
- } else if (*s2 == '\0') {
- return 1;
- }
-
- int utf1 = dexGetUtf16FromUtf8(&s1);
- int utf2 = dexGetUtf16FromUtf8(&s2);
- int diff = utf1 - utf2;
-
- if (diff != 0) {
- return diff;
- }
- }
-}
-
-/* for dexIsValidMemberNameUtf8(), a bit vector indicating valid low ascii */
-u4 DEX_MEMBER_VALID_LOW_ASCII[4] = {
- 0x00000000, // 00..1f low control characters; nothing valid
- 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
- 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
- 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z'
-};
-
-/* Helper for dexIsValidMemberNameUtf8(); do not call directly. */
-bool dexIsValidMemberNameUtf8_0(const char** pUtf8Ptr) {
- /*
- * It's a multibyte encoded character. Decode it and analyze. We
- * accept anything that isn't (a) an improperly encoded low value,
- * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
- * control character, or (e) a high space, layout, or special
- * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
- * U+fff0..U+ffff). This is all specified in the dex format
- * document.
- */
-
- u2 utf16 = dexGetUtf16FromUtf8(pUtf8Ptr);
-
- // Perform follow-up tests based on the high 8 bits.
- switch (utf16 >> 8) {
- case 0x00: {
- // It's only valid if it's above the ISO-8859-1 high space (0xa0).
- return (utf16 > 0x00a0);
- }
- case 0xd8:
- case 0xd9:
- case 0xda:
- case 0xdb: {
- /*
- * It's a leading surrogate. Check to see that a trailing
- * surrogate follows.
- */
- utf16 = dexGetUtf16FromUtf8(pUtf8Ptr);
- return (utf16 >= 0xdc00) && (utf16 <= 0xdfff);
- }
- case 0xdc:
- case 0xdd:
- case 0xde:
- case 0xdf: {
- // It's a trailing surrogate, which is not valid at this point.
- return false;
- }
- case 0x20:
- case 0xff: {
- // It's in the range that has spaces, controls, and specials.
- switch (utf16 & 0xfff8) {
- case 0x2000:
- case 0x2008:
- case 0x2028:
- case 0xfff0:
- case 0xfff8: {
- return false;
- }
- }
- break;
- }
- }
-
- return true;
-}
-
-/* Return whether the given string is a valid field or method name. */
-bool dexIsValidMemberName(const char* s) {
- bool angleName = false;
-
- switch (*s) {
- case '\0': {
- // The empty string is not a valid name.
- return false;
- }
- case '<': {
- /*
- * '<' is allowed only at the start of a name, and if present,
- * means that the name must end with '>'.
- */
- angleName = true;
- s++;
- break;
- }
- }
-
- for (;;) {
- switch (*s) {
- case '\0': {
- return !angleName;
- }
- case '>': {
- return angleName && s[1] == '\0';
- }
- }
- if (!dexIsValidMemberNameUtf8(&s)) {
- return false;
- }
- }
-}
-
-/* Helper for validating type descriptors and class names, which is parametric
- * with respect to type vs. class and dot vs. slash. */
-static bool isValidTypeDescriptorOrClassName(const char* s, bool isClassName,
- bool dotSeparator) {
- int arrayCount = 0;
-
- while (*s == '[') {
- arrayCount++;
- s++;
- }
-
- if (arrayCount > 255) {
- // Arrays may have no more than 255 dimensions.
- return false;
- }
-
- if (arrayCount != 0) {
- /*
- * If we're looking at an array of some sort, then it doesn't
- * matter if what is being asked for is a class name; the
- * format looks the same as a type descriptor in that case, so
- * treat it as such.
- */
- isClassName = false;
- }
-
- if (!isClassName) {
- /*
- * We are looking for a descriptor. Either validate it as a
- * single-character primitive type, or continue on to check the
- * embedded class name (bracketed by "L" and ";").
- */
- switch (*(s++)) {
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'I':
- case 'J':
- case 'S':
- case 'Z': {
- // These are all single-character descriptors for primitive types.
- return (*s == '\0');
- }
- case 'V': {
- // Non-array void is valid, but you can't have an array of void.
- return (arrayCount == 0) && (*s == '\0');
- }
- case 'L': {
- // Class name: Break out and continue below.
- break;
- }
- default: {
- // Oddball descriptor character.
- return false;
- }
- }
- }
-
- /*
- * We just consumed the 'L' that introduces a class name as part
- * of a type descriptor, or we are looking for an unadorned class
- * name.
- */
-
- bool sepOrFirst = true; // first character or just encountered a separator.
- for (;;) {
- u1 c = (u1) *s;
- switch (c) {
- case '\0': {
- /*
- * Premature end for a type descriptor, but valid for
- * a class name as long as we haven't encountered an
- * empty component (including the degenerate case of
- * the empty string "").
- */
- return isClassName && !sepOrFirst;
- }
- case ';': {
- /*
- * Invalid character for a class name, but the
- * legitimate end of a type descriptor. In the latter
- * case, make sure that this is the end of the string
- * and that it doesn't end with an empty component
- * (including the degenerate case of "L;").
- */
- return !isClassName && !sepOrFirst && (s[1] == '\0');
- }
- case '/':
- case '.': {
- if (dotSeparator != (c == '.')) {
- // The wrong separator character.
- return false;
- }
- if (sepOrFirst) {
- // Separator at start or two separators in a row.
- return false;
- }
- sepOrFirst = true;
- s++;
- break;
- }
- default: {
- if (!dexIsValidMemberNameUtf8(&s)) {
- return false;
- }
- sepOrFirst = false;
- break;
- }
- }
- }
-}
-
-/* Return whether the given string is a valid type descriptor. */
-bool dexIsValidTypeDescriptor(const char* s) {
- return isValidTypeDescriptorOrClassName(s, false, false);
-}
-
-/* (documented in header) */
-bool dexIsValidClassName(const char* s, bool dotSeparator) {
- return isValidTypeDescriptorOrClassName(s, true, dotSeparator);
-}
-
-/* Return whether the given string is a valid reference descriptor. This
- * is true if dexIsValidTypeDescriptor() returns true and the descriptor
- * is for a class or array and not a primitive type. */
-bool dexIsReferenceDescriptor(const char* s) {
- if (!dexIsValidTypeDescriptor(s)) {
- return false;
- }
-
- return (s[0] == 'L') || (s[0] == '[');
-}
-
-/* Return whether the given string is a valid class descriptor. This
- * is true if dexIsValidTypeDescriptor() returns true and the descriptor
- * is for a class and not an array or primitive type. */
-bool dexIsClassDescriptor(const char* s) {
- if (!dexIsValidTypeDescriptor(s)) {
- return false;
- }
-
- return s[0] == 'L';
-}
-
-/* Return whether the given string is a valid field type descriptor. This
- * is true if dexIsValidTypeDescriptor() returns true and the descriptor
- * is for anything but "void". */
-bool dexIsFieldDescriptor(const char* s) {
- if (!dexIsValidTypeDescriptor(s)) {
- return false;
- }
-
- return s[0] != 'V';
-}
-
diff --git a/libdex/DexUtf.h b/libdex/DexUtf.h
deleted file mode 100644
index cb3d919ae..000000000
--- a/libdex/DexUtf.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Validate and manipulate MUTF-8 (modified UTF-8) encoded string data.
- */
-
-#ifndef LIBDEX_DEXUTF_H_
-#define LIBDEX_DEXUTF_H_
-
-#include "DexFile.h"
-
-/*
- * Retrieve the next UTF-16 character from a UTF-8 string.
- *
- * Advances "*pUtf8Ptr" to the start of the next character.
- *
- * WARNING: If a string is corrupted by dropping a '\0' in the middle
- * of a 3-byte sequence, you can end up overrunning the buffer with
- * reads (and possibly with the writes if the length was computed and
- * cached before the damage). For performance reasons, this function
- * assumes that the string being parsed is known to be valid (e.g., by
- * already being verified). Most strings we process here are coming
- * out of dex files or other internal translations, so the only real
- * risk comes from the JNI NewStringUTF call.
- */
-DEX_INLINE u2 dexGetUtf16FromUtf8(const char** pUtf8Ptr)
-{
- unsigned int one, two, three;
-
- one = *(*pUtf8Ptr)++;
- if ((one & 0x80) != 0) {
- /* two- or three-byte encoding */
- two = *(*pUtf8Ptr)++;
- if ((one & 0x20) != 0) {
- /* three-byte encoding */
- three = *(*pUtf8Ptr)++;
- return ((one & 0x0f) << 12) |
- ((two & 0x3f) << 6) |
- (three & 0x3f);
- } else {
- /* two-byte encoding */
- return ((one & 0x1f) << 6) |
- (two & 0x3f);
- }
- } else {
- /* one-byte encoding */
- return one;
- }
-}
-
-/* Compare two '\0'-terminated modified UTF-8 strings, using Unicode
- * code point values for comparison. This treats different encodings
- * for the same code point as equivalent, except that only a real '\0'
- * byte is considered the string terminator. The return value is as
- * for strcmp(). */
-int dexUtf8Cmp(const char* s1, const char* s2);
-
-/* for dexIsValidMemberNameUtf8(), a bit vector indicating valid low ascii */
-extern u4 DEX_MEMBER_VALID_LOW_ASCII[4];
-
-/* Helper for dexIsValidMemberUtf8(); do not call directly. */
-bool dexIsValidMemberNameUtf8_0(const char** pUtf8Ptr);
-
-/* Return whether the pointed-at modified-UTF-8 encoded character is
- * valid as part of a member name, updating the pointer to point past
- * the consumed character. This will consume two encoded UTF-16 code
- * points if the character is encoded as a surrogate pair. Also, if
- * this function returns false, then the given pointer may only have
- * been partially advanced. */
-DEX_INLINE bool dexIsValidMemberNameUtf8(const char** pUtf8Ptr) {
- u1 c = (u1) **pUtf8Ptr;
- if (c <= 0x7f) {
- // It's low-ascii, so check the table.
- u4 wordIdx = c >> 5;
- u4 bitIdx = c & 0x1f;
- (*pUtf8Ptr)++;
- return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
- }
-
- /*
- * It's a multibyte encoded character. Call a non-inline function
- * for the heavy lifting.
- */
- return dexIsValidMemberNameUtf8_0(pUtf8Ptr);
-}
-
-/* Return whether the given string is a valid field or method name. */
-bool dexIsValidMemberName(const char* s);
-
-/* Return whether the given string is a valid type descriptor. */
-bool dexIsValidTypeDescriptor(const char* s);
-
-/* Return whether the given string is a valid internal-form class
- * name, with components separated either by dots or slashes as
- * specified. A class name is like a type descriptor, except that it
- * can't name a primitive type (including void). In terms of syntax,
- * the form is either (a) the name of the class without adornment
- * (that is, not bracketed by "L" and ";"); or (b) identical to the
- * type descriptor syntax for array types. */
-bool dexIsValidClassName(const char* s, bool dotSeparator);
-
-/* Return whether the given string is a valid reference descriptor. This
- * is true if dexIsValidTypeDescriptor() returns true and the descriptor
- * is for a class or array and not a primitive type. */
-bool dexIsReferenceDescriptor(const char* s);
-
-/* Return whether the given string is a valid class descriptor. This
- * is true if dexIsValidTypeDescriptor() returns true and the descriptor
- * is for a class and not an array or primitive type. */
-bool dexIsClassDescriptor(const char* s);
-
-/* Return whether the given string is a valid field type descriptor. This
- * is true if dexIsValidTypeDescriptor() returns true and the descriptor
- * is for anything but "void". */
-bool dexIsFieldDescriptor(const char* s);
-
-#endif // LIBDEX_DEXUTF_H_
diff --git a/libdex/InstrUtils.cpp b/libdex/InstrUtils.cpp
deleted file mode 100644
index 56f5dd80b..000000000
--- a/libdex/InstrUtils.cpp
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Dalvik instruction utility functions.
- *
- * IMPORTANT NOTE: Much of the contents of this file are generated
- * automatically by the opcode-gen tool. Any edits to the generated
- * sections will get wiped out the next time the tool is run.
- */
-
-#include "InstrUtils.h"
-#include <stdlib.h>
-
-/*
- * Table that maps each opcode to the full width of instructions that
- * use that opcode, in (16-bit) code units. Unimplemented opcodes as
- * well as the "breakpoint" opcode have a width of zero.
- */
-static InstructionWidth gInstructionWidthTable[kNumPackedOpcodes] = {
- // BEGIN(libdex-widths); GENERATED AUTOMATICALLY BY opcode-gen
- 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 3, 2, 2, 3, 5, 2, 2, 3, 2, 1, 1, 2,
- 2, 1, 2, 2, 3, 3, 3, 1, 1, 2, 3, 3, 3, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
- 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
- 3, 3, 3, 0, 3, 3, 3, 3, 3, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 3, 3,
- 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 4, 4, 3, 3, 2, 2,
- // END(libdex-widths)
-};
-
-/*
- * Table that maps each opcode to the flags associated with that
- * opcode.
- */
-static u1 gOpcodeFlagsTable[kNumPackedOpcodes] = {
- // BEGIN(libdex-flags); GENERATED AUTOMATICALLY BY opcode-gen
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanReturn,
- kInstrCanReturn,
- kInstrCanReturn,
- kInstrCanReturn,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue,
- kInstrCanThrow,
- kInstrCanBranch,
- kInstrCanBranch,
- kInstrCanBranch,
- kInstrCanContinue|kInstrCanSwitch,
- kInstrCanContinue|kInstrCanSwitch,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- kInstrCanContinue|kInstrCanBranch,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- 0,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- 0,
- 0,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- 0,
- kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanReturn,
- kInstrCanContinue|kInstrCanThrow,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
- kInstrCanContinue|kInstrCanThrow,
- kInstrCanContinue|kInstrCanThrow,
- // END(libdex-flags)
-};
-
-/*
- * Table that maps each opcode to the instruction format associated
- * that opcode.
- */
-static u1 gInstructionFormatTable[kNumPackedOpcodes] = {
- // BEGIN(libdex-formats); GENERATED AUTOMATICALLY BY opcode-gen
- kFmt10x, kFmt12x, kFmt22x, kFmt32x, kFmt12x, kFmt22x, kFmt32x,
- kFmt12x, kFmt22x, kFmt32x, kFmt11x, kFmt11x, kFmt11x, kFmt11x,
- kFmt10x, kFmt11x, kFmt11x, kFmt11x, kFmt11n, kFmt21s, kFmt31i,
- kFmt21h, kFmt21s, kFmt31i, kFmt51l, kFmt21h, kFmt21c, kFmt31c,
- kFmt21c, kFmt11x, kFmt11x, kFmt21c, kFmt22c, kFmt12x, kFmt21c,
- kFmt22c, kFmt35c, kFmt3rc, kFmt31t, kFmt11x, kFmt10t, kFmt20t,
- kFmt30t, kFmt31t, kFmt31t, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
- kFmt23x, kFmt22t, kFmt22t, kFmt22t, kFmt22t, kFmt22t, kFmt22t,
- kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt00x,
- kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt23x, kFmt23x,
- kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
- kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt22c, kFmt22c,
- kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c,
- kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt21c, kFmt21c,
- kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c,
- kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt35c, kFmt35c,
- kFmt35c, kFmt35c, kFmt35c, kFmt00x, kFmt3rc, kFmt3rc, kFmt3rc,
- kFmt3rc, kFmt3rc, kFmt00x, kFmt00x, kFmt12x, kFmt12x, kFmt12x,
- kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
- kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
- kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt23x, kFmt23x, kFmt23x,
- kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
- kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
- kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
- kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
- kFmt23x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
- kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
- kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
- kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
- kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt22s, kFmt22s,
- kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22b,
- kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b,
- kFmt22b, kFmt22b, kFmt22b, kFmt22c, kFmt22c, kFmt21c, kFmt21c,
- kFmt22c, kFmt22c, kFmt22c, kFmt21c, kFmt21c, kFmt00x, kFmt20bc,
- kFmt35mi, kFmt3rmi, kFmt35c, kFmt10x, kFmt22cs, kFmt00x, kFmt00x,
- kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt45cc, kFmt4rcc,
- kFmt35c, kFmt3rc, kFmt21c, kFmt21c,
- // END(libdex-formats)
-};
-
-/*
- * Table that maps each opcode to the index type implied by that
- * opcode.
- */
-static u1 gInstructionIndexTypeTable[kNumPackedOpcodes] = {
- // BEGIN(libdex-index-types); GENERATED AUTOMATICALLY BY opcode-gen
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexStringRef,
- kIndexStringRef, kIndexTypeRef, kIndexNone,
- kIndexNone, kIndexTypeRef, kIndexTypeRef,
- kIndexNone, kIndexTypeRef, kIndexTypeRef,
- kIndexTypeRef, kIndexTypeRef, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexUnknown,
- kIndexUnknown, kIndexUnknown, kIndexUnknown,
- kIndexUnknown, kIndexUnknown, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexMethodRef,
- kIndexMethodRef, kIndexMethodRef, kIndexMethodRef,
- kIndexMethodRef, kIndexUnknown, kIndexMethodRef,
- kIndexMethodRef, kIndexMethodRef, kIndexMethodRef,
- kIndexMethodRef, kIndexUnknown, kIndexUnknown,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexNone,
- kIndexNone, kIndexNone, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
- kIndexFieldRef, kIndexFieldRef, kIndexUnknown,
- kIndexVaries, kIndexInlineMethod, kIndexInlineMethod,
- kIndexMethodRef, kIndexNone, kIndexFieldOffset,
- kIndexUnknown, kIndexUnknown, kIndexUnknown,
- kIndexUnknown, kIndexUnknown, kIndexUnknown,
- kIndexUnknown, kIndexMethodAndProtoRef, kIndexMethodAndProtoRef,
- kIndexCallSiteRef, kIndexCallSiteRef, kIndexMethodHandleRef,
- kIndexProtoRef,
- // END(libdex-index-types)
-};
-
-/*
- * Global InstructionInfoTables struct.
- */
-InstructionInfoTables gDexOpcodeInfo = {
- gInstructionFormatTable,
- gInstructionIndexTypeTable,
- gOpcodeFlagsTable,
- gInstructionWidthTable
-};
-
-/*
- * Handy macros for helping decode instructions.
- */
-#define FETCH(_offset) (insns[(_offset)])
-#define FETCH_u4(_offset) (fetch_u4_impl((_offset), insns))
-#define INST_A(_inst) (((u2)(_inst) >> 8) & 0x0f)
-#define INST_B(_inst) ((u2)(_inst) >> 12)
-#define INST_AA(_inst) ((_inst) >> 8)
-
-/* Helper for FETCH_u4, above. */
-static inline u4 fetch_u4_impl(u4 offset, const u2* insns) {
- return insns[offset] | ((u4) insns[offset+1] << 16);
-}
-
-/*
- * Decode the instruction pointed to by "insns".
- *
- * Fills out the pieces of "pDec" that are affected by the current
- * instruction. Does not touch anything else.
- */
-void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec)
-{
- u2 inst = *insns;
- Opcode opcode = dexOpcodeFromCodeUnit(inst);
- InstructionFormat format = dexGetFormatFromOpcode(opcode);
-
- pDec->opcode = opcode;
- pDec->indexType = dexGetIndexTypeFromOpcode(opcode);
-
- switch (format) {
- case kFmt10x: // op
- /* nothing to do; copy the AA bits out for the verifier */
- pDec->vA = INST_AA(inst);
- break;
- case kFmt12x: // op vA, vB
- pDec->vA = INST_A(inst);
- pDec->vB = INST_B(inst);
- break;
- case kFmt11n: // op vA, #+B
- pDec->vA = INST_A(inst);
- pDec->vB = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value
- break;
- case kFmt11x: // op vAA
- pDec->vA = INST_AA(inst);
- break;
- case kFmt10t: // op +AA
- pDec->vA = (s1) INST_AA(inst); // sign-extend 8-bit value
- break;
- case kFmt20t: // op +AAAA
- pDec->vA = (s2) FETCH(1); // sign-extend 16-bit value
- break;
- case kFmt20bc: // [opt] op AA, thing@BBBB
- case kFmt21c: // op vAA, thing@BBBB
- case kFmt22x: // op vAA, vBBBB
- pDec->vA = INST_AA(inst);
- pDec->vB = FETCH(1);
- break;
- case kFmt21s: // op vAA, #+BBBB
- case kFmt21t: // op vAA, +BBBB
- pDec->vA = INST_AA(inst);
- pDec->vB = (s2) FETCH(1); // sign-extend 16-bit value
- break;
- case kFmt21h: // op vAA, #+BBBB0000[00000000]
- pDec->vA = INST_AA(inst);
- /*
- * The value should be treated as right-zero-extended, but we don't
- * actually do that here. Among other things, we don't know if it's
- * the top bits of a 32- or 64-bit value.
- */
- pDec->vB = FETCH(1);
- break;
- case kFmt23x: // op vAA, vBB, vCC
- pDec->vA = INST_AA(inst);
- pDec->vB = FETCH(1) & 0xff;
- pDec->vC = FETCH(1) >> 8;
- break;
- case kFmt22b: // op vAA, vBB, #+CC
- pDec->vA = INST_AA(inst);
- pDec->vB = FETCH(1) & 0xff;
- pDec->vC = (s1) (FETCH(1) >> 8); // sign-extend 8-bit value
- break;
- case kFmt22s: // op vA, vB, #+CCCC
- case kFmt22t: // op vA, vB, +CCCC
- pDec->vA = INST_A(inst);
- pDec->vB = INST_B(inst);
- pDec->vC = (s2) FETCH(1); // sign-extend 16-bit value
- break;
- case kFmt22c: // op vA, vB, thing@CCCC
- case kFmt22cs: // [opt] op vA, vB, field offset CCCC
- pDec->vA = INST_A(inst);
- pDec->vB = INST_B(inst);
- pDec->vC = FETCH(1);
- break;
- case kFmt30t: // op +AAAAAAAA
- pDec->vA = FETCH_u4(1); // signed 32-bit value
- break;
- case kFmt31t: // op vAA, +BBBBBBBB
- case kFmt31c: // op vAA, string@BBBBBBBB
- pDec->vA = INST_AA(inst);
- pDec->vB = FETCH_u4(1); // 32-bit value
- break;
- case kFmt32x: // op vAAAA, vBBBB
- pDec->vA = FETCH(1);
- pDec->vB = FETCH(2);
- break;
- case kFmt31i: // op vAA, #+BBBBBBBB
- pDec->vA = INST_AA(inst);
- pDec->vB = FETCH_u4(1); // signed 32-bit value
- break;
- case kFmt35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
- case kFmt35ms: // [opt] invoke-virtual+super
- case kFmt35mi: // [opt] inline invoke
- {
- /*
- * Note that the fields mentioned in the spec don't appear in
- * their "usual" positions here compared to most formats. This
- * was done so that the field names for the argument count and
- * reference index match between this format and the corresponding
- * range formats (3rc and friends).
- *
- * Bottom line: The argument count is always in vA, and the
- * method constant (or equivalent) is always in vB.
- */
- u2 regList;
- int count;
-
- pDec->vA = INST_B(inst); // This is labeled A in the spec.
- pDec->vB = FETCH(1);
- regList = FETCH(2);
-
- count = pDec->vA;
-
- /*
- * Copy the argument registers into the arg[] array, and
- * also copy the first argument (if any) into vC. (The
- * DecodedInstruction structure doesn't have separate
- * fields for {vD, vE, vF, vG}, so there's no need to make
- * copies of those.) Note that cases 5..2 fall through.
- */
- switch (count) {
- case 5: {
- if (format == kFmt35mi) {
- /* A fifth arg is verboten for inline invokes. */
- ALOGW("Invalid arg count in 35mi (5)");
- goto bail;
- }
- /*
- * Per note at the top of this format decoder, the
- * fifth argument comes from the A field in the
- * instruction, but it's labeled G in the spec.
- */
- pDec->arg[4] = INST_A(inst);
- FALLTHROUGH_INTENDED;
- }
- case 4: pDec->arg[3] = (regList >> 12) & 0x0f; FALLTHROUGH_INTENDED;
- case 3: pDec->arg[2] = (regList >> 8) & 0x0f; FALLTHROUGH_INTENDED;
- case 2: pDec->arg[1] = (regList >> 4) & 0x0f; FALLTHROUGH_INTENDED;
- case 1: pDec->vC = pDec->arg[0] = regList & 0x0f; break;
- case 0: break; // Valid, but no need to do anything.
- default:
- ALOGW("Invalid arg count in 35c/35ms/35mi (%d)", count);
- goto bail;
- }
- }
- break;
- case kFmt3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
- case kFmt3rms: // [opt] invoke-virtual+super/range
- case kFmt3rmi: // [opt] execute-inline/range
- pDec->vA = INST_AA(inst);
- pDec->vB = FETCH(1);
- pDec->vC = FETCH(2);
- break;
- case kFmt51l: // op vAA, #+BBBBBBBBBBBBBBBB
- pDec->vA = INST_AA(inst);
- pDec->vB_wide = FETCH_u4(1) | ((u8) FETCH_u4(3) << 32);
- break;
- case kFmt45cc:
- {
- // AG op BBBB FEDC HHHH
- pDec->vA = INST_B(inst); // This is labelled A in the spec.
- pDec->vB = FETCH(1); // vB meth@BBBB
- u2 fedc = FETCH(2);
- pDec->vC = fedc & 0xf;
- pDec->arg[0] = (fedc >> 4) & 0xf; // vD
- pDec->arg[1] = (fedc >> 8) & 0xf; // vE
- pDec->arg[2] = (fedc >> 12); // vF
- pDec->arg[3] = INST_A(inst); // vG
- pDec->arg[4] = FETCH(3); // vH proto@HHHH
- }
- break;
- case kFmt4rcc:
- {
- // AA op BBBB CCCC HHHH
- pDec->vA = INST_AA(inst);
- pDec->vB = FETCH(1);
- pDec->vC = FETCH(2);
- pDec->arg[4] = FETCH(3); // vH proto@HHHH
- }
- break;
- default:
- ALOGW("Can't decode unexpected format %d (op=%d)", format, opcode);
- assert(false);
- break;
- }
-
-bail:
- ;
-}
-
-/*
- * Return the width of the specified instruction, or 0 if not defined. Also
- * works for special OP_NOP entries, including switch statement data tables
- * and array data.
- */
-size_t dexGetWidthFromInstruction(const u2* insns)
-{
- size_t width;
-
- if (*insns == kPackedSwitchSignature) {
- width = 4 + insns[1] * 2;
- } else if (*insns == kSparseSwitchSignature) {
- width = 2 + insns[1] * 4;
- } else if (*insns == kArrayDataSignature) {
- u2 elemWidth = insns[1];
- u4 len = insns[2] | (((u4)insns[3]) << 16);
- // The plus 1 is to round up for odd size and width.
- width = 4 + (elemWidth * len + 1) / 2;
- } else {
- width = dexGetWidthFromOpcode(dexOpcodeFromCodeUnit(insns[0]));
- }
-
- return width;
-}
diff --git a/libdex/InstrUtils.h b/libdex/InstrUtils.h
deleted file mode 100644
index c5bf77cb0..000000000
--- a/libdex/InstrUtils.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Dalvik instruction utility functions.
- */
-#ifndef LIBDEX_INSTRUTILS_H_
-#define LIBDEX_INSTRUTILS_H_
-
-#include "DexFile.h"
-#include "DexOpcodes.h"
-
-/*
- * Possible instruction formats associated with Dalvik opcodes.
- *
- * See the file opcode-gen/README.txt for information about updating
- * opcodes and instruction formats.
- */
-enum InstructionFormat {
- kFmt00x = 0, // unknown format (also used for "breakpoint" opcode)
- kFmt10x, // op
- kFmt12x, // op vA, vB
- kFmt11n, // op vA, #+B
- kFmt11x, // op vAA
- kFmt10t, // op +AA
- kFmt20bc, // [opt] op AA, thing@BBBB
- kFmt20t, // op +AAAA
- kFmt22x, // op vAA, vBBBB
- kFmt21t, // op vAA, +BBBB
- kFmt21s, // op vAA, #+BBBB
- kFmt21h, // op vAA, #+BBBB00000[00000000]
- kFmt21c, // op vAA, thing@BBBB
- kFmt23x, // op vAA, vBB, vCC
- kFmt22b, // op vAA, vBB, #+CC
- kFmt22t, // op vA, vB, +CCCC
- kFmt22s, // op vA, vB, #+CCCC
- kFmt22c, // op vA, vB, thing@CCCC
- kFmt22cs, // [opt] op vA, vB, field offset CCCC
- kFmt30t, // op +AAAAAAAA
- kFmt32x, // op vAAAA, vBBBB
- kFmt31i, // op vAA, #+BBBBBBBB
- kFmt31t, // op vAA, +BBBBBBBB
- kFmt31c, // op vAA, string@BBBBBBBB
- kFmt35c, // op {vC,vD,vE,vF,vG}, thing@BBBB
- kFmt35ms, // [opt] invoke-virtual+super
- kFmt3rc, // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
- kFmt3rms, // [opt] invoke-virtual+super/range
- kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB
- kFmt35mi, // [opt] inline invoke
- kFmt3rmi, // [opt] inline invoke/range
- kFmt45cc, // op {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH
- kFmt4rcc, // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH
-};
-
-/*
- * Types of indexed reference that are associated with opcodes whose
- * formats include such an indexed reference (e.g., 21c and 35c).
- */
-enum InstructionIndexType {
- kIndexUnknown = 0,
- kIndexNone, // has no index
- kIndexVaries, // "It depends." Used for throw-verification-error
- kIndexTypeRef, // type reference index
- kIndexStringRef, // string reference index
- kIndexMethodRef, // method reference index
- kIndexFieldRef, // field reference index
- kIndexInlineMethod, // inline method index (for inline linked methods)
- kIndexVtableOffset, // vtable offset (for static linked methods)
- kIndexFieldOffset, // field offset (for static linked fields)
- kIndexMethodAndProtoRef, // method index and proto index
- kIndexCallSiteRef, // call site index
- kIndexMethodHandleRef, // constant method handle reference index
- kIndexProtoRef, // constant prototype reference index
-};
-
-/*
- * Instruction width implied by an opcode's format; a value in the
- * range 0 to 5. Note that there are special "pseudo-instructions"
- * which are used to encode switch and data tables, and these don't
- * have a fixed width. See dexGetWidthFromInstruction(), below.
- */
-typedef u1 InstructionWidth;
-
-/*
- * Opcode control flow flags, used by the verifier and JIT.
- */
-typedef u1 OpcodeFlags;
-enum OpcodeFlagsBits {
- kInstrCanBranch = 1, // conditional or unconditional branch
- kInstrCanContinue = 1 << 1, // flow can continue to next statement
- kInstrCanSwitch = 1 << 2, // switch statement
- kInstrCanThrow = 1 << 3, // could cause an exception to be thrown
- kInstrCanReturn = 1 << 4, // returns, no additional statements
- kInstrInvoke = 1 << 5, // a flavor of invoke
-};
-
-/*
- * Struct that includes a pointer to each of the opcode information
- * tables.
- *
- * Note: We use "u1*" here instead of the names of the enumerated
- * types to guarantee that elements don't use much space. We hold out
- * hope for a standard way to indicate the size of an enumerated type
- * that works for both C and C++, but in the mean time, this will
- * suffice.
- */
-struct InstructionInfoTables {
- u1* formats; /* InstructionFormat elements */
- u1* indexTypes; /* InstructionIndexType elements */
- OpcodeFlags* flags;
- InstructionWidth* widths;
-};
-
-/*
- * Global InstructionInfoTables struct.
- */
-extern InstructionInfoTables gDexOpcodeInfo;
-
-/*
- * Holds the contents of a decoded instruction.
- */
-struct DecodedInstruction {
- u4 vA;
- u4 vB;
- u8 vB_wide; /* for kFmt51l */
- u4 vC;
- u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
- Opcode opcode;
- InstructionIndexType indexType;
-};
-
-/*
- * Return the instruction width of the specified opcode, or 0 if not defined.
- */
-DEX_INLINE size_t dexGetWidthFromOpcode(Opcode opcode)
-{
- assert((u4) opcode < kNumPackedOpcodes);
- return gDexOpcodeInfo.widths[opcode];
-}
-
-/*
- * Return the width of the specified instruction, or 0 if not defined. Also
- * works for special OP_NOP entries, including switch statement data tables
- * and array data.
- */
-size_t dexGetWidthFromInstruction(const u2* insns);
-
-/*
- * Returns the flags for the specified opcode.
- */
-DEX_INLINE OpcodeFlags dexGetFlagsFromOpcode(Opcode opcode)
-{
- assert((u4) opcode < kNumPackedOpcodes);
- return gDexOpcodeInfo.flags[opcode];
-}
-
-/*
- * Returns true if the given flags represent a goto (unconditional branch).
- */
-DEX_INLINE bool dexIsGoto(OpcodeFlags flags)
-{
- return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch;
-}
-
-/*
- * Return the instruction format for the specified opcode.
- */
-DEX_INLINE InstructionFormat dexGetFormatFromOpcode(Opcode opcode)
-{
- assert((u4) opcode < kNumPackedOpcodes);
- return (InstructionFormat) gDexOpcodeInfo.formats[opcode];
-}
-
-/*
- * Return the instruction index type for the specified opcode.
- */
-DEX_INLINE InstructionIndexType dexGetIndexTypeFromOpcode(Opcode opcode)
-{
- assert((u4) opcode < kNumPackedOpcodes);
- return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode];
-}
-
-/*
- * Decode the instruction pointed to by "insns".
- */
-void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec);
-
-#endif // LIBDEX_INSTRUTILS_H_
diff --git a/libdex/Leb128.cpp b/libdex/Leb128.cpp
deleted file mode 100644
index ed09e19aa..000000000
--- a/libdex/Leb128.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions for interpreting LEB128 (little endian base 128) values
- */
-
-#include "Leb128.h"
-
-/*
- * Reads an unsigned LEB128 value, updating the given pointer to point
- * just past the end of the read value and also indicating whether the
- * value was syntactically valid. The only syntactically *invalid*
- * values are ones that are five bytes long where the final byte has
- * any but the low-order four bits set. Additionally, if the limit is
- * passed as non-NULL and bytes would need to be read past the limit,
- * then the read is considered invalid.
- */
-int readAndVerifyUnsignedLeb128(const u1** pStream, const u1* limit,
- bool* okay) {
- const u1* ptr = *pStream;
- int result = readUnsignedLeb128(pStream);
-
- if (((limit != NULL) && (*pStream > limit))
- || (((*pStream - ptr) == 5) && (ptr[4] > 0x0f))) {
- *okay = false;
- }
-
- return result;
-}
-
-/*
- * Reads a signed LEB128 value, updating the given pointer to point
- * just past the end of the read value and also indicating whether the
- * value was syntactically valid. The only syntactically *invalid*
- * values are ones that are five bytes long where the final byte has
- * any but the low-order four bits set. Additionally, if the limit is
- * passed as non-NULL and bytes would need to be read past the limit,
- * then the read is considered invalid.
- */
-int readAndVerifySignedLeb128(const u1** pStream, const u1* limit,
- bool* okay) {
- const u1* ptr = *pStream;
- int result = readSignedLeb128(pStream);
-
- if (((limit != NULL) && (*pStream > limit))
- || (((*pStream - ptr) == 5) && (ptr[4] > 0x0f))) {
- *okay = false;
- }
-
- return result;
-}
diff --git a/libdex/Leb128.h b/libdex/Leb128.h
deleted file mode 100644
index 21f4edaa1..000000000
--- a/libdex/Leb128.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Functions for interpreting LEB128 (little endian base 128) values
- */
-
-#ifndef LIBDEX_LEB128_H_
-#define LIBDEX_LEB128_H_
-
-#include "DexFile.h"
-
-/*
- * Reads an unsigned LEB128 value, updating the given pointer to point
- * just past the end of the read value. This function tolerates
- * non-zero high-order bits in the fifth encoded byte.
- */
-DEX_INLINE int readUnsignedLeb128(const u1** pStream) {
- const u1* ptr = *pStream;
- int result = *(ptr++);
-
- if (result > 0x7f) {
- int cur = *(ptr++);
- result = (result & 0x7f) | ((cur & 0x7f) << 7);
- if (cur > 0x7f) {
- cur = *(ptr++);
- result |= (cur & 0x7f) << 14;
- if (cur > 0x7f) {
- cur = *(ptr++);
- result |= (cur & 0x7f) << 21;
- if (cur > 0x7f) {
- /*
- * Note: We don't check to see if cur is out of
- * range here, meaning we tolerate garbage in the
- * high four-order bits.
- */
- cur = *(ptr++);
- result |= cur << 28;
- }
- }
- }
- }
-
- *pStream = ptr;
- return result;
-}
-
-/*
- * Reads a signed LEB128 value, updating the given pointer to point
- * just past the end of the read value. This function tolerates
- * non-zero high-order bits in the fifth encoded byte.
- */
-DEX_INLINE int readSignedLeb128(const u1** pStream) {
- const u1* ptr = *pStream;
- int result = *(ptr++);
-
- if (result <= 0x7f) {
- result = (result << 25) >> 25;
- } else {
- int cur = *(ptr++);
- result = (result & 0x7f) | ((cur & 0x7f) << 7);
- if (cur <= 0x7f) {
- result = (result << 18) >> 18;
- } else {
- cur = *(ptr++);
- result |= (cur & 0x7f) << 14;
- if (cur <= 0x7f) {
- result = (result << 11) >> 11;
- } else {
- cur = *(ptr++);
- result |= (cur & 0x7f) << 21;
- if (cur <= 0x7f) {
- result = (result << 4) >> 4;
- } else {
- /*
- * Note: We don't check to see if cur is out of
- * range here, meaning we tolerate garbage in the
- * high four-order bits.
- */
- cur = *(ptr++);
- result |= cur << 28;
- }
- }
- }
- }
-
- *pStream = ptr;
- return result;
-}
-
-/*
- * Reads an unsigned LEB128 value, updating the given pointer to point
- * just past the end of the read value and also indicating whether the
- * value was syntactically valid. The only syntactically *invalid*
- * values are ones that are five bytes long where the final byte has
- * any but the low-order four bits set. Additionally, if the limit is
- * passed as non-NULL and bytes would need to be read past the limit,
- * then the read is considered invalid.
- */
-int readAndVerifyUnsignedLeb128(const u1** pStream, const u1* limit,
- bool* okay);
-
-/*
- * Reads a signed LEB128 value, updating the given pointer to point
- * just past the end of the read value and also indicating whether the
- * value was syntactically valid. The only syntactically *invalid*
- * values are ones that are five bytes long where the final byte has
- * any but the low-order four bits set. Additionally, if the limit is
- * passed as non-NULL and bytes would need to be read past the limit,
- * then the read is considered invalid.
- */
-int readAndVerifySignedLeb128(const u1** pStream, const u1* limit, bool* okay);
-
-
-/*
- * Writes a 32-bit value in unsigned ULEB128 format.
- *
- * Returns the updated pointer.
- */
-DEX_INLINE u1* writeUnsignedLeb128(u1* ptr, u4 data)
-{
- while (true) {
- u1 out = data & 0x7f;
- if (out != data) {
- *ptr++ = out | 0x80;
- data >>= 7;
- } else {
- *ptr++ = out;
- break;
- }
- }
-
- return ptr;
-}
-
-/*
- * Returns the number of bytes needed to encode "val" in ULEB128 form.
- */
-DEX_INLINE int unsignedLeb128Size(u4 data)
-{
- int count = 0;
-
- do {
- data >>= 7;
- count++;
- } while (data != 0);
-
- return count;
-}
-
-#endif
diff --git a/libdex/OptInvocation.cpp b/libdex/OptInvocation.cpp
deleted file mode 100644
index 35d6262e5..000000000
--- a/libdex/OptInvocation.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Utility functions for dealing with optimized dex files.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <errno.h>
-
-#include "OptInvocation.h"
-#include "DexFile.h"
-
-static const char* kCacheDirectoryName = "dalvik-cache";
-
-#if defined(__aarch64__)
-static const char* kInstructionSet = "arm64";
-#elif defined(__arm__)
-static const char* kInstructionSet = "arm";
-#elif defined(__i386__)
-static const char* kInstructionSet = "x86";
-#elif defined(__mips__)
-static const char* kInstructionSet = "mips";
-#elif defined(__x86_64__)
-static const char* kInstructionSet = "x86_64";
-#else
-#error Unsupported instruction set.
-#endif
-
-static int dexOptMkdir(const char* path, int mode)
-{
-#ifdef _WIN32
- return mkdir(path);
-#else
- return mkdir(path, mode);
-#endif
-}
-
-/*
- * Given the filename of a .jar or .dex file, construct the DEX file cache
- * name.
- *
- * For a Jar, "subFileName" is the name of the entry (usually "classes.dex").
- * For a DEX, it may be NULL.
- *
- * Returns a newly-allocated string, or NULL on failure.
- */
-char* dexOptGenerateCacheFileName(const char* fileName, const char* subFileName)
-{
- char nameBuf[512];
- char absoluteFile[sizeof(nameBuf)];
- const size_t kBufLen = sizeof(nameBuf) - 1;
- const char* dataRoot;
- char* cp;
-
- /*
- * Get the absolute path of the Jar or DEX file.
- */
- absoluteFile[0] = '\0';
- if (fileName[0] != '/') {
- /*
- * Generate the absolute path. This doesn't do everything it
- * should, e.g. if filename is "./out/whatever" it doesn't crunch
- * the leading "./" out, but it'll do.
- */
- if (getcwd(absoluteFile, kBufLen) == NULL) {
- ALOGE("Can't get CWD while opening jar file");
- return NULL;
- }
- strncat(absoluteFile, "/", kBufLen - strlen(absoluteFile));
- }
- strncat(absoluteFile, fileName, kBufLen - strlen(absoluteFile));
-
- /*
- * Append the name of the Jar file entry, if any. This is not currently
- * required, but will be if we start putting more than one DEX file
- * in a Jar.
- */
- if (subFileName != NULL) {
- strncat(absoluteFile, "/", kBufLen - strlen(absoluteFile));
- strncat(absoluteFile, subFileName, kBufLen - strlen(absoluteFile));
- }
-
- /* Turn the path into a flat filename by replacing
- * any slashes after the first one with '@' characters.
- */
- cp = absoluteFile + 1;
- while (*cp != '\0') {
- if (*cp == '/') {
- *cp = '@';
- }
- cp++;
- }
-
- /* Build the name of the cache directory.
- */
- dataRoot = getenv("ANDROID_DATA");
- if (dataRoot == NULL)
- dataRoot = "/data";
- snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCacheDirectoryName);
- if (strcmp(dataRoot, "/data") != 0) {
- int result = dexOptMkdir(nameBuf, 0700);
- if (result != 0 && errno != EEXIST) {
- ALOGE("Failed to create dalvik-cache directory %s: %s", nameBuf, strerror(errno));
- return NULL;
- }
- }
- snprintf(nameBuf, kBufLen, "%s/%s/%s", dataRoot, kCacheDirectoryName, kInstructionSet);
- if (strcmp(dataRoot, "/data") != 0) {
- int result = dexOptMkdir(nameBuf, 0700);
- if (result != 0 && errno != EEXIST) {
- ALOGE("Failed to create dalvik-cache directory %s: %s", nameBuf, strerror(errno));
- return NULL;
- }
- }
-
- /* Tack on the file name for the actual cache file path.
- */
- strncat(nameBuf, absoluteFile, kBufLen - strlen(nameBuf));
-
- ALOGV("Cache file for '%s' '%s' is '%s'", fileName, subFileName, nameBuf);
- return strdup(nameBuf);
-}
-
-/*
- * Create a skeletal "opt" header in a new file. Most of the fields are
- * initialized to garbage, but we fill in "dexOffset" so others can
- * see how large the header is.
- *
- * "fd" must be positioned at the start of the file. On return, it will
- * be positioned just past the header, and the place where the DEX data
- * should go.
- *
- * Returns 0 on success, errno on failure.
- */
-int dexOptCreateEmptyHeader(int fd)
-{
- DexOptHeader optHdr;
- ssize_t actual;
-
- assert(lseek(fd, 0, SEEK_CUR) == 0);
-
- /*
- * The data is only expected to be readable on the current system, so
- * we just write the structure. We do need the file offset to be 64-bit
- * aligned to fulfill a DEX requirement.
- */
- assert((sizeof(optHdr) & 0x07) == 0);
- memset(&optHdr, 0xff, sizeof(optHdr));
- optHdr.dexOffset = sizeof(optHdr);
- actual = write(fd, &optHdr, sizeof(optHdr));
- if (actual != sizeof(optHdr)) {
- ALOGE("opt header write failed: %s", strerror(errno));
- return errno;
- }
-
- return 0;
-}
diff --git a/libdex/OptInvocation.h b/libdex/OptInvocation.h
deleted file mode 100644
index 3f32b94bf..000000000
--- a/libdex/OptInvocation.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Utility functions related to "dexopt".
- */
-#ifndef LIBDEX_OPTINVOCATION_H_
-#define LIBDEX_OPTINVOCATION_H_
-
-/*
- * Utility routines, used by the VM.
- */
-char* dexOptGenerateCacheFileName(const char* fileName,
- const char* subFileName);
-int dexOptCreateEmptyHeader(int fd);
-
-#endif // LIBDEX_OPTINVOCATION_H_
diff --git a/libdex/SysUtil.cpp b/libdex/SysUtil.cpp
deleted file mode 100644
index 3a1cba3b5..000000000
--- a/libdex/SysUtil.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * System utilities.
- */
-#include "DexFile.h"
-#include "SysUtil.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#if !defined(__MINGW32__)
-# include <sys/mman.h>
-#endif
-#include <limits.h>
-#include <errno.h>
-
-/*
- * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
- * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
- * not already defined, then define it here.
- */
-#ifndef TEMP_FAILURE_RETRY
-/* Used to retry syscalls that can return EINTR. */
-#define TEMP_FAILURE_RETRY(exp) ({ \
- typeof (exp) _rc; \
- do { \
- _rc = (exp); \
- } while (_rc == -1 && errno == EINTR); \
- _rc; })
-#endif
-
-/*
- * Create an anonymous shared memory segment large enough to hold "length"
- * bytes. The actual segment may be larger because mmap() operates on
- * page boundaries (usually 4K).
- */
-static void* sysCreateAnonShmem(size_t length)
-{
-#if !defined(__MINGW32__)
- void* ptr;
-
- ptr = mmap(NULL, length, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_ANON, -1, 0);
- if (ptr == MAP_FAILED) {
- ALOGW("mmap(%d, RW, SHARED|ANON) failed: %s", (int) length,
- strerror(errno));
- return NULL;
- }
-
- return ptr;
-#else
- ALOGE("sysCreateAnonShmem not implemented.");
- return NULL;
-#endif
-}
-
-/*
- * Create a private anonymous storage area.
- */
-int sysCreatePrivateMap(size_t length, MemMapping* pMap)
-{
- void* memPtr;
-
- memPtr = sysCreateAnonShmem(length);
- if (memPtr == NULL)
- return -1;
-
- pMap->addr = pMap->baseAddr = memPtr;
- pMap->length = pMap->baseLength = length;
- return 0;
-}
-
-/*
- * Determine the current offset and remaining length of the open file.
- */
-static int getFileStartAndLength(int fd, off_t *start_, size_t *length_)
-{
- off_t start, end;
- size_t length;
-
- assert(start_ != NULL);
- assert(length_ != NULL);
-
- start = lseek(fd, 0L, SEEK_CUR);
- end = lseek(fd, 0L, SEEK_END);
- (void) lseek(fd, start, SEEK_SET);
-
- if (start == (off_t) -1 || end == (off_t) -1) {
- ALOGE("could not determine length of file");
- return -1;
- }
-
- length = end - start;
- if (length == 0) {
- ALOGE("file is empty");
- return -1;
- }
-
- *start_ = start;
- *length_ = length;
-
- return 0;
-}
-
-#if defined(__MINGW32__)
-int sysFakeMapFile(int fd, MemMapping* pMap)
-{
- /* No MMAP, just fake it by copying the bits.
- For Win32 we could use MapViewOfFile if really necessary
- (see libs/utils/FileMap.cpp).
- */
- off_t start;
- size_t length;
- void* memPtr;
-
- assert(pMap != NULL);
-
- if (getFileStartAndLength(fd, &start, &length) < 0)
- return -1;
-
- memPtr = malloc(length);
- if (read(fd, memPtr, length) < 0) {
- ALOGW("read(fd=%d, start=%d, length=%d) failed: %s", (int) length,
- fd, (int) start, strerror(errno));
- free(memPtr);
- return -1;
- }
-
- pMap->baseAddr = pMap->addr = memPtr;
- pMap->baseLength = pMap->length = length;
-
- return 0;
-}
-#endif
-
-/*
- * Map a file (from fd's current offset) into a private, read-write memory
- * segment that will be marked read-only (a/k/a "writable read-only"). The
- * file offset must be a multiple of the system page size.
- *
- * In some cases the mapping will be fully writable (e.g. for files on
- * FAT filesystems).
- *
- * On success, returns 0 and fills out "pMap". On failure, returns a nonzero
- * value and does not disturb "pMap".
- */
-int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap)
-{
-#if !defined(__MINGW32__)
- off_t start;
- size_t length;
- void* memPtr;
-
- assert(pMap != NULL);
-
- if (getFileStartAndLength(fd, &start, &length) < 0)
- return -1;
-
- memPtr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,
- fd, start);
- if (memPtr == MAP_FAILED) {
- ALOGW("mmap(%d, R/W, FILE|PRIVATE, %d, %d) failed: %s", (int) length,
- fd, (int) start, strerror(errno));
- return -1;
- }
- if (mprotect(memPtr, length, PROT_READ) < 0) {
- /* this fails with EACCESS on FAT filesystems, e.g. /sdcard */
- int err = errno;
- ALOGV("mprotect(%p, %zd, PROT_READ) failed: %s",
- memPtr, length, strerror(err));
- ALOGD("mprotect(RO) failed (%d), file will remain read-write", err);
- }
-
- pMap->baseAddr = pMap->addr = memPtr;
- pMap->baseLength = pMap->length = length;
-
- return 0;
-#else
- return sysFakeMapFile(fd, pMap);
-#endif
-}
-
-/*
- * Map part of a file into a shared, read-only memory segment. The "start"
- * offset is absolute, not relative.
- *
- * On success, returns 0 and fills out "pMap". On failure, returns a nonzero
- * value and does not disturb "pMap".
- */
-int sysMapFileSegmentInShmem(int fd, off_t start, size_t length,
- MemMapping* pMap)
-{
-#if !defined(__MINGW32__)
- size_t actualLength;
- off_t actualStart;
- int adjust;
- void* memPtr;
-
- assert(pMap != NULL);
-
- /* adjust to be page-aligned */
- adjust = start % SYSTEM_PAGE_SIZE;
- actualStart = start - adjust;
- actualLength = length + adjust;
-
- memPtr = mmap(NULL, actualLength, PROT_READ, MAP_FILE | MAP_SHARED,
- fd, actualStart);
- if (memPtr == MAP_FAILED) {
- ALOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s",
- (int) actualLength, fd, (int) actualStart, strerror(errno));
- return -1;
- }
-
- pMap->baseAddr = memPtr;
- pMap->baseLength = actualLength;
- pMap->addr = (char*)memPtr + adjust;
- pMap->length = length;
-
- LOGVV("mmap seg (st=%d ln=%d): bp=%p bl=%d ad=%p ln=%d",
- (int) start, (int) length,
- pMap->baseAddr, (int) pMap->baseLength,
- pMap->addr, (int) pMap->length);
-
- return 0;
-#else
- ALOGE("sysMapFileSegmentInShmem not implemented.");
- return -1;
-#endif
-}
-
-/*
- * Change the access rights on one or more pages to read-only or read-write.
- *
- * Returns 0 on success.
- */
-int sysChangeMapAccess(void* addr, size_t length, int wantReadWrite,
- MemMapping* pMap)
-{
-#if !defined(__MINGW32__)
- /*
- * Verify that "addr" is part of this mapping file.
- */
- if (addr < pMap->baseAddr ||
- (u1*)addr >= (u1*)pMap->baseAddr + pMap->baseLength)
- {
- ALOGE("Attempted to change %p; map is %p - %p",
- addr, pMap->baseAddr, (u1*)pMap->baseAddr + pMap->baseLength);
- return -1;
- }
-
- /*
- * Align "addr" to a page boundary and adjust "length" appropriately.
- * (The address must be page-aligned, the length doesn't need to be,
- * but we do need to ensure we cover the same range.)
- */
- u1* alignAddr = (u1*) ((uintptr_t) addr & ~(SYSTEM_PAGE_SIZE-1));
- size_t alignLength = length + ((u1*) addr - alignAddr);
-
- //ALOGI("%p/%zd --> %p/%zd", addr, length, alignAddr, alignLength);
- int prot = wantReadWrite ? (PROT_READ|PROT_WRITE) : (PROT_READ);
- if (mprotect(alignAddr, alignLength, prot) != 0) {
- ALOGV("mprotect (%p,%zd,%d) failed: %s",
- alignAddr, alignLength, prot, strerror(errno));
- return (errno != 0) ? errno : -1;
- }
-#endif
-
- /* for "fake" mapping, no need to do anything */
- return 0;
-}
-
-/*
- * Release a memory mapping.
- */
-void sysReleaseShmem(MemMapping* pMap)
-{
-#if !defined(__MINGW32__)
- if (pMap->baseAddr == NULL && pMap->baseLength == 0)
- return;
-
- if (munmap(pMap->baseAddr, pMap->baseLength) < 0) {
- ALOGW("munmap(%p, %zd) failed: %s",
- pMap->baseAddr, pMap->baseLength, strerror(errno));
- } else {
- ALOGV("munmap(%p, %zd) succeeded", pMap->baseAddr, pMap->baseLength);
- pMap->baseAddr = NULL;
- pMap->baseLength = 0;
- }
-#else
- /* Free the bits allocated by sysMapFileInShmem. */
- if (pMap->baseAddr != NULL) {
- free(pMap->baseAddr);
- pMap->baseAddr = NULL;
- }
- pMap->baseLength = 0;
-#endif
-}
-
-/*
- * Make a copy of a MemMapping.
- */
-void sysCopyMap(MemMapping* dst, const MemMapping* src)
-{
- memcpy(dst, src, sizeof(MemMapping));
-}
-
-/*
- * Write until all bytes have been written.
- *
- * Returns 0 on success, or an errno value on failure.
- */
-int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
-{
- while (count != 0) {
- ssize_t actual = TEMP_FAILURE_RETRY(write(fd, buf, count));
- if (actual < 0) {
- int err = errno;
- ALOGE("%s: write failed: %s", logMsg, strerror(err));
- return err;
- } else if (actual != (ssize_t) count) {
- ALOGD("%s: partial write (will retry): (%d of %zd)",
- logMsg, (int) actual, count);
- buf = (const void*) (((const u1*) buf) + actual);
- }
- count -= actual;
- }
-
- return 0;
-}
-
-/* See documentation comment in header file. */
-int sysCopyFileToFile(int outFd, int inFd, size_t count)
-{
- const size_t kBufSize = 32768;
- unsigned char buf[kBufSize];
-
- while (count != 0) {
- size_t getSize = (count > kBufSize) ? kBufSize : count;
-
- ssize_t actual = TEMP_FAILURE_RETRY(read(inFd, buf, getSize));
- if (actual != (ssize_t) getSize) {
- ALOGW("sysCopyFileToFile: copy read failed (%d vs %zd)",
- (int) actual, getSize);
- return -1;
- }
-
- if (sysWriteFully(outFd, buf, getSize, "sysCopyFileToFile") != 0)
- return -1;
-
- count -= getSize;
- }
-
- return 0;
-}
diff --git a/libdex/SysUtil.h b/libdex/SysUtil.h
deleted file mode 100644
index c02ec6eda..000000000
--- a/libdex/SysUtil.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * System utilities.
- */
-#ifndef LIBDEX_SYSUTIL_H_
-#define LIBDEX_SYSUTIL_H_
-
-#include <sys/types.h>
-
-/*
- * System page size. Normally you're expected to get this from
- * sysconf(_SC_PAGESIZE) or some system-specific define (usually PAGESIZE
- * or PAGE_SIZE). If we use a simple #define the compiler can generate
- * appropriate masks directly, so we define it here and verify it as the
- * VM is starting up.
- *
- * Must be a power of 2.
- */
-#ifdef PAGE_SHIFT
-#define SYSTEM_PAGE_SIZE (1<<PAGE_SHIFT)
-#else
-#define SYSTEM_PAGE_SIZE 4096
-#endif
-
-/*
- * Use this to keep track of mapped segments.
- */
-struct MemMapping {
- void* addr; /* start of data */
- size_t length; /* length of data */
-
- void* baseAddr; /* page-aligned base address */
- size_t baseLength; /* length of mapping */
-};
-
-/*
- * Copy a map.
- */
-void sysCopyMap(MemMapping* dst, const MemMapping* src);
-
-/*
- * Map a file (from fd's current offset) into a shared, read-only memory
- * segment that can be made writable. (In some cases, such as when
- * mapping a file on a FAT filesystem, the result may be fully writable.)
- *
- * On success, "pMap" is filled in, and zero is returned.
- */
-int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap);
-
-/*
- * Map part of a file into a shared, read-only memory segment.
- *
- * On success, "pMap" is filled in, and zero is returned.
- */
-int sysMapFileSegmentInShmem(int fd, off_t start, size_t length,
- MemMapping* pMap);
-
-/*
- * Create a private anonymous mapping, useful for large allocations.
- *
- * On success, "pMap" is filled in, and zero is returned.
- */
-int sysCreatePrivateMap(size_t length, MemMapping* pMap);
-
-/*
- * Change the access rights on one or more pages. If "wantReadWrite" is
- * zero, the pages will be made read-only; otherwise they will be read-write.
- *
- * Returns 0 on success.
- */
-int sysChangeMapAccess(void* addr, size_t length, int wantReadWrite,
- MemMapping* pmap);
-
-/*
- * Release the pages associated with a shared memory segment.
- *
- * This does not free "pMap"; it just releases the memory.
- */
-void sysReleaseShmem(MemMapping* pMap);
-
-/*
- * Write until all bytes have been written.
- *
- * Returns 0 on success, or an errno value on failure.
- */
-int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg);
-
-/*
- * Copy the given number of bytes from one fd to another. Returns
- * 0 on success, -1 on failure.
- */
-int sysCopyFileToFile(int outFd, int inFd, size_t count);
-
-#endif // LIBDEX_SYSUTIL_H_
diff --git a/libdex/ZipArchive.h b/libdex/ZipArchive.h
deleted file mode 100644
index 206afd55c..000000000
--- a/libdex/ZipArchive.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Read-only access to Zip archives, with minimal heap allocation.
- */
-#ifndef LIBDEX_ZIPARCHIVE_H_
-#define LIBDEX_ZIPARCHIVE_H_
-
-#include <ziparchive/zip_archive.h>
-
-#include "SysUtil.h"
-#include "DexFile.h" // need DEX_INLINE
-
-/*
- * Open a Zip archive.
- *
- * On success, returns 0 and populates "pArchive". Returns nonzero errno
- * value on failure.
- */
-DEX_INLINE int dexZipOpenArchive(const char* fileName, ZipArchiveHandle* pArchive) {
- return OpenArchive(fileName, pArchive);
-}
-
-/*
- * Like dexZipOpenArchive, but takes a file descriptor open for reading
- * at the start of the file. The descriptor must be mappable (this does
- * not allow access to a stream).
- *
- * "debugFileName" will appear in error messages, but is not otherwise used.
- */
-DEX_INLINE int dexZipOpenArchiveFd(int fd, const char* debugFileName,
- ZipArchiveHandle* pArchive) {
- return OpenArchiveFd(fd, debugFileName, pArchive);
-}
-
-/*
- * Close archive, releasing resources associated with it.
- *
- * Depending on the implementation this could unmap pages used by classes
- * stored in a Jar. This should only be done after unloading classes.
- */
-DEX_INLINE void dexZipCloseArchive(ZipArchiveHandle archive) {
- CloseArchive(archive);
-}
-
-/*
- * Return the archive's file descriptor.
- */
-DEX_INLINE int dexZipGetArchiveFd(const ZipArchiveHandle pArchive) {
- return GetFileDescriptor(pArchive);
-}
-
-/*
- * Find an entry in the Zip archive, by name. Returns NULL if the entry
- * was not found.
- */
-DEX_INLINE int dexZipFindEntry(const ZipArchiveHandle pArchive,
- const char* entryName, ZipEntry* data) {
- return FindEntry(pArchive, ZipString(entryName), data);
-}
-
-/*
- * Uncompress and write an entry to a file descriptor.
- *
- * Returns 0 on success.
- */
-DEX_INLINE int dexZipExtractEntryToFile(ZipArchiveHandle handle,
- ZipEntry* entry, int fd) {
- return ExtractEntryToFile(handle, entry, fd);
-}
-
-#endif // LIBDEX_ZIPARCHIVE_H_
diff --git a/libdex/sha1.cpp b/libdex/sha1.cpp
deleted file mode 100644
index d59493451..000000000
--- a/libdex/sha1.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Tweaked in various ways for Google/Android:
- * - Changed from .cpp to .c.
- * - Made argument to SHA1Update a const pointer, and enabled
- * SHA1HANDSOFF. This incurs a speed penalty but prevents us from
- * trashing the input.
- * - Include <endian.h> to get endian info.
- * - Split a small piece into a header file.
- */
-
-/*
-sha1sum: inspired by md5sum.
-
-SHA-1 in C
-By Steve Reid <steve@edmweb.com>
-100% Public Domain
-
------------------
-Modified 7/98
-By James H. Brown <jbrown@burgoyne.com>
-Still 100% Public Domain
-
-bit machines
-Routine SHA1Update changed from
- void SHA1Update(SHA1_CTX* context, unsigned char* data,
- unsigned int len)
-to
- void SHA1Update(SHA1_CTX* context, unsigned char* data,
- unsigned long len)
-
-The 'len' parameter was declared an int which works fine on 32
-bit machines. However, on 16 bit machines an int is too small
-for the shifts being done against it. This caused the hash
-function to generate incorrect values if len was greater than
-8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
-
-Since the file IO in main() reads 16K at a time, any file 8K or
-larger would be guaranteed to generate the wrong hash (e.g.
-Test Vector #3, a million "a"s).
-
-I also changed the declaration of variables i & j in SHA1Update
-to unsigned long from unsigned int for the same reason.
-
-These changes should make no difference to any 32 bit
-implementations since an int and a long are the same size in
-those environments.
-
---
-I also corrected a few compiler warnings generated by Borland
-C.
-1. Added #include <process.h> for exit() prototype
-2. Removed unused variable 'j' in SHA1Final
-3. Changed exit(0) to return(0) at end of main.
-
-ALL changes I made can be located by searching for comments
-containing 'JHB'
-
------------------
-Modified 13 August 2000
-By Michael Paul Johnson <mpj@cryptography.org>
-Still 100% Public Domain
-
-Changed command line syntax, added feature to automatically
-check files against their previous SHA-1 check values, kind of
-like md5sum does. Added functions hexval, verifyfile,
-and sha1file. Rewrote main().
------------------
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-#define SHA1HANDSOFF /*Copies data before messing with it.*/
-
-/*#define CMDLINE * include main() and file processing */
-
-#include "sha1.h"
-
-#include <stdio.h>
-#include <string.h>
-#ifdef __BORLANDC__
-#include <dir.h>
-#include <dos.h>
-#include <process.h> /* prototype for exit() - JHB
- needed for Win32, but chokes Linux - MPJ */
-#define X_LITTLE_ENDIAN /* This should be #define'd if true.*/
-#else
-# include <unistd.h>
-# include <stdlib.h>
-//# include <endian.h>
-//# if __BYTE_ORDER == __LITTLE_ENDIAN
-# define X_LITTLE_ENDIAN
-//# endif
-#endif
-#include <ctype.h>
-
-#define LINESIZE 2048
-
-static void SHA1Transform(unsigned long state[5],
- const unsigned char buffer[64]);
-
-#define rol(value,bits) \
- (((value)<<(bits))|((value)>>(32-(bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from
- SSLeay */
-#ifdef X_LITTLE_ENDIAN
-#define blk0(i) (block->l[i]=(rol(block->l[i],24)&0xFF00FF00) \
- |(rol(block->l[i],8)&0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[(i)&15] = rol(block->l[((i)+13)&15]^block->l[((i)+8)&15] \
- ^block->l[((i)+2)&15]^block->l[(i)&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=(((w)&((x)^(y)))^(y))+blk0(i)+0x5A827999+rol(v,5);(w)=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=(((w)&((x)^(y)))^(y))+blk(i)+0x5A827999+rol(v,5);(w)=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=((w)^(x)^(y))+blk(i)+0x6ED9EBA1+rol(v,5);(w)=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=((((w)|(x))&(y))|((w)&(x)))+blk(i)+0x8F1BBCDC+rol(v,5);(w)=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=((w)^(x)^(y))+blk(i)+0xCA62C1D6+rol(v,5);(w)=rol(w,30);
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-static void SHA1Transform(unsigned long state[5],
- const unsigned char buffer[64])
-{
-unsigned long a, b, c, d, e;
-union CHAR64LONG16 {
- unsigned char c[64];
- unsigned long l[16];
-};
-CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-static unsigned char workspace[64];
- block = (CHAR64LONG16*)workspace;
- memcpy(block, buffer, 64);
-#else
- block = (CHAR64LONG16*)buffer;
-#endif
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2);
- R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5);
- R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8);
- R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14);
- R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17);
- R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20);
- R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26);
- R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29);
- R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32);
- R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38);
- R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41);
- R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44);
- R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50);
- R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53);
- R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56);
- R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62);
- R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65);
- R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68);
- R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74);
- R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77);
- R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- /* Wipe variables */
-/* a = b = c = d = e = 0; Nice try, but the compiler
-optimizes this out, anyway, and it produces an annoying
-warning. */
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, const unsigned char* data,
- unsigned long len) /* JHB */
-{
- unsigned long i, j; /* JHB */
-
- j = (context->count[0] >> 3) & 63;
- if ((context->count[0] += len << 3) < (len << 3))
- context->count[1]++;
- context->count[1] += (len >> 29);
- if ((j + len) > 63)
- {
- memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64) {
- SHA1Transform(context->state, &data[i]);
- }
- j = 0;
- }
- else
- i = 0;
- memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(unsigned char digest[HASHSIZE], SHA1_CTX*
-context)
-{
-unsigned long i; /* JHB */
-unsigned char finalcount[8];
-
- for (i = 0; i < 8; i++)
- {
- finalcount[i] = (unsigned char)((context->count[(i>=4?
- 0:1)]>>((3-(i&3))*8))&255);
- /* Endian independent */
- }
- SHA1Update(context, (unsigned char *)"\200", 1);
- while ((context->count[0] & 504) != 448) {
- SHA1Update(context, (unsigned char *)"\0", 1);
- }
- SHA1Update(context, finalcount, 8);
- /* Should cause a SHA1Transform() */
- for (i = 0; i < HASHSIZE; i++) {
- digest[i] = (unsigned char)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
- /* Wipe variables */
- memset(context->buffer, 0, 64);
- memset(context->state, 0, HASHSIZE);
- memset(context->count, 0, 8);
- memset(&finalcount, 0, 8);
-#ifdef SHA1HANDSOFF
- /* make SHA1Transform overwrite it's own static vars */
- SHA1Transform(context->state, context->buffer);
-#endif
-}
-
-
-
-#ifdef CMDLINE
-
-/* sha1file computes the SHA-1 hash of the named file and puts
- it in the 20-byte array digest. If fname is NULL, stdin is
- assumed.
-*/
-void sha1file(char *fname, unsigned char* digest)
-{
- int bytesread;
- SHA1_CTX context;
- unsigned char buffer[16384];
- FILE* f;
-
- if (fname)
- {
- f = fopen(fname, "rb");
- if (!f)
- {
- fprintf(stderr, "Can't open %s\n", fname);
- memset(digest, 0, HASHSIZE);
- return;
- }
- }
- else
- {
- f = stdin;
- }
- SHA1Init(&context);
- while (!feof(f))
- {
- bytesread = fread(buffer, 1, 16384, f);
- SHA1Update(&context, buffer, bytesread);
- }
- SHA1Final(digest, &context);
- if (fname)
- fclose(f);
-}
-
-/* Convert ASCII hexidecimal digit to 4-bit value. */
-unsigned char hexval(char c)
-{
- unsigned char h;
-
- c = toupper(c);
- if (c >= 'A')
- h = c - 'A' + 10;
- else
- h = c - '0';
- return h;
-}
-
-/* Verify a file created with sha1sum by redirecting output
- to a file. */
-int verifyfile(char *fname)
-{
- int j, k;
- int found = 0;
- unsigned char digest[HASHSIZE];
- unsigned char expected_digest[HASHSIZE];
- FILE *checkfile;
- char checkline[LINESIZE];
- char *s;
- unsigned char err;
-
- checkfile = fopen(fname, "rt");
- if (!checkfile)
- {
- fprintf(stderr, "Can't open %s\n", fname);
- return(0);
- }
- do
- {
- s = fgets(checkline, LINESIZE, checkfile);
- if (s)
- {
- if ((strlen(checkline)>26)&&
- 1 /*(!strncmp(checkline,"SHA1=", 5))*/)
- {
- /* Overwrite newline. */
- checkline[strlen(checkline)-1]=0;
- found = 1;
-
- /* Read expected check value. */
- for (k=0, j=5; k < HASHSIZE; k++)
- {
- expected_digest[k]=hexval(checkline[j++]);
- expected_digest[k]=(expected_digest[k]<<4)
- +hexval(checkline[j++]);
- }
-
- /* Compute fingerprints */
- s = checkline+46;
- sha1file(s, digest);
-
- /* Compare fingerprints */
- err = 0;
- for (k=0; k<HASHSIZE; k++)
- err |= digest[k]-
- expected_digest[k];
- if (err)
- {
- fprintf(stderr, "FAILED: %s\n"
- " EXPECTED: ", s);
- for (k=0; k<HASHSIZE; k++)
- fprintf(stderr, "%02X",
- expected_digest[k]);
- fprintf(stderr,"\n FOUND: ");
- for (k=0; k<HASHSIZE; k++)
- fprintf(stderr, "%02X", digest[k]);
- fprintf(stderr, "\n");
- }
- else
- {
- printf("OK: %s\n", s);
- }
- }
- }
- } while (s);
- fclose(checkfile);
- return found;
-}
-
-
-
-void syntax(char *progname)
-{
- printf("\nsyntax:\n"
- "%s [-c|-h][-q] file name[s]\n"
- " -c = check files against previous check values\n"
- " -g = generate SHA-1 check values (default action)\n"
- " -h = display this help\n"
- "For example,\n"
- "sha1sum test.txt > check.txt\n"
- "generates check value for test.txt in check.txt, and\n"
- "sha1sum -c check.txt\n"
- "checks test.txt against the check value in check.txt\n",
- progname);
- exit(1);
-}
-
-
-/**********************************************************/
-
-int main(int argc, char** argv)
-{
- int i, j, k;
- int check = 0;
- int found = 0;
- unsigned char digest[HASHSIZE];
- unsigned char expected_digest[HASHSIZE];
- FILE *checkfile;
- char checkline[LINESIZE];
- char *s;
-#ifdef __BORLANDC__
- struct ffblk f;
- int done;
- char path[MAXPATH];
- char drive[MAXDRIVE];
- char dir[MAXDIR];
- char name[MAXFILE];
- char ext[MAXEXT];
-#endif
- unsigned char err;
-
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] == '-')
- {
- switch (argv[i][1])
- {
- case 'c':
- case 'C':
- check = 1;
- break;
- case 'g':
- case 'G':
- check = 0;
- break;
- default:
- syntax(argv[0]);
- }
- }
- }
-
- for (i=1; i<argc; i++)
- {
- if (argv[i][0] != '-')
- {
-#ifdef __BORLANDC__
- fnsplit(argv[i], drive, dir, name, ext);
- done = findfirst(argv[i], &f, FA_RDONLY |
- FA_HIDDEN|FA_SYSTEM|FA_ARCH);
- while (!done)
- {
- sprintf(path, "%s%s%s", drive, dir, f.ff_name);
- s = path;
-#else
- s = argv[i];
-#endif
-
- if (check)
- { /* Check fingerprint file. */
- found |= verifyfile(s);
- }
- else
- { /* Generate fingerprints & write to
- stdout. */
- sha1file(s, digest);
- //printf("SHA1=");
- for (j=0; j<HASHSIZE; j++)
- printf("%02x", digest[j]);
- printf(" %s\n", s);
- found = 1;
- }
-
-#ifdef __BORLANDC__
- done = findnext(&f);
- }
-#endif
-
- }
- }
- if (!found)
- {
- if (check)
- {
- fprintf(stderr,
- "No SHA1 lines found in %s\n",
- argv[i]);
- }
- else
- {
- fprintf(stderr, "No files checked.\n");
- syntax(argv[0]);
- }
- }
- return(0); /* JHB */
-}
-
-#endif /*CMDLINE*/
diff --git a/libdex/sha1.h b/libdex/sha1.h
deleted file mode 100644
index 28907dedc..000000000
--- a/libdex/sha1.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * See "sha1.cpp" for author info.
- */
-#ifndef LIBDEX_SHA1_H_
-#define LIBDEX_SHA1_H_
-
-struct SHA1_CTX {
- unsigned long state[5];
- unsigned long count[2];
- unsigned char buffer[64];
-};
-
-#define HASHSIZE 20
-
-void SHA1Init(SHA1_CTX* context);
-void SHA1Update(SHA1_CTX* context, const unsigned char* data,
- unsigned long len);
-void SHA1Final(unsigned char digest[HASHSIZE], SHA1_CTX* context);
-
-#endif // LIBDEX_SHA1_H_