Allow to symbolize multiple addresses at once.

Bug: 138725313
Change-Id: I9012332d345b7062669e06bd30a2a366031d94f7
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 65e2c32..ea7a286 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -47,6 +47,7 @@
 
 source_set("pprofbuilder") {
   deps = [
+    ":symbolizer",
     ":utils",
     "../../gn:default_deps",
     "../../include/perfetto/base",
diff --git a/tools/trace_to_text/local_symbolizer.cc b/tools/trace_to_text/local_symbolizer.cc
index 9b30bb3..dde9ea0 100644
--- a/tools/trace_to_text/local_symbolizer.cc
+++ b/tools/trace_to_text/local_symbolizer.cc
@@ -321,16 +321,19 @@
   }
   return result;
 }
-
-std::vector<SymbolizedFrame> LocalSymbolizer::Symbolize(
+std::vector<std::vector<SymbolizedFrame>> LocalSymbolizer::Symbolize(
     const std::string& mapping_name,
     const std::string& build_id,
-    uint64_t address) {
+    const std::vector<uint64_t>& addresses) {
   base::Optional<std::string> binary =
       finder_.FindBinary(mapping_name, build_id);
   if (!binary)
     return {};
-  return llvm_symbolizer_.Symbolize(*binary, address);
+  std::vector<std::vector<SymbolizedFrame>> result;
+  result.reserve(addresses.size());
+  for (uint64_t address : addresses)
+    result.emplace_back(llvm_symbolizer_.Symbolize(*binary, address));
+  return result;
 }
 
 LocalSymbolizer::~LocalSymbolizer() = default;
diff --git a/tools/trace_to_text/local_symbolizer.h b/tools/trace_to_text/local_symbolizer.h
index 6472d72..8fa76e9 100644
--- a/tools/trace_to_text/local_symbolizer.h
+++ b/tools/trace_to_text/local_symbolizer.h
@@ -82,9 +82,10 @@
  public:
   LocalSymbolizer(std::vector<std::string> roots) : finder_(std::move(roots)) {}
 
-  std::vector<SymbolizedFrame> Symbolize(const std::string& mapping_name,
-                                         const std::string& build_id,
-                                         uint64_t address) override;
+  std::vector<std::vector<SymbolizedFrame>> Symbolize(
+      const std::string& mapping_name,
+      const std::string& build_id,
+      const std::vector<uint64_t>& address) override;
 
   ~LocalSymbolizer() override;
 
diff --git a/tools/trace_to_text/symbolize_profile.cc b/tools/trace_to_text/symbolize_profile.cc
index 391bc46..5948677 100644
--- a/tools/trace_to_text/symbolize_profile.cc
+++ b/tools/trace_to_text/symbolize_profile.cc
@@ -34,7 +34,6 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/ext/base/utils.h"
 
 #include "tools/trace_to_text/local_symbolizer.h"
@@ -62,16 +61,6 @@
 using ::perfetto::protos::Mapping;
 using ::perfetto::protos::ProfilePacket;
 
-std::vector<std::string> GetRootsForEnv() {
-  std::vector<std::string> roots;
-  const char* root = getenv("PERFETTO_BINARY_PATH");
-  if (root != nullptr) {
-    for (base::StringSplitter sp(std::string(root), ':'); sp.Next();)
-      roots.emplace_back(sp.cur_token(), sp.cur_token_size());
-  }
-  return roots;
-}
-
 class SymbolizedTraceRewriter {
  public:
   SymbolizedTraceRewriter(std::unique_ptr<Symbolizer> symbolizer)
@@ -93,10 +82,10 @@
     }
     const ResolvedMapping& mapping = it->second;
     auto result = symbolizer_->Symbolize(mapping.mapping_name, mapping.build_id,
-                                         frame->rel_pc());
+                                         {frame->rel_pc()});
     if (!result.empty()) {
       // TODO(fmayer): Better support for inline functions.
-      const SymbolizedFrame& symf = result[0];
+      const SymbolizedFrame& symf = result[0][0];
       if (symf.function_name != "??") {
         uint64_t& id = intern_table_[symf.function_name];
         if (!id)
@@ -158,8 +147,8 @@
 }  // namespace
 
 int SymbolizeProfile(std::istream* input, std::ostream* output) {
-  SymbolizedTraceRewriter symbolizer(
-      std::unique_ptr<Symbolizer>(new LocalSymbolizer(GetRootsForEnv())));
+  SymbolizedTraceRewriter symbolizer(std::unique_ptr<Symbolizer>(
+      new LocalSymbolizer(GetPerfettoBinaryPath())));
 
   ForEachPacketInTrace(input, [&output,
                                &symbolizer](protos::TracePacket packet) {
diff --git a/tools/trace_to_text/symbolizer.h b/tools/trace_to_text/symbolizer.h
index d755abc..dc1949d 100644
--- a/tools/trace_to_text/symbolizer.h
+++ b/tools/trace_to_text/symbolizer.h
@@ -34,10 +34,15 @@
 
 class Symbolizer {
  public:
-  virtual std::vector<SymbolizedFrame> Symbolize(
+  // For each address in the input vector, output a vector of SymbolizedFrame
+  // representing the functions corresponding to that address. When inlining
+  // occurs, this can be more than one function for a single address.
+  //
+  // On failure, return an empty vector.
+  virtual std::vector<std::vector<SymbolizedFrame>> Symbolize(
       const std::string& mapping_name,
       const std::string& build_id,
-      uint64_t address) = 0;
+      const std::vector<uint64_t>& address) = 0;
   virtual ~Symbolizer();
 };
 
diff --git a/tools/trace_to_text/utils.cc b/tools/trace_to_text/utils.cc
index 70ff493..b08af58 100644
--- a/tools/trace_to_text/utils.cc
+++ b/tools/trace_to_text/utils.cc
@@ -24,6 +24,7 @@
 #include <utility>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/ext/traced/sys_stats_counters.h"
 #include "perfetto/trace/ftrace/ftrace_stats.pb.h"
 
@@ -94,5 +95,15 @@
   fprintf(stderr, "\n");
 }
 
+std::vector<std::string> GetPerfettoBinaryPath() {
+  std::vector<std::string> roots;
+  const char* root = getenv("PERFETTO_BINARY_PATH");
+  if (root != nullptr) {
+    for (base::StringSplitter sp(std::string(root), ':'); sp.Next();)
+      roots.emplace_back(sp.cur_token(), sp.cur_token_size());
+  }
+  return roots;
+}
+
 }  // namespace trace_to_text
 }  // namespace perfetto
diff --git a/tools/trace_to_text/utils.h b/tools/trace_to_text/utils.h
index a861a3a..dd2d24c 100644
--- a/tools/trace_to_text/utils.h
+++ b/tools/trace_to_text/utils.h
@@ -24,6 +24,7 @@
 #include <functional>
 #include <iostream>
 #include <memory>
+#include <vector>
 
 #include "perfetto/base/build_config.h"
 
@@ -51,6 +52,8 @@
     std::istream* input,
     const std::function<void(const protos::TracePacket&)>&);
 
+std::vector<std::string> GetPerfettoBinaryPath();
+
 }  // namespace trace_to_text
 }  // namespace perfetto