[veridex] Reflective usage detection improvements.

- Convert a string name to the internal name
- Recognize ClassLoader.loadClass.
- Do a dummy merge in VeriFlow by just overwriting registers.

bug: 77513322
Test: m

(cherry picked from commit 295cba006e5212c06fde5ec956c81c507b2974e6)

Change-Id: I888ff742197f4aec9aee68a03daca84f165e4114
diff --git a/tools/veridex/flow_analysis.cc b/tools/veridex/flow_analysis.cc
index abd0b9b..a4553f9 100644
--- a/tools/veridex/flow_analysis.cc
+++ b/tools/veridex/flow_analysis.cc
@@ -41,7 +41,11 @@
 bool VeriFlowAnalysis::MergeRegisterValues(uint32_t dex_pc) {
   // TODO: Do the merging. Right now, just return that we should continue
   // the iteration if the instruction has not been visited.
-  return !instruction_infos_[dex_pc].has_been_visited;
+  if (!instruction_infos_[dex_pc].has_been_visited) {
+    dex_registers_[dex_pc]->assign(current_registers_.begin(), current_registers_.end());
+    return true;
+  }
+  return false;
 }
 
 void VeriFlowAnalysis::SetVisited(uint32_t dex_pc) {
@@ -260,6 +264,10 @@
         RegisterValue obj = GetRegister(args[0]);
         last_result_ = RegisterValue(
             obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
+      } else if (method == VeriClass::loadClass_) {
+        RegisterValue value = GetRegister(args[1]);
+        last_result_ = RegisterValue(
+            value.GetSource(), value.GetDexFileReference(), VeriClass::class_);
       } else {
         last_result_ = GetReturnType(instruction.VRegB_35c());
       }
diff --git a/tools/veridex/flow_analysis.h b/tools/veridex/flow_analysis.h
index c065fb8..80ae5fc 100644
--- a/tools/veridex/flow_analysis.h
+++ b/tools/veridex/flow_analysis.h
@@ -20,6 +20,7 @@
 #include "dex/code_item_accessors.h"
 #include "dex/dex_file_reference.h"
 #include "dex/method_reference.h"
+#include "hidden_api.h"
 #include "veridex.h"
 
 namespace art {
@@ -52,10 +53,19 @@
   DexFileReference GetDexFileReference() const { return reference_; }
   const VeriClass* GetType() const { return type_; }
 
-  const char* ToString() const {
+  std::string ToString() const {
     switch (source_) {
-      case RegisterSource::kString:
-        return reference_.dex_file->StringDataByIdx(dex::StringIndex(reference_.index));
+      case RegisterSource::kString: {
+        const char* str = reference_.dex_file->StringDataByIdx(dex::StringIndex(reference_.index));
+        if (type_ == VeriClass::class_) {
+          // Class names at the Java level are of the form x.y.z, but the list encodes
+          // them of the form Lx/y/z;. Inner classes have '$' for both Java level class
+          // names in strings, and hidden API lists.
+          return HiddenApi::ToInternalName(str);
+        } else {
+          return str;
+        }
+      }
       case RegisterSource::kClass:
         return reference_.dex_file->StringByTypeIdx(dex::TypeIndex(reference_.index));
       default:
diff --git a/tools/veridex/hidden_api.h b/tools/veridex/hidden_api.h
index 4c67768..b1c8559 100644
--- a/tools/veridex/hidden_api.h
+++ b/tools/veridex/hidden_api.h
@@ -63,6 +63,12 @@
     return HiddenApi::GetApiMethodName(*ref.dex_file, ref.index);
   }
 
+  static std::string ToInternalName(const std::string& str) {
+    std::string val = str;
+    std::replace(val.begin(), val.end(), '.', '/');
+    return "L" + val + ";";
+  }
+
  private:
   static bool IsInList(const std::string& name, const std::set<std::string>& list) {
     return list.find(name) != list.end();
diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc
index b9be618..b1ae7dd 100644
--- a/tools/veridex/hidden_api_finder.cc
+++ b/tools/veridex/hidden_api_finder.cc
@@ -95,9 +95,7 @@
               // Class names at the Java level are of the form x.y.z, but the list encodes
               // them of the form Lx/y/z;. Inner classes have '$' for both Java level class
               // names in strings, and hidden API lists.
-              std::string str = name;
-              std::replace(str.begin(), str.end(), '.', '/');
-              str = "L" + str + ";";
+              std::string str = HiddenApi::ToInternalName(name);
               // Note: we can query the lists directly, as HiddenApi added classes that own
               // private methods and fields in them.
               // We don't add class names to the `strings_` set as we know method/field names
diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc
index 6e72faa..dc7ea94 100644
--- a/tools/veridex/veridex.cc
+++ b/tools/veridex/veridex.cc
@@ -52,6 +52,7 @@
 // Will be set after boot classpath has been resolved.
 VeriClass* VeriClass::object_ = nullptr;
 VeriClass* VeriClass::class_ = nullptr;
+VeriClass* VeriClass::class_loader_ = nullptr;
 VeriClass* VeriClass::string_ = nullptr;
 VeriClass* VeriClass::throwable_ = nullptr;
 VeriMethod VeriClass::forName_ = nullptr;
@@ -60,6 +61,7 @@
 VeriMethod VeriClass::getMethod_ = nullptr;
 VeriMethod VeriClass::getDeclaredMethod_ = nullptr;
 VeriMethod VeriClass::getClass_ = nullptr;
+VeriMethod VeriClass::loadClass_ = nullptr;
 
 struct VeridexOptions {
   const char* dex_file = nullptr;
@@ -176,6 +178,7 @@
     // methods.
     VeriClass::object_ = type_map["Ljava/lang/Object;"];
     VeriClass::class_ = type_map["Ljava/lang/Class;"];
+    VeriClass::class_loader_ = type_map["Ljava/lang/ClassLoader;"];
     VeriClass::string_ = type_map["Ljava/lang/String;"];
     VeriClass::throwable_ = type_map["Ljava/lang/Throwable;"];
     VeriClass::forName_ = boot_resolvers[0]->LookupDeclaredMethodIn(
@@ -194,6 +197,8 @@
         "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
     VeriClass::getClass_ = boot_resolvers[0]->LookupDeclaredMethodIn(
         *VeriClass::object_, "getClass", "()Ljava/lang/Class;");
+    VeriClass::loadClass_ = boot_resolvers[0]->LookupDeclaredMethodIn(
+        *VeriClass::class_loader_, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
 
     std::vector<std::unique_ptr<VeridexResolver>> app_resolvers;
     Resolve(app_dex_files, resolver_map, type_map, &app_resolvers);
diff --git a/tools/veridex/veridex.h b/tools/veridex/veridex.h
index 75e4845..9c0a158 100644
--- a/tools/veridex/veridex.h
+++ b/tools/veridex/veridex.h
@@ -65,6 +65,7 @@
 
   static VeriClass* object_;
   static VeriClass* class_;
+  static VeriClass* class_loader_;
   static VeriClass* string_;
   static VeriClass* throwable_;
   static VeriClass* boolean_;
@@ -83,6 +84,7 @@
   static VeriMethod getMethod_;
   static VeriMethod getDeclaredMethod_;
   static VeriMethod getClass_;
+  static VeriMethod loadClass_;
 
  private:
   Primitive::Type kind_;