Handle gracefully profiles with invalid classes or methods
Bug: 38410980
Test: m test-art-host-run-test-707
Change-Id: I8c1b0a00c113c0faf0cc5d141e67e4183322520f
diff --git a/profman/profman.cc b/profman/profman.cc
index e565171..afc2105 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -144,6 +144,8 @@
// Separators used when parsing human friendly representation of profiles.
static const std::string kMethodSep = "->";
static const std::string kMissingTypesMarker = "missing_types";
+static const std::string kInvalidClassDescriptor = "invalid_class";
+static const std::string kInvalidMethod = "invalid_method";
static const std::string kClassAllMethods = "*";
static constexpr char kProfileParsingInlineChacheSep = '+';
static constexpr char kProfileParsingTypeSep = ',';
@@ -562,8 +564,23 @@
bool FindClass(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
const std::string& klass_descriptor,
/*out*/TypeReference* class_ref) {
+ constexpr uint16_t kInvalidTypeIndex = std::numeric_limits<uint16_t>::max() - 1;
for (const std::unique_ptr<const DexFile>& dex_file_ptr : dex_files) {
const DexFile* dex_file = dex_file_ptr.get();
+ if (klass_descriptor == kInvalidClassDescriptor) {
+ if (kInvalidTypeIndex >= dex_file->NumTypeIds()) {
+ // The dex file does not contain all possible type ids which leaves us room
+ // to add an "invalid" type id.
+ class_ref->dex_file = dex_file;
+ class_ref->type_index = dex::TypeIndex(kInvalidTypeIndex);
+ return true;
+ } else {
+ // The dex file contains all possible type ids. We don't have any free type id
+ // that we can use as invalid.
+ continue;
+ }
+ }
+
const DexFile::TypeId* type_id = dex_file->FindTypeId(klass_descriptor.c_str());
if (type_id == nullptr) {
continue;
@@ -581,15 +598,25 @@
}
// Find the method specified by method_spec in the class class_ref.
- uint32_t FindMethodIndex(const TypeReference& class_ref, const std::string& method_spec) {
+ uint32_t FindMethodIndex(const TypeReference& class_ref,
+ const std::string& method_spec) {
+ const DexFile* dex_file = class_ref.dex_file;
+ if (method_spec == kInvalidMethod) {
+ constexpr uint16_t kInvalidMethodIndex = std::numeric_limits<uint16_t>::max() - 1;
+ return kInvalidMethodIndex >= dex_file->NumMethodIds()
+ ? kInvalidMethodIndex
+ : DexFile::kDexNoIndex;
+ }
+
std::vector<std::string> name_and_signature;
Split(method_spec, kProfileParsingFirstCharInSignature, &name_and_signature);
if (name_and_signature.size() != 2) {
LOG(ERROR) << "Invalid method name and signature " << method_spec;
+ return DexFile::kDexNoIndex;
}
+
const std::string& name = name_and_signature[0];
const std::string& signature = kProfileParsingFirstCharInSignature + name_and_signature[1];
- const DexFile* dex_file = class_ref.dex_file;
const DexFile::StringId* name_id = dex_file->FindStringId(name.c_str());
if (name_id == nullptr) {
@@ -655,9 +682,12 @@
// The possible line formats are:
// "LJustTheCass;".
// "LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;".
+ // "LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,invalid_class".
// "LTestInline;->inlineMissingTypes(LSuper;)I+missing_types".
// "LTestInline;->inlineNoInlineCaches(LSuper;)I".
// "LTestInline;->*".
+ // "invalid_class".
+ // "LTestInline;->invalid_method".
// The method and classes are searched only in the given dex files.
bool ProcessLine(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
const std::string& line,