upload android base code part3
This commit is contained in:
parent
71b83c22f1
commit
b9e30e05b1
15122 changed files with 2089659 additions and 0 deletions
29
android/art/dexlist/Android.bp
Normal file
29
android/art/dexlist/Android.bp
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (C) 2015 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.
|
||||
|
||||
art_cc_binary {
|
||||
name: "dexlist",
|
||||
host_supported: true,
|
||||
srcs: ["dexlist.cc"],
|
||||
cflags: ["-Wall"],
|
||||
shared_libs: ["libart"],
|
||||
}
|
||||
|
||||
art_cc_test {
|
||||
name: "art_dexlist_tests",
|
||||
defaults: [
|
||||
"art_gtest_defaults",
|
||||
],
|
||||
srcs: ["dexlist_test.cc"],
|
||||
}
|
291
android/art/dexlist/dexlist.cc
Normal file
291
android/art/dexlist/dexlist.cc
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*
|
||||
* Implementation file of the dexlist utility.
|
||||
*
|
||||
* This is a re-implementation of the original dexlist utility that was
|
||||
* based on Dalvik functions in libdex into a new dexlist that is now
|
||||
* based on Art functions in libart instead. The output is identical to
|
||||
* the original for correct DEX files. Error messages may differ, however.
|
||||
*
|
||||
* List all methods in all concrete classes in one or more DEX files.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dex_file-inl.h"
|
||||
#include "mem_map.h"
|
||||
#include "runtime.h"
|
||||
|
||||
namespace art {
|
||||
|
||||
static const char* gProgName = "dexlist";
|
||||
|
||||
/* Command-line options. */
|
||||
static struct {
|
||||
char* argCopy;
|
||||
const char* classToFind;
|
||||
const char* methodToFind;
|
||||
const char* outputFileName;
|
||||
} gOptions;
|
||||
|
||||
/*
|
||||
* Output file. Defaults to stdout.
|
||||
*/
|
||||
static FILE* gOutFile = stdout;
|
||||
|
||||
/*
|
||||
* Data types that match the definitions in the VM specification.
|
||||
*/
|
||||
typedef uint8_t u1;
|
||||
typedef uint32_t u4;
|
||||
typedef uint64_t u8;
|
||||
|
||||
/*
|
||||
* Returns a newly-allocated string for the "dot version" of the class
|
||||
* name for the given type descriptor. That is, The initial "L" and
|
||||
* final ";" (if any) have been removed and all occurrences of '/'
|
||||
* have been changed to '.'.
|
||||
*/
|
||||
static std::unique_ptr<char[]> descriptorToDot(const char* str) {
|
||||
size_t len = strlen(str);
|
||||
if (str[0] == 'L') {
|
||||
len -= 2; // Two fewer chars to copy (trims L and ;).
|
||||
str++; // Start past 'L'.
|
||||
}
|
||||
std::unique_ptr<char[]> newStr(new char[len + 1]);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
newStr[i] = (str[i] == '/') ? '.' : str[i];
|
||||
}
|
||||
newStr[len] = '\0';
|
||||
return newStr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Positions table callback; we just want to catch the number of the
|
||||
* first line in the method, which *should* correspond to the first
|
||||
* entry from the table. (Could also use "min" here.)
|
||||
*/
|
||||
static bool positionsCb(void* context, const DexFile::PositionInfo& entry) {
|
||||
int* pFirstLine = reinterpret_cast<int *>(context);
|
||||
if (*pFirstLine == -1) {
|
||||
*pFirstLine = entry.line_;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dumps a method.
|
||||
*/
|
||||
static void dumpMethod(const DexFile* pDexFile,
|
||||
const char* fileName, u4 idx, u4 flags ATTRIBUTE_UNUSED,
|
||||
const DexFile::CodeItem* pCode, u4 codeOffset) {
|
||||
// Abstract and native methods don't get listed.
|
||||
if (pCode == nullptr || codeOffset == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Method information.
|
||||
const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
|
||||
const char* methodName = pDexFile->StringDataByIdx(pMethodId.name_idx_);
|
||||
const char* classDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
|
||||
std::unique_ptr<char[]> className(descriptorToDot(classDescriptor));
|
||||
const u4 insnsOff = codeOffset + 0x10;
|
||||
|
||||
// Don't list methods that do not match a particular query.
|
||||
if (gOptions.methodToFind != nullptr &&
|
||||
(strcmp(gOptions.classToFind, className.get()) != 0 ||
|
||||
strcmp(gOptions.methodToFind, methodName) != 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the filename is empty, then set it to something printable.
|
||||
if (fileName == nullptr || fileName[0] == 0) {
|
||||
fileName = "(none)";
|
||||
}
|
||||
|
||||
// Find the first line.
|
||||
int firstLine = -1;
|
||||
pDexFile->DecodeDebugPositionInfo(pCode, positionsCb, &firstLine);
|
||||
|
||||
// Method signature.
|
||||
const Signature signature = pDexFile->GetMethodSignature(pMethodId);
|
||||
char* typeDesc = strdup(signature.ToString().c_str());
|
||||
|
||||
// Dump actual method information.
|
||||
fprintf(gOutFile, "0x%08x %d %s %s %s %s %d\n",
|
||||
insnsOff, pCode->insns_size_in_code_units_ * 2,
|
||||
className.get(), methodName, typeDesc, fileName, firstLine);
|
||||
|
||||
free(typeDesc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs through all direct and virtual methods in the class.
|
||||
*/
|
||||
void dumpClass(const DexFile* pDexFile, u4 idx) {
|
||||
const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
|
||||
|
||||
const char* fileName;
|
||||
if (!pClassDef.source_file_idx_.IsValid()) {
|
||||
fileName = nullptr;
|
||||
} else {
|
||||
fileName = pDexFile->StringDataByIdx(pClassDef.source_file_idx_);
|
||||
}
|
||||
|
||||
const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
|
||||
if (pEncodedData != nullptr) {
|
||||
ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
|
||||
pClassData.SkipAllFields();
|
||||
// Direct methods.
|
||||
for (; pClassData.HasNextDirectMethod(); pClassData.Next()) {
|
||||
dumpMethod(pDexFile, fileName,
|
||||
pClassData.GetMemberIndex(),
|
||||
pClassData.GetRawMemberAccessFlags(),
|
||||
pClassData.GetMethodCodeItem(),
|
||||
pClassData.GetMethodCodeItemOffset());
|
||||
}
|
||||
// Virtual methods.
|
||||
for (; pClassData.HasNextVirtualMethod(); pClassData.Next()) {
|
||||
dumpMethod(pDexFile, fileName,
|
||||
pClassData.GetMemberIndex(),
|
||||
pClassData.GetRawMemberAccessFlags(),
|
||||
pClassData.GetMethodCodeItem(),
|
||||
pClassData.GetMethodCodeItemOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes a single file (either direct .dex or indirect .zip/.jar/.apk).
|
||||
*/
|
||||
static int processFile(const char* fileName) {
|
||||
// If the file is not a .dex file, the function tries .zip/.jar/.apk files,
|
||||
// all of which are Zip archives with "classes.dex" inside.
|
||||
static constexpr bool kVerifyChecksum = true;
|
||||
std::string error_msg;
|
||||
std::vector<std::unique_ptr<const DexFile>> dex_files;
|
||||
if (!DexFile::Open(fileName, fileName, kVerifyChecksum, &error_msg, &dex_files)) {
|
||||
fputs(error_msg.c_str(), stderr);
|
||||
fputc('\n', stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Success. Iterate over all dex files found in given file.
|
||||
fprintf(gOutFile, "#%s\n", fileName);
|
||||
for (size_t i = 0; i < dex_files.size(); i++) {
|
||||
// Iterate over all classes in one dex file.
|
||||
const DexFile* pDexFile = dex_files[i].get();
|
||||
const u4 classDefsSize = pDexFile->GetHeader().class_defs_size_;
|
||||
for (u4 idx = 0; idx < classDefsSize; idx++) {
|
||||
dumpClass(pDexFile, idx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shows usage.
|
||||
*/
|
||||
static void usage(void) {
|
||||
fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
|
||||
fprintf(stderr, "%s: [-m p.c.m] [-o outfile] dexfile...\n", gProgName);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Main driver of the dexlist utility.
|
||||
*/
|
||||
int dexlistDriver(int argc, char** argv) {
|
||||
// Art specific set up.
|
||||
InitLogging(argv, Runtime::Abort);
|
||||
MemMap::Init();
|
||||
|
||||
// Reset options.
|
||||
bool wantUsage = false;
|
||||
memset(&gOptions, 0, sizeof(gOptions));
|
||||
|
||||
// Parse all arguments.
|
||||
while (1) {
|
||||
const int ic = getopt(argc, argv, "o:m:");
|
||||
if (ic < 0) {
|
||||
break; // done
|
||||
}
|
||||
switch (ic) {
|
||||
case 'o': // output file
|
||||
gOptions.outputFileName = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
// If -m p.c.m is given, then find all instances of the
|
||||
// fully-qualified method name. This isn't really what
|
||||
// dexlist is for, but it's easy to do it here.
|
||||
{
|
||||
gOptions.argCopy = strdup(optarg);
|
||||
char* meth = strrchr(gOptions.argCopy, '.');
|
||||
if (meth == nullptr) {
|
||||
fprintf(stderr, "Expected: package.Class.method\n");
|
||||
wantUsage = true;
|
||||
} else {
|
||||
*meth = '\0';
|
||||
gOptions.classToFind = gOptions.argCopy;
|
||||
gOptions.methodToFind = meth + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
wantUsage = true;
|
||||
break;
|
||||
} // switch
|
||||
} // while
|
||||
|
||||
// Detect early problems.
|
||||
if (optind == argc) {
|
||||
fprintf(stderr, "%s: no file specified\n", gProgName);
|
||||
wantUsage = true;
|
||||
}
|
||||
if (wantUsage) {
|
||||
usage();
|
||||
free(gOptions.argCopy);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Open alternative output file.
|
||||
if (gOptions.outputFileName) {
|
||||
gOutFile = fopen(gOptions.outputFileName, "w");
|
||||
if (!gOutFile) {
|
||||
fprintf(stderr, "Can't open %s\n", gOptions.outputFileName);
|
||||
free(gOptions.argCopy);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Process all files supplied on command line. If one of them fails we
|
||||
// continue on, only returning a failure at the end.
|
||||
int result = 0;
|
||||
while (optind < argc) {
|
||||
result |= processFile(argv[optind++]);
|
||||
} // while
|
||||
|
||||
free(gOptions.argCopy);
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
} // namespace art
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return art::dexlistDriver(argc, argv);
|
||||
}
|
||||
|
83
android/art/dexlist/dexlist_test.cc
Normal file
83
android/art/dexlist/dexlist_test.cc
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common_runtime_test.h"
|
||||
#include "runtime/arch/instruction_set.h"
|
||||
#include "runtime/exec_utils.h"
|
||||
#include "runtime/gc/heap.h"
|
||||
#include "runtime/gc/space/image_space.h"
|
||||
#include "runtime/os.h"
|
||||
#include "runtime/utils.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace art {
|
||||
|
||||
class DexListTest : public CommonRuntimeTest {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
CommonRuntimeTest::SetUp();
|
||||
// Dogfood our own lib core dex file.
|
||||
dex_file_ = GetLibCoreDexFileNames()[0];
|
||||
}
|
||||
|
||||
// Runs test with given arguments.
|
||||
bool Exec(const std::vector<std::string>& args, std::string* error_msg) {
|
||||
std::string file_path = GetTestAndroidRoot();
|
||||
file_path += "/bin/dexlist";
|
||||
EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
|
||||
std::vector<std::string> exec_argv = { file_path };
|
||||
exec_argv.insert(exec_argv.end(), args.begin(), args.end());
|
||||
return ::art::Exec(exec_argv, error_msg);
|
||||
}
|
||||
|
||||
std::string dex_file_;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(DexListTest, NoInputFileGiven) {
|
||||
std::string error_msg;
|
||||
ASSERT_FALSE(Exec({}, &error_msg)) << error_msg;
|
||||
}
|
||||
|
||||
TEST_F(DexListTest, CantOpenOutput) {
|
||||
std::string error_msg;
|
||||
ASSERT_FALSE(Exec({"-o", "/joho", dex_file_}, &error_msg)) << error_msg;
|
||||
}
|
||||
|
||||
TEST_F(DexListTest, IllFormedMethod) {
|
||||
std::string error_msg;
|
||||
ASSERT_FALSE(Exec({"-m", "joho", dex_file_}, &error_msg)) << error_msg;
|
||||
}
|
||||
|
||||
TEST_F(DexListTest, FullOutput) {
|
||||
std::string error_msg;
|
||||
ASSERT_TRUE(Exec({"-o", "/dev/null", dex_file_}, &error_msg)) << error_msg;
|
||||
}
|
||||
|
||||
TEST_F(DexListTest, MethodOutput) {
|
||||
std::string error_msg;
|
||||
ASSERT_TRUE(Exec({"-o", "/dev/null", "-m", "java.lang.Object.toString",
|
||||
dex_file_}, &error_msg)) << error_msg;
|
||||
}
|
||||
|
||||
} // namespace art
|
Loading…
Add table
Add a link
Reference in a new issue