Don't resolve already resolved paths when parsing ld.config.txt

When parsing ld.config.txt, paths in *.search.paths properties are
resolved using resolved_paths(). This is causing a number of newfstatat
system calls during a process start-up and is contributing about 3.6%
of the entire linker initialization time.

Optimize the overhead by not resolving already resolved paths; resolved
paths are cached.

Bug: 132348336
Test: strace -C -e newfstatat ls shows the number of the syscalls is
reduced from 131 to 99
Test: simpleperf record --call-graph fp -f 10000000 -o /data/perf.data ls
simpleperf report -g -i /data/perf.data
shows percentage of get_paths() from 2.9% to 2.5%

Change-Id: I79823255a89f6e2a63b80c74e6768850276ab536
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index 7741904..46c91a3 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -417,9 +417,22 @@
 
     if (resolve) {
       std::vector<std::string> resolved_paths;
-
-      // do not remove paths that do not exist
-      resolve_paths(paths, &resolved_paths);
+      for (const auto& path : paths) {
+        if (path.empty()) {
+          continue;
+        }
+        // this is single threaded. no need to lock
+        auto cached = resolved_paths_.find(path);
+        if (cached == resolved_paths_.end()) {
+          resolved_paths_[path] = resolve_path(path);
+          cached = resolved_paths_.find(path);
+        }
+        CHECK(cached != resolved_paths_.end());
+        if (cached->second.empty()) {
+          continue;
+        }
+        resolved_paths.push_back(cached->second);
+      }
 
       return resolved_paths;
     } else {
@@ -442,6 +455,7 @@
     return it;
   }
   std::unordered_map<std::string, PropertyValue> properties_;
+  std::unordered_map<std::string, std::string> resolved_paths_;
   int target_sdk_version_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Properties);