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,