xref: /aosp_15_r20/external/abseil-cpp/absl/debugging/symbolize_elf.inc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker// Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker//
3*9356374aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker//
7*9356374aSAndroid Build Coastguard Worker//      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker//
9*9356374aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker// limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker// This library provides Symbolize() function that symbolizes program
16*9356374aSAndroid Build Coastguard Worker// counters to their corresponding symbol names on linux platforms.
17*9356374aSAndroid Build Coastguard Worker// This library has a minimal implementation of an ELF symbol table
18*9356374aSAndroid Build Coastguard Worker// reader (i.e. it doesn't depend on libelf, etc.).
19*9356374aSAndroid Build Coastguard Worker//
20*9356374aSAndroid Build Coastguard Worker// The algorithm used in Symbolize() is as follows.
21*9356374aSAndroid Build Coastguard Worker//
22*9356374aSAndroid Build Coastguard Worker//   1. Go through a list of maps in /proc/self/maps and find the map
23*9356374aSAndroid Build Coastguard Worker//   containing the program counter.
24*9356374aSAndroid Build Coastguard Worker//
25*9356374aSAndroid Build Coastguard Worker//   2. Open the mapped file and find a regular symbol table inside.
26*9356374aSAndroid Build Coastguard Worker//   Iterate over symbols in the symbol table and look for the symbol
27*9356374aSAndroid Build Coastguard Worker//   containing the program counter.  If such a symbol is found,
28*9356374aSAndroid Build Coastguard Worker//   obtain the symbol name, and demangle the symbol if possible.
29*9356374aSAndroid Build Coastguard Worker//   If the symbol isn't found in the regular symbol table (binary is
30*9356374aSAndroid Build Coastguard Worker//   stripped), try the same thing with a dynamic symbol table.
31*9356374aSAndroid Build Coastguard Worker//
32*9356374aSAndroid Build Coastguard Worker// Note that Symbolize() is originally implemented to be used in
33*9356374aSAndroid Build Coastguard Worker// signal handlers, hence it doesn't use malloc() and other unsafe
34*9356374aSAndroid Build Coastguard Worker// operations.  It should be both thread-safe and async-signal-safe.
35*9356374aSAndroid Build Coastguard Worker//
36*9356374aSAndroid Build Coastguard Worker// Implementation note:
37*9356374aSAndroid Build Coastguard Worker//
38*9356374aSAndroid Build Coastguard Worker// We don't use heaps but only use stacks.  We want to reduce the
39*9356374aSAndroid Build Coastguard Worker// stack consumption so that the symbolizer can run on small stacks.
40*9356374aSAndroid Build Coastguard Worker//
41*9356374aSAndroid Build Coastguard Worker// Here are some numbers collected with GCC 4.1.0 on x86:
42*9356374aSAndroid Build Coastguard Worker// - sizeof(Elf32_Sym)  = 16
43*9356374aSAndroid Build Coastguard Worker// - sizeof(Elf32_Shdr) = 40
44*9356374aSAndroid Build Coastguard Worker// - sizeof(Elf64_Sym)  = 24
45*9356374aSAndroid Build Coastguard Worker// - sizeof(Elf64_Shdr) = 64
46*9356374aSAndroid Build Coastguard Worker//
47*9356374aSAndroid Build Coastguard Worker// This implementation is intended to be async-signal-safe but uses some
48*9356374aSAndroid Build Coastguard Worker// functions which are not guaranteed to be so, such as memchr() and
49*9356374aSAndroid Build Coastguard Worker// memmove().  We assume they are async-signal-safe.
50*9356374aSAndroid Build Coastguard Worker
51*9356374aSAndroid Build Coastguard Worker#include <dlfcn.h>
52*9356374aSAndroid Build Coastguard Worker#include <elf.h>
53*9356374aSAndroid Build Coastguard Worker#include <fcntl.h>
54*9356374aSAndroid Build Coastguard Worker#include <link.h>  // For ElfW() macro.
55*9356374aSAndroid Build Coastguard Worker#include <sys/stat.h>
56*9356374aSAndroid Build Coastguard Worker#include <sys/types.h>
57*9356374aSAndroid Build Coastguard Worker#include <unistd.h>
58*9356374aSAndroid Build Coastguard Worker
59*9356374aSAndroid Build Coastguard Worker#include <algorithm>
60*9356374aSAndroid Build Coastguard Worker#include <array>
61*9356374aSAndroid Build Coastguard Worker#include <atomic>
62*9356374aSAndroid Build Coastguard Worker#include <cerrno>
63*9356374aSAndroid Build Coastguard Worker#include <cinttypes>
64*9356374aSAndroid Build Coastguard Worker#include <climits>
65*9356374aSAndroid Build Coastguard Worker#include <cstdint>
66*9356374aSAndroid Build Coastguard Worker#include <cstdio>
67*9356374aSAndroid Build Coastguard Worker#include <cstdlib>
68*9356374aSAndroid Build Coastguard Worker#include <cstring>
69*9356374aSAndroid Build Coastguard Worker
70*9356374aSAndroid Build Coastguard Worker#include "absl/base/casts.h"
71*9356374aSAndroid Build Coastguard Worker#include "absl/base/dynamic_annotations.h"
72*9356374aSAndroid Build Coastguard Worker#include "absl/base/internal/low_level_alloc.h"
73*9356374aSAndroid Build Coastguard Worker#include "absl/base/internal/raw_logging.h"
74*9356374aSAndroid Build Coastguard Worker#include "absl/base/internal/spinlock.h"
75*9356374aSAndroid Build Coastguard Worker#include "absl/base/port.h"
76*9356374aSAndroid Build Coastguard Worker#include "absl/debugging/internal/demangle.h"
77*9356374aSAndroid Build Coastguard Worker#include "absl/debugging/internal/vdso_support.h"
78*9356374aSAndroid Build Coastguard Worker#include "absl/strings/string_view.h"
79*9356374aSAndroid Build Coastguard Worker
80*9356374aSAndroid Build Coastguard Worker#if defined(__FreeBSD__) && !defined(ElfW)
81*9356374aSAndroid Build Coastguard Worker#define ElfW(x) __ElfN(x)
82*9356374aSAndroid Build Coastguard Worker#endif
83*9356374aSAndroid Build Coastguard Worker
84*9356374aSAndroid Build Coastguard Workernamespace absl {
85*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_BEGIN
86*9356374aSAndroid Build Coastguard Worker
87*9356374aSAndroid Build Coastguard Worker// Value of argv[0]. Used by MaybeInitializeObjFile().
88*9356374aSAndroid Build Coastguard Workerstatic char *argv0_value = nullptr;
89*9356374aSAndroid Build Coastguard Worker
90*9356374aSAndroid Build Coastguard Workervoid InitializeSymbolizer(const char *argv0) {
91*9356374aSAndroid Build Coastguard Worker#ifdef ABSL_HAVE_VDSO_SUPPORT
92*9356374aSAndroid Build Coastguard Worker  // We need to make sure VDSOSupport::Init() is called before any setuid or
93*9356374aSAndroid Build Coastguard Worker  // chroot calls, so InitializeSymbolizer() should be called very early in the
94*9356374aSAndroid Build Coastguard Worker  // life of a program.
95*9356374aSAndroid Build Coastguard Worker  absl::debugging_internal::VDSOSupport::Init();
96*9356374aSAndroid Build Coastguard Worker#endif
97*9356374aSAndroid Build Coastguard Worker  if (argv0_value != nullptr) {
98*9356374aSAndroid Build Coastguard Worker    free(argv0_value);
99*9356374aSAndroid Build Coastguard Worker    argv0_value = nullptr;
100*9356374aSAndroid Build Coastguard Worker  }
101*9356374aSAndroid Build Coastguard Worker  if (argv0 != nullptr && argv0[0] != '\0') {
102*9356374aSAndroid Build Coastguard Worker    argv0_value = strdup(argv0);
103*9356374aSAndroid Build Coastguard Worker  }
104*9356374aSAndroid Build Coastguard Worker}
105*9356374aSAndroid Build Coastguard Worker
106*9356374aSAndroid Build Coastguard Workernamespace debugging_internal {
107*9356374aSAndroid Build Coastguard Workernamespace {
108*9356374aSAndroid Build Coastguard Worker
109*9356374aSAndroid Build Coastguard Worker// Re-runs fn until it doesn't cause EINTR.
110*9356374aSAndroid Build Coastguard Worker#define NO_INTR(fn) \
111*9356374aSAndroid Build Coastguard Worker  do {              \
112*9356374aSAndroid Build Coastguard Worker  } while ((fn) < 0 && errno == EINTR)
113*9356374aSAndroid Build Coastguard Worker
114*9356374aSAndroid Build Coastguard Worker// On Linux, ELF_ST_* are defined in <linux/elf.h>.  To make this portable
115*9356374aSAndroid Build Coastguard Worker// we define our own ELF_ST_BIND and ELF_ST_TYPE if not available.
116*9356374aSAndroid Build Coastguard Worker#ifndef ELF_ST_BIND
117*9356374aSAndroid Build Coastguard Worker#define ELF_ST_BIND(info) (((unsigned char)(info)) >> 4)
118*9356374aSAndroid Build Coastguard Worker#endif
119*9356374aSAndroid Build Coastguard Worker
120*9356374aSAndroid Build Coastguard Worker#ifndef ELF_ST_TYPE
121*9356374aSAndroid Build Coastguard Worker#define ELF_ST_TYPE(info) (((unsigned char)(info)) & 0xF)
122*9356374aSAndroid Build Coastguard Worker#endif
123*9356374aSAndroid Build Coastguard Worker
124*9356374aSAndroid Build Coastguard Worker// Some platforms use a special .opd section to store function pointers.
125*9356374aSAndroid Build Coastguard Workerconst char kOpdSectionName[] = ".opd";
126*9356374aSAndroid Build Coastguard Worker
127*9356374aSAndroid Build Coastguard Worker#if (defined(__powerpc__) && !(_CALL_ELF > 1)) || defined(__ia64)
128*9356374aSAndroid Build Coastguard Worker// Use opd section for function descriptors on these platforms, the function
129*9356374aSAndroid Build Coastguard Worker// address is the first word of the descriptor.
130*9356374aSAndroid Build Coastguard Workerenum { kPlatformUsesOPDSections = 1 };
131*9356374aSAndroid Build Coastguard Worker#else  // not PPC or IA64
132*9356374aSAndroid Build Coastguard Workerenum { kPlatformUsesOPDSections = 0 };
133*9356374aSAndroid Build Coastguard Worker#endif
134*9356374aSAndroid Build Coastguard Worker
135*9356374aSAndroid Build Coastguard Worker// This works for PowerPC & IA64 only.  A function descriptor consist of two
136*9356374aSAndroid Build Coastguard Worker// pointers and the first one is the function's entry.
137*9356374aSAndroid Build Coastguard Workerconst size_t kFunctionDescriptorSize = sizeof(void *) * 2;
138*9356374aSAndroid Build Coastguard Worker
139*9356374aSAndroid Build Coastguard Workerconst int kMaxDecorators = 10;  // Seems like a reasonable upper limit.
140*9356374aSAndroid Build Coastguard Worker
141*9356374aSAndroid Build Coastguard Workerstruct InstalledSymbolDecorator {
142*9356374aSAndroid Build Coastguard Worker  SymbolDecorator fn;
143*9356374aSAndroid Build Coastguard Worker  void *arg;
144*9356374aSAndroid Build Coastguard Worker  int ticket;
145*9356374aSAndroid Build Coastguard Worker};
146*9356374aSAndroid Build Coastguard Worker
147*9356374aSAndroid Build Coastguard Workerint g_num_decorators;
148*9356374aSAndroid Build Coastguard WorkerInstalledSymbolDecorator g_decorators[kMaxDecorators];
149*9356374aSAndroid Build Coastguard Worker
150*9356374aSAndroid Build Coastguard Workerstruct FileMappingHint {
151*9356374aSAndroid Build Coastguard Worker  const void *start;
152*9356374aSAndroid Build Coastguard Worker  const void *end;
153*9356374aSAndroid Build Coastguard Worker  uint64_t offset;
154*9356374aSAndroid Build Coastguard Worker  const char *filename;
155*9356374aSAndroid Build Coastguard Worker};
156*9356374aSAndroid Build Coastguard Worker
157*9356374aSAndroid Build Coastguard Worker// Protects g_decorators.
158*9356374aSAndroid Build Coastguard Worker// We are using SpinLock and not a Mutex here, because we may be called
159*9356374aSAndroid Build Coastguard Worker// from inside Mutex::Lock itself, and it prohibits recursive calls.
160*9356374aSAndroid Build Coastguard Worker// This happens in e.g. base/stacktrace_syscall_unittest.
161*9356374aSAndroid Build Coastguard Worker// Moreover, we are using only TryLock(), if the decorator list
162*9356374aSAndroid Build Coastguard Worker// is being modified (is busy), we skip all decorators, and possibly
163*9356374aSAndroid Build Coastguard Worker// loose some info. Sorry, that's the best we could do.
164*9356374aSAndroid Build Coastguard WorkerABSL_CONST_INIT absl::base_internal::SpinLock g_decorators_mu(
165*9356374aSAndroid Build Coastguard Worker    absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
166*9356374aSAndroid Build Coastguard Worker
167*9356374aSAndroid Build Coastguard Workerconst int kMaxFileMappingHints = 8;
168*9356374aSAndroid Build Coastguard Workerint g_num_file_mapping_hints;
169*9356374aSAndroid Build Coastguard WorkerFileMappingHint g_file_mapping_hints[kMaxFileMappingHints];
170*9356374aSAndroid Build Coastguard Worker// Protects g_file_mapping_hints.
171*9356374aSAndroid Build Coastguard WorkerABSL_CONST_INIT absl::base_internal::SpinLock g_file_mapping_mu(
172*9356374aSAndroid Build Coastguard Worker    absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
173*9356374aSAndroid Build Coastguard Worker
174*9356374aSAndroid Build Coastguard Worker// Async-signal-safe function to zero a buffer.
175*9356374aSAndroid Build Coastguard Worker// memset() is not guaranteed to be async-signal-safe.
176*9356374aSAndroid Build Coastguard Workerstatic void SafeMemZero(void* p, size_t size) {
177*9356374aSAndroid Build Coastguard Worker  unsigned char *c = static_cast<unsigned char *>(p);
178*9356374aSAndroid Build Coastguard Worker  while (size--) {
179*9356374aSAndroid Build Coastguard Worker    *c++ = 0;
180*9356374aSAndroid Build Coastguard Worker  }
181*9356374aSAndroid Build Coastguard Worker}
182*9356374aSAndroid Build Coastguard Worker
183*9356374aSAndroid Build Coastguard Workerstruct ObjFile {
184*9356374aSAndroid Build Coastguard Worker  ObjFile()
185*9356374aSAndroid Build Coastguard Worker      : filename(nullptr),
186*9356374aSAndroid Build Coastguard Worker        start_addr(nullptr),
187*9356374aSAndroid Build Coastguard Worker        end_addr(nullptr),
188*9356374aSAndroid Build Coastguard Worker        offset(0),
189*9356374aSAndroid Build Coastguard Worker        fd(-1),
190*9356374aSAndroid Build Coastguard Worker        elf_type(-1) {
191*9356374aSAndroid Build Coastguard Worker    SafeMemZero(&elf_header, sizeof(elf_header));
192*9356374aSAndroid Build Coastguard Worker    SafeMemZero(&phdr[0], sizeof(phdr));
193*9356374aSAndroid Build Coastguard Worker  }
194*9356374aSAndroid Build Coastguard Worker
195*9356374aSAndroid Build Coastguard Worker  char *filename;
196*9356374aSAndroid Build Coastguard Worker  const void *start_addr;
197*9356374aSAndroid Build Coastguard Worker  const void *end_addr;
198*9356374aSAndroid Build Coastguard Worker  uint64_t offset;
199*9356374aSAndroid Build Coastguard Worker
200*9356374aSAndroid Build Coastguard Worker  // The following fields are initialized on the first access to the
201*9356374aSAndroid Build Coastguard Worker  // object file.
202*9356374aSAndroid Build Coastguard Worker  int fd;
203*9356374aSAndroid Build Coastguard Worker  int elf_type;
204*9356374aSAndroid Build Coastguard Worker  ElfW(Ehdr) elf_header;
205*9356374aSAndroid Build Coastguard Worker
206*9356374aSAndroid Build Coastguard Worker  // PT_LOAD program header describing executable code.
207*9356374aSAndroid Build Coastguard Worker  // Normally we expect just one, but SWIFT binaries have two.
208*9356374aSAndroid Build Coastguard Worker  // CUDA binaries have 3 (see cr/473913254 description).
209*9356374aSAndroid Build Coastguard Worker  std::array<ElfW(Phdr), 4> phdr;
210*9356374aSAndroid Build Coastguard Worker};
211*9356374aSAndroid Build Coastguard Worker
212*9356374aSAndroid Build Coastguard Worker// Build 4-way associative cache for symbols. Within each cache line, symbols
213*9356374aSAndroid Build Coastguard Worker// are replaced in LRU order.
214*9356374aSAndroid Build Coastguard Workerenum {
215*9356374aSAndroid Build Coastguard Worker  ASSOCIATIVITY = 4,
216*9356374aSAndroid Build Coastguard Worker};
217*9356374aSAndroid Build Coastguard Workerstruct SymbolCacheLine {
218*9356374aSAndroid Build Coastguard Worker  const void *pc[ASSOCIATIVITY];
219*9356374aSAndroid Build Coastguard Worker  char *name[ASSOCIATIVITY];
220*9356374aSAndroid Build Coastguard Worker
221*9356374aSAndroid Build Coastguard Worker  // age[i] is incremented when a line is accessed. it's reset to zero if the
222*9356374aSAndroid Build Coastguard Worker  // i'th entry is read.
223*9356374aSAndroid Build Coastguard Worker  uint32_t age[ASSOCIATIVITY];
224*9356374aSAndroid Build Coastguard Worker};
225*9356374aSAndroid Build Coastguard Worker
226*9356374aSAndroid Build Coastguard Worker// ---------------------------------------------------------------
227*9356374aSAndroid Build Coastguard Worker// An async-signal-safe arena for LowLevelAlloc
228*9356374aSAndroid Build Coastguard Workerstatic std::atomic<base_internal::LowLevelAlloc::Arena *> g_sig_safe_arena;
229*9356374aSAndroid Build Coastguard Worker
230*9356374aSAndroid Build Coastguard Workerstatic base_internal::LowLevelAlloc::Arena *SigSafeArena() {
231*9356374aSAndroid Build Coastguard Worker  return g_sig_safe_arena.load(std::memory_order_acquire);
232*9356374aSAndroid Build Coastguard Worker}
233*9356374aSAndroid Build Coastguard Worker
234*9356374aSAndroid Build Coastguard Workerstatic void InitSigSafeArena() {
235*9356374aSAndroid Build Coastguard Worker  if (SigSafeArena() == nullptr) {
236*9356374aSAndroid Build Coastguard Worker    base_internal::LowLevelAlloc::Arena *new_arena =
237*9356374aSAndroid Build Coastguard Worker        base_internal::LowLevelAlloc::NewArena(
238*9356374aSAndroid Build Coastguard Worker            base_internal::LowLevelAlloc::kAsyncSignalSafe);
239*9356374aSAndroid Build Coastguard Worker    base_internal::LowLevelAlloc::Arena *old_value = nullptr;
240*9356374aSAndroid Build Coastguard Worker    if (!g_sig_safe_arena.compare_exchange_strong(old_value, new_arena,
241*9356374aSAndroid Build Coastguard Worker                                                  std::memory_order_release,
242*9356374aSAndroid Build Coastguard Worker                                                  std::memory_order_relaxed)) {
243*9356374aSAndroid Build Coastguard Worker      // We lost a race to allocate an arena; deallocate.
244*9356374aSAndroid Build Coastguard Worker      base_internal::LowLevelAlloc::DeleteArena(new_arena);
245*9356374aSAndroid Build Coastguard Worker    }
246*9356374aSAndroid Build Coastguard Worker  }
247*9356374aSAndroid Build Coastguard Worker}
248*9356374aSAndroid Build Coastguard Worker
249*9356374aSAndroid Build Coastguard Worker// ---------------------------------------------------------------
250*9356374aSAndroid Build Coastguard Worker// An AddrMap is a vector of ObjFile, using SigSafeArena() for allocation.
251*9356374aSAndroid Build Coastguard Worker
252*9356374aSAndroid Build Coastguard Workerclass AddrMap {
253*9356374aSAndroid Build Coastguard Worker public:
254*9356374aSAndroid Build Coastguard Worker  AddrMap() : size_(0), allocated_(0), obj_(nullptr) {}
255*9356374aSAndroid Build Coastguard Worker  ~AddrMap() { base_internal::LowLevelAlloc::Free(obj_); }
256*9356374aSAndroid Build Coastguard Worker  size_t Size() const { return size_; }
257*9356374aSAndroid Build Coastguard Worker  ObjFile *At(size_t i) { return &obj_[i]; }
258*9356374aSAndroid Build Coastguard Worker  ObjFile *Add();
259*9356374aSAndroid Build Coastguard Worker  void Clear();
260*9356374aSAndroid Build Coastguard Worker
261*9356374aSAndroid Build Coastguard Worker private:
262*9356374aSAndroid Build Coastguard Worker  size_t size_;       // count of valid elements (<= allocated_)
263*9356374aSAndroid Build Coastguard Worker  size_t allocated_;  // count of allocated elements
264*9356374aSAndroid Build Coastguard Worker  ObjFile *obj_;      // array of allocated_ elements
265*9356374aSAndroid Build Coastguard Worker  AddrMap(const AddrMap &) = delete;
266*9356374aSAndroid Build Coastguard Worker  AddrMap &operator=(const AddrMap &) = delete;
267*9356374aSAndroid Build Coastguard Worker};
268*9356374aSAndroid Build Coastguard Worker
269*9356374aSAndroid Build Coastguard Workervoid AddrMap::Clear() {
270*9356374aSAndroid Build Coastguard Worker  for (size_t i = 0; i != size_; i++) {
271*9356374aSAndroid Build Coastguard Worker    At(i)->~ObjFile();
272*9356374aSAndroid Build Coastguard Worker  }
273*9356374aSAndroid Build Coastguard Worker  size_ = 0;
274*9356374aSAndroid Build Coastguard Worker}
275*9356374aSAndroid Build Coastguard Worker
276*9356374aSAndroid Build Coastguard WorkerObjFile *AddrMap::Add() {
277*9356374aSAndroid Build Coastguard Worker  if (size_ == allocated_) {
278*9356374aSAndroid Build Coastguard Worker    size_t new_allocated = allocated_ * 2 + 50;
279*9356374aSAndroid Build Coastguard Worker    ObjFile *new_obj_ =
280*9356374aSAndroid Build Coastguard Worker        static_cast<ObjFile *>(base_internal::LowLevelAlloc::AllocWithArena(
281*9356374aSAndroid Build Coastguard Worker            new_allocated * sizeof(*new_obj_), SigSafeArena()));
282*9356374aSAndroid Build Coastguard Worker    if (obj_) {
283*9356374aSAndroid Build Coastguard Worker      memcpy(new_obj_, obj_, allocated_ * sizeof(*new_obj_));
284*9356374aSAndroid Build Coastguard Worker      base_internal::LowLevelAlloc::Free(obj_);
285*9356374aSAndroid Build Coastguard Worker    }
286*9356374aSAndroid Build Coastguard Worker    obj_ = new_obj_;
287*9356374aSAndroid Build Coastguard Worker    allocated_ = new_allocated;
288*9356374aSAndroid Build Coastguard Worker  }
289*9356374aSAndroid Build Coastguard Worker  return new (&obj_[size_++]) ObjFile;
290*9356374aSAndroid Build Coastguard Worker}
291*9356374aSAndroid Build Coastguard Worker
292*9356374aSAndroid Build Coastguard Workerclass CachingFile {
293*9356374aSAndroid Build Coastguard Worker public:
294*9356374aSAndroid Build Coastguard Worker  // Setup reader for fd that uses buf[0, buf_size-1] as a cache.
295*9356374aSAndroid Build Coastguard Worker  CachingFile(int fd, char *buf, size_t buf_size)
296*9356374aSAndroid Build Coastguard Worker      : fd_(fd),
297*9356374aSAndroid Build Coastguard Worker        cache_(buf),
298*9356374aSAndroid Build Coastguard Worker        cache_size_(buf_size),
299*9356374aSAndroid Build Coastguard Worker        cache_start_(0),
300*9356374aSAndroid Build Coastguard Worker        cache_limit_(0) {}
301*9356374aSAndroid Build Coastguard Worker
302*9356374aSAndroid Build Coastguard Worker  int fd() const { return fd_; }
303*9356374aSAndroid Build Coastguard Worker  ssize_t ReadFromOffset(void *buf, size_t count, off_t offset);
304*9356374aSAndroid Build Coastguard Worker  bool ReadFromOffsetExact(void *buf, size_t count, off_t offset);
305*9356374aSAndroid Build Coastguard Worker
306*9356374aSAndroid Build Coastguard Worker private:
307*9356374aSAndroid Build Coastguard Worker  // Bytes [cache_start_, cache_limit_-1] from fd_ are stored in
308*9356374aSAndroid Build Coastguard Worker  // a prefix of cache_[0, cache_size_-1].
309*9356374aSAndroid Build Coastguard Worker  int fd_;
310*9356374aSAndroid Build Coastguard Worker  char *cache_;
311*9356374aSAndroid Build Coastguard Worker  size_t cache_size_;
312*9356374aSAndroid Build Coastguard Worker  off_t cache_start_;
313*9356374aSAndroid Build Coastguard Worker  off_t cache_limit_;
314*9356374aSAndroid Build Coastguard Worker};
315*9356374aSAndroid Build Coastguard Worker
316*9356374aSAndroid Build Coastguard Worker// ---------------------------------------------------------------
317*9356374aSAndroid Build Coastguard Worker
318*9356374aSAndroid Build Coastguard Workerenum FindSymbolResult { SYMBOL_NOT_FOUND = 1, SYMBOL_TRUNCATED, SYMBOL_FOUND };
319*9356374aSAndroid Build Coastguard Worker
320*9356374aSAndroid Build Coastguard Workerclass Symbolizer {
321*9356374aSAndroid Build Coastguard Worker public:
322*9356374aSAndroid Build Coastguard Worker  Symbolizer();
323*9356374aSAndroid Build Coastguard Worker  ~Symbolizer();
324*9356374aSAndroid Build Coastguard Worker  const char *GetSymbol(const void *const pc);
325*9356374aSAndroid Build Coastguard Worker
326*9356374aSAndroid Build Coastguard Worker private:
327*9356374aSAndroid Build Coastguard Worker  char *CopyString(const char *s) {
328*9356374aSAndroid Build Coastguard Worker    size_t len = strlen(s);
329*9356374aSAndroid Build Coastguard Worker    char *dst = static_cast<char *>(
330*9356374aSAndroid Build Coastguard Worker        base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena()));
331*9356374aSAndroid Build Coastguard Worker    ABSL_RAW_CHECK(dst != nullptr, "out of memory");
332*9356374aSAndroid Build Coastguard Worker    memcpy(dst, s, len + 1);
333*9356374aSAndroid Build Coastguard Worker    return dst;
334*9356374aSAndroid Build Coastguard Worker  }
335*9356374aSAndroid Build Coastguard Worker  ObjFile *FindObjFile(const void *const start,
336*9356374aSAndroid Build Coastguard Worker                       size_t size) ABSL_ATTRIBUTE_NOINLINE;
337*9356374aSAndroid Build Coastguard Worker  static bool RegisterObjFile(const char *filename,
338*9356374aSAndroid Build Coastguard Worker                              const void *const start_addr,
339*9356374aSAndroid Build Coastguard Worker                              const void *const end_addr, uint64_t offset,
340*9356374aSAndroid Build Coastguard Worker                              void *arg);
341*9356374aSAndroid Build Coastguard Worker  SymbolCacheLine *GetCacheLine(const void *const pc);
342*9356374aSAndroid Build Coastguard Worker  const char *FindSymbolInCache(const void *const pc);
343*9356374aSAndroid Build Coastguard Worker  const char *InsertSymbolInCache(const void *const pc, const char *name);
344*9356374aSAndroid Build Coastguard Worker  void AgeSymbols(SymbolCacheLine *line);
345*9356374aSAndroid Build Coastguard Worker  void ClearAddrMap();
346*9356374aSAndroid Build Coastguard Worker  FindSymbolResult GetSymbolFromObjectFile(const ObjFile &obj,
347*9356374aSAndroid Build Coastguard Worker                                           const void *const pc,
348*9356374aSAndroid Build Coastguard Worker                                           const ptrdiff_t relocation,
349*9356374aSAndroid Build Coastguard Worker                                           char *out, size_t out_size,
350*9356374aSAndroid Build Coastguard Worker                                           char *tmp_buf, size_t tmp_buf_size);
351*9356374aSAndroid Build Coastguard Worker  const char *GetUncachedSymbol(const void *pc);
352*9356374aSAndroid Build Coastguard Worker
353*9356374aSAndroid Build Coastguard Worker  enum {
354*9356374aSAndroid Build Coastguard Worker    SYMBOL_BUF_SIZE = 3072,
355*9356374aSAndroid Build Coastguard Worker    TMP_BUF_SIZE = 1024,
356*9356374aSAndroid Build Coastguard Worker    SYMBOL_CACHE_LINES = 128,
357*9356374aSAndroid Build Coastguard Worker    FILE_CACHE_SIZE = 8192,
358*9356374aSAndroid Build Coastguard Worker  };
359*9356374aSAndroid Build Coastguard Worker
360*9356374aSAndroid Build Coastguard Worker  AddrMap addr_map_;
361*9356374aSAndroid Build Coastguard Worker
362*9356374aSAndroid Build Coastguard Worker  bool ok_;
363*9356374aSAndroid Build Coastguard Worker  bool addr_map_read_;
364*9356374aSAndroid Build Coastguard Worker
365*9356374aSAndroid Build Coastguard Worker  char symbol_buf_[SYMBOL_BUF_SIZE];
366*9356374aSAndroid Build Coastguard Worker  char file_cache_[FILE_CACHE_SIZE];
367*9356374aSAndroid Build Coastguard Worker
368*9356374aSAndroid Build Coastguard Worker  // tmp_buf_ will be used to store arrays of ElfW(Shdr) and ElfW(Sym)
369*9356374aSAndroid Build Coastguard Worker  // so we ensure that tmp_buf_ is properly aligned to store either.
370*9356374aSAndroid Build Coastguard Worker  alignas(16) char tmp_buf_[TMP_BUF_SIZE];
371*9356374aSAndroid Build Coastguard Worker  static_assert(alignof(ElfW(Shdr)) <= 16,
372*9356374aSAndroid Build Coastguard Worker                "alignment of tmp buf too small for Shdr");
373*9356374aSAndroid Build Coastguard Worker  static_assert(alignof(ElfW(Sym)) <= 16,
374*9356374aSAndroid Build Coastguard Worker                "alignment of tmp buf too small for Sym");
375*9356374aSAndroid Build Coastguard Worker
376*9356374aSAndroid Build Coastguard Worker  SymbolCacheLine symbol_cache_[SYMBOL_CACHE_LINES];
377*9356374aSAndroid Build Coastguard Worker};
378*9356374aSAndroid Build Coastguard Worker
379*9356374aSAndroid Build Coastguard Workerstatic std::atomic<Symbolizer *> g_cached_symbolizer;
380*9356374aSAndroid Build Coastguard Worker
381*9356374aSAndroid Build Coastguard Worker}  // namespace
382*9356374aSAndroid Build Coastguard Worker
383*9356374aSAndroid Build Coastguard Workerstatic size_t SymbolizerSize() {
384*9356374aSAndroid Build Coastguard Worker#if defined(__wasm__) || defined(__asmjs__)
385*9356374aSAndroid Build Coastguard Worker  auto pagesize = static_cast<size_t>(getpagesize());
386*9356374aSAndroid Build Coastguard Worker#else
387*9356374aSAndroid Build Coastguard Worker  auto pagesize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
388*9356374aSAndroid Build Coastguard Worker#endif
389*9356374aSAndroid Build Coastguard Worker  return ((sizeof(Symbolizer) - 1) / pagesize + 1) * pagesize;
390*9356374aSAndroid Build Coastguard Worker}
391*9356374aSAndroid Build Coastguard Worker
392*9356374aSAndroid Build Coastguard Worker// Return (and set null) g_cached_symbolized_state if it is not null.
393*9356374aSAndroid Build Coastguard Worker// Otherwise return a new symbolizer.
394*9356374aSAndroid Build Coastguard Workerstatic Symbolizer *AllocateSymbolizer() {
395*9356374aSAndroid Build Coastguard Worker  InitSigSafeArena();
396*9356374aSAndroid Build Coastguard Worker  Symbolizer *symbolizer =
397*9356374aSAndroid Build Coastguard Worker      g_cached_symbolizer.exchange(nullptr, std::memory_order_acquire);
398*9356374aSAndroid Build Coastguard Worker  if (symbolizer != nullptr) {
399*9356374aSAndroid Build Coastguard Worker    return symbolizer;
400*9356374aSAndroid Build Coastguard Worker  }
401*9356374aSAndroid Build Coastguard Worker  return new (base_internal::LowLevelAlloc::AllocWithArena(
402*9356374aSAndroid Build Coastguard Worker      SymbolizerSize(), SigSafeArena())) Symbolizer();
403*9356374aSAndroid Build Coastguard Worker}
404*9356374aSAndroid Build Coastguard Worker
405*9356374aSAndroid Build Coastguard Worker// Set g_cached_symbolize_state to s if it is null, otherwise
406*9356374aSAndroid Build Coastguard Worker// delete s.
407*9356374aSAndroid Build Coastguard Workerstatic void FreeSymbolizer(Symbolizer *s) {
408*9356374aSAndroid Build Coastguard Worker  Symbolizer *old_cached_symbolizer = nullptr;
409*9356374aSAndroid Build Coastguard Worker  if (!g_cached_symbolizer.compare_exchange_strong(old_cached_symbolizer, s,
410*9356374aSAndroid Build Coastguard Worker                                                   std::memory_order_release,
411*9356374aSAndroid Build Coastguard Worker                                                   std::memory_order_relaxed)) {
412*9356374aSAndroid Build Coastguard Worker    s->~Symbolizer();
413*9356374aSAndroid Build Coastguard Worker    base_internal::LowLevelAlloc::Free(s);
414*9356374aSAndroid Build Coastguard Worker  }
415*9356374aSAndroid Build Coastguard Worker}
416*9356374aSAndroid Build Coastguard Worker
417*9356374aSAndroid Build Coastguard WorkerSymbolizer::Symbolizer() : ok_(true), addr_map_read_(false) {
418*9356374aSAndroid Build Coastguard Worker  for (SymbolCacheLine &symbol_cache_line : symbol_cache_) {
419*9356374aSAndroid Build Coastguard Worker    for (size_t j = 0; j < ABSL_ARRAYSIZE(symbol_cache_line.name); ++j) {
420*9356374aSAndroid Build Coastguard Worker      symbol_cache_line.pc[j] = nullptr;
421*9356374aSAndroid Build Coastguard Worker      symbol_cache_line.name[j] = nullptr;
422*9356374aSAndroid Build Coastguard Worker      symbol_cache_line.age[j] = 0;
423*9356374aSAndroid Build Coastguard Worker    }
424*9356374aSAndroid Build Coastguard Worker  }
425*9356374aSAndroid Build Coastguard Worker}
426*9356374aSAndroid Build Coastguard Worker
427*9356374aSAndroid Build Coastguard WorkerSymbolizer::~Symbolizer() {
428*9356374aSAndroid Build Coastguard Worker  for (SymbolCacheLine &symbol_cache_line : symbol_cache_) {
429*9356374aSAndroid Build Coastguard Worker    for (char *s : symbol_cache_line.name) {
430*9356374aSAndroid Build Coastguard Worker      base_internal::LowLevelAlloc::Free(s);
431*9356374aSAndroid Build Coastguard Worker    }
432*9356374aSAndroid Build Coastguard Worker  }
433*9356374aSAndroid Build Coastguard Worker  ClearAddrMap();
434*9356374aSAndroid Build Coastguard Worker}
435*9356374aSAndroid Build Coastguard Worker
436*9356374aSAndroid Build Coastguard Worker// We don't use assert() since it's not guaranteed to be
437*9356374aSAndroid Build Coastguard Worker// async-signal-safe.  Instead we define a minimal assertion
438*9356374aSAndroid Build Coastguard Worker// macro. So far, we don't need pretty printing for __FILE__, etc.
439*9356374aSAndroid Build Coastguard Worker#define SAFE_ASSERT(expr) ((expr) ? static_cast<void>(0) : abort())
440*9356374aSAndroid Build Coastguard Worker
441*9356374aSAndroid Build Coastguard Worker// Read up to "count" bytes from file descriptor "fd" into the buffer
442*9356374aSAndroid Build Coastguard Worker// starting at "buf" while handling short reads and EINTR.  On
443*9356374aSAndroid Build Coastguard Worker// success, return the number of bytes read.  Otherwise, return -1.
444*9356374aSAndroid Build Coastguard Workerstatic ssize_t ReadPersistent(int fd, void *buf, size_t count) {
445*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(fd >= 0);
446*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(count <= SSIZE_MAX);
447*9356374aSAndroid Build Coastguard Worker  char *buf0 = reinterpret_cast<char *>(buf);
448*9356374aSAndroid Build Coastguard Worker  size_t num_bytes = 0;
449*9356374aSAndroid Build Coastguard Worker  while (num_bytes < count) {
450*9356374aSAndroid Build Coastguard Worker    ssize_t len;
451*9356374aSAndroid Build Coastguard Worker    NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes));
452*9356374aSAndroid Build Coastguard Worker    if (len < 0) {  // There was an error other than EINTR.
453*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "read failed: errno=%d", errno);
454*9356374aSAndroid Build Coastguard Worker      return -1;
455*9356374aSAndroid Build Coastguard Worker    }
456*9356374aSAndroid Build Coastguard Worker    if (len == 0) {  // Reached EOF.
457*9356374aSAndroid Build Coastguard Worker      break;
458*9356374aSAndroid Build Coastguard Worker    }
459*9356374aSAndroid Build Coastguard Worker    num_bytes += static_cast<size_t>(len);
460*9356374aSAndroid Build Coastguard Worker  }
461*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(num_bytes <= count);
462*9356374aSAndroid Build Coastguard Worker  return static_cast<ssize_t>(num_bytes);
463*9356374aSAndroid Build Coastguard Worker}
464*9356374aSAndroid Build Coastguard Worker
465*9356374aSAndroid Build Coastguard Worker// Read up to "count" bytes from "offset" into the buffer starting at "buf",
466*9356374aSAndroid Build Coastguard Worker// while handling short reads and EINTR.  On success, return the number of bytes
467*9356374aSAndroid Build Coastguard Worker// read.  Otherwise, return -1.
468*9356374aSAndroid Build Coastguard Workerssize_t CachingFile::ReadFromOffset(void *buf, size_t count, off_t offset) {
469*9356374aSAndroid Build Coastguard Worker  char *dst = static_cast<char *>(buf);
470*9356374aSAndroid Build Coastguard Worker  size_t read = 0;
471*9356374aSAndroid Build Coastguard Worker  while (read < count) {
472*9356374aSAndroid Build Coastguard Worker    // Look in cache first.
473*9356374aSAndroid Build Coastguard Worker    if (offset >= cache_start_ && offset < cache_limit_) {
474*9356374aSAndroid Build Coastguard Worker      const char *hit_start = &cache_[offset - cache_start_];
475*9356374aSAndroid Build Coastguard Worker      const size_t n =
476*9356374aSAndroid Build Coastguard Worker          std::min(count - read, static_cast<size_t>(cache_limit_ - offset));
477*9356374aSAndroid Build Coastguard Worker      memcpy(dst, hit_start, n);
478*9356374aSAndroid Build Coastguard Worker      dst += n;
479*9356374aSAndroid Build Coastguard Worker      read += static_cast<size_t>(n);
480*9356374aSAndroid Build Coastguard Worker      offset += static_cast<off_t>(n);
481*9356374aSAndroid Build Coastguard Worker      continue;
482*9356374aSAndroid Build Coastguard Worker    }
483*9356374aSAndroid Build Coastguard Worker
484*9356374aSAndroid Build Coastguard Worker    cache_start_ = 0;
485*9356374aSAndroid Build Coastguard Worker    cache_limit_ = 0;
486*9356374aSAndroid Build Coastguard Worker    ssize_t n = pread(fd_, cache_, cache_size_, offset);
487*9356374aSAndroid Build Coastguard Worker    if (n < 0) {
488*9356374aSAndroid Build Coastguard Worker      if (errno == EINTR) {
489*9356374aSAndroid Build Coastguard Worker        continue;
490*9356374aSAndroid Build Coastguard Worker      }
491*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "read failed: errno=%d", errno);
492*9356374aSAndroid Build Coastguard Worker      return -1;
493*9356374aSAndroid Build Coastguard Worker    }
494*9356374aSAndroid Build Coastguard Worker    if (n == 0) {  // Reached EOF.
495*9356374aSAndroid Build Coastguard Worker      break;
496*9356374aSAndroid Build Coastguard Worker    }
497*9356374aSAndroid Build Coastguard Worker
498*9356374aSAndroid Build Coastguard Worker    cache_start_ = offset;
499*9356374aSAndroid Build Coastguard Worker    cache_limit_ = offset + static_cast<off_t>(n);
500*9356374aSAndroid Build Coastguard Worker    // Next iteration will copy from cache into dst.
501*9356374aSAndroid Build Coastguard Worker  }
502*9356374aSAndroid Build Coastguard Worker  return static_cast<ssize_t>(read);
503*9356374aSAndroid Build Coastguard Worker}
504*9356374aSAndroid Build Coastguard Worker
505*9356374aSAndroid Build Coastguard Worker// Try reading exactly "count" bytes from "offset" bytes into the buffer
506*9356374aSAndroid Build Coastguard Worker// starting at "buf" while handling short reads and EINTR.  On success, return
507*9356374aSAndroid Build Coastguard Worker// true. Otherwise, return false.
508*9356374aSAndroid Build Coastguard Workerbool CachingFile::ReadFromOffsetExact(void *buf, size_t count, off_t offset) {
509*9356374aSAndroid Build Coastguard Worker  ssize_t len = ReadFromOffset(buf, count, offset);
510*9356374aSAndroid Build Coastguard Worker  return len >= 0 && static_cast<size_t>(len) == count;
511*9356374aSAndroid Build Coastguard Worker}
512*9356374aSAndroid Build Coastguard Worker
513*9356374aSAndroid Build Coastguard Worker// Returns elf_header.e_type if the file pointed by fd is an ELF binary.
514*9356374aSAndroid Build Coastguard Workerstatic int FileGetElfType(CachingFile *file) {
515*9356374aSAndroid Build Coastguard Worker  ElfW(Ehdr) elf_header;
516*9356374aSAndroid Build Coastguard Worker  if (!file->ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) {
517*9356374aSAndroid Build Coastguard Worker    return -1;
518*9356374aSAndroid Build Coastguard Worker  }
519*9356374aSAndroid Build Coastguard Worker  if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) {
520*9356374aSAndroid Build Coastguard Worker    return -1;
521*9356374aSAndroid Build Coastguard Worker  }
522*9356374aSAndroid Build Coastguard Worker  return elf_header.e_type;
523*9356374aSAndroid Build Coastguard Worker}
524*9356374aSAndroid Build Coastguard Worker
525*9356374aSAndroid Build Coastguard Worker// Read the section headers in the given ELF binary, and if a section
526*9356374aSAndroid Build Coastguard Worker// of the specified type is found, set the output to this section header
527*9356374aSAndroid Build Coastguard Worker// and return true.  Otherwise, return false.
528*9356374aSAndroid Build Coastguard Worker// To keep stack consumption low, we would like this function to not get
529*9356374aSAndroid Build Coastguard Worker// inlined.
530*9356374aSAndroid Build Coastguard Workerstatic ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(
531*9356374aSAndroid Build Coastguard Worker    CachingFile *file, ElfW(Half) sh_num, const off_t sh_offset,
532*9356374aSAndroid Build Coastguard Worker    ElfW(Word) type, ElfW(Shdr) * out, char *tmp_buf, size_t tmp_buf_size) {
533*9356374aSAndroid Build Coastguard Worker  ElfW(Shdr) *buf = reinterpret_cast<ElfW(Shdr) *>(tmp_buf);
534*9356374aSAndroid Build Coastguard Worker  const size_t buf_entries = tmp_buf_size / sizeof(buf[0]);
535*9356374aSAndroid Build Coastguard Worker  const size_t buf_bytes = buf_entries * sizeof(buf[0]);
536*9356374aSAndroid Build Coastguard Worker
537*9356374aSAndroid Build Coastguard Worker  for (size_t i = 0; static_cast<int>(i) < sh_num;) {
538*9356374aSAndroid Build Coastguard Worker    const size_t num_bytes_left =
539*9356374aSAndroid Build Coastguard Worker        (static_cast<size_t>(sh_num) - i) * sizeof(buf[0]);
540*9356374aSAndroid Build Coastguard Worker    const size_t num_bytes_to_read =
541*9356374aSAndroid Build Coastguard Worker        (buf_bytes > num_bytes_left) ? num_bytes_left : buf_bytes;
542*9356374aSAndroid Build Coastguard Worker    const off_t offset = sh_offset + static_cast<off_t>(i * sizeof(buf[0]));
543*9356374aSAndroid Build Coastguard Worker    const ssize_t len = file->ReadFromOffset(buf, num_bytes_to_read, offset);
544*9356374aSAndroid Build Coastguard Worker    if (len < 0) {
545*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(
546*9356374aSAndroid Build Coastguard Worker          WARNING,
547*9356374aSAndroid Build Coastguard Worker          "Reading %zu bytes from offset %ju returned %zd which is negative.",
548*9356374aSAndroid Build Coastguard Worker          num_bytes_to_read, static_cast<intmax_t>(offset), len);
549*9356374aSAndroid Build Coastguard Worker      return false;
550*9356374aSAndroid Build Coastguard Worker    }
551*9356374aSAndroid Build Coastguard Worker    if (static_cast<size_t>(len) % sizeof(buf[0]) != 0) {
552*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(
553*9356374aSAndroid Build Coastguard Worker          WARNING,
554*9356374aSAndroid Build Coastguard Worker          "Reading %zu bytes from offset %jd returned %zd which is not a "
555*9356374aSAndroid Build Coastguard Worker          "multiple of %zu.",
556*9356374aSAndroid Build Coastguard Worker          num_bytes_to_read, static_cast<intmax_t>(offset), len,
557*9356374aSAndroid Build Coastguard Worker          sizeof(buf[0]));
558*9356374aSAndroid Build Coastguard Worker      return false;
559*9356374aSAndroid Build Coastguard Worker    }
560*9356374aSAndroid Build Coastguard Worker    const size_t num_headers_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
561*9356374aSAndroid Build Coastguard Worker    SAFE_ASSERT(num_headers_in_buf <= buf_entries);
562*9356374aSAndroid Build Coastguard Worker    for (size_t j = 0; j < num_headers_in_buf; ++j) {
563*9356374aSAndroid Build Coastguard Worker      if (buf[j].sh_type == type) {
564*9356374aSAndroid Build Coastguard Worker        *out = buf[j];
565*9356374aSAndroid Build Coastguard Worker        return true;
566*9356374aSAndroid Build Coastguard Worker      }
567*9356374aSAndroid Build Coastguard Worker    }
568*9356374aSAndroid Build Coastguard Worker    i += num_headers_in_buf;
569*9356374aSAndroid Build Coastguard Worker  }
570*9356374aSAndroid Build Coastguard Worker  return false;
571*9356374aSAndroid Build Coastguard Worker}
572*9356374aSAndroid Build Coastguard Worker
573*9356374aSAndroid Build Coastguard Worker// There is no particular reason to limit section name to 63 characters,
574*9356374aSAndroid Build Coastguard Worker// but there has (as yet) been no need for anything longer either.
575*9356374aSAndroid Build Coastguard Workerconst int kMaxSectionNameLen = 64;
576*9356374aSAndroid Build Coastguard Worker
577*9356374aSAndroid Build Coastguard Worker// Small cache to use for miscellaneous file reads.
578*9356374aSAndroid Build Coastguard Workerconst int kSmallFileCacheSize = 100;
579*9356374aSAndroid Build Coastguard Worker
580*9356374aSAndroid Build Coastguard Workerbool ForEachSection(int fd,
581*9356374aSAndroid Build Coastguard Worker                    const std::function<bool(absl::string_view name,
582*9356374aSAndroid Build Coastguard Worker                                             const ElfW(Shdr) &)> &callback) {
583*9356374aSAndroid Build Coastguard Worker  char buf[kSmallFileCacheSize];
584*9356374aSAndroid Build Coastguard Worker  CachingFile file(fd, buf, sizeof(buf));
585*9356374aSAndroid Build Coastguard Worker
586*9356374aSAndroid Build Coastguard Worker  ElfW(Ehdr) elf_header;
587*9356374aSAndroid Build Coastguard Worker  if (!file.ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) {
588*9356374aSAndroid Build Coastguard Worker    return false;
589*9356374aSAndroid Build Coastguard Worker  }
590*9356374aSAndroid Build Coastguard Worker
591*9356374aSAndroid Build Coastguard Worker  // Technically it can be larger, but in practice this never happens.
592*9356374aSAndroid Build Coastguard Worker  if (elf_header.e_shentsize != sizeof(ElfW(Shdr))) {
593*9356374aSAndroid Build Coastguard Worker    return false;
594*9356374aSAndroid Build Coastguard Worker  }
595*9356374aSAndroid Build Coastguard Worker
596*9356374aSAndroid Build Coastguard Worker  ElfW(Shdr) shstrtab;
597*9356374aSAndroid Build Coastguard Worker  off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +
598*9356374aSAndroid Build Coastguard Worker                          elf_header.e_shentsize * elf_header.e_shstrndx;
599*9356374aSAndroid Build Coastguard Worker  if (!file.ReadFromOffsetExact(&shstrtab, sizeof(shstrtab), shstrtab_offset)) {
600*9356374aSAndroid Build Coastguard Worker    return false;
601*9356374aSAndroid Build Coastguard Worker  }
602*9356374aSAndroid Build Coastguard Worker
603*9356374aSAndroid Build Coastguard Worker  for (int i = 0; i < elf_header.e_shnum; ++i) {
604*9356374aSAndroid Build Coastguard Worker    ElfW(Shdr) out;
605*9356374aSAndroid Build Coastguard Worker    off_t section_header_offset =
606*9356374aSAndroid Build Coastguard Worker        static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i;
607*9356374aSAndroid Build Coastguard Worker    if (!file.ReadFromOffsetExact(&out, sizeof(out), section_header_offset)) {
608*9356374aSAndroid Build Coastguard Worker      return false;
609*9356374aSAndroid Build Coastguard Worker    }
610*9356374aSAndroid Build Coastguard Worker    off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out.sh_name;
611*9356374aSAndroid Build Coastguard Worker    char header_name[kMaxSectionNameLen];
612*9356374aSAndroid Build Coastguard Worker    ssize_t n_read =
613*9356374aSAndroid Build Coastguard Worker        file.ReadFromOffset(&header_name, kMaxSectionNameLen, name_offset);
614*9356374aSAndroid Build Coastguard Worker    if (n_read < 0) {
615*9356374aSAndroid Build Coastguard Worker      return false;
616*9356374aSAndroid Build Coastguard Worker    } else if (n_read > kMaxSectionNameLen) {
617*9356374aSAndroid Build Coastguard Worker      // Long read?
618*9356374aSAndroid Build Coastguard Worker      return false;
619*9356374aSAndroid Build Coastguard Worker    }
620*9356374aSAndroid Build Coastguard Worker
621*9356374aSAndroid Build Coastguard Worker    absl::string_view name(header_name,
622*9356374aSAndroid Build Coastguard Worker                           strnlen(header_name, static_cast<size_t>(n_read)));
623*9356374aSAndroid Build Coastguard Worker    if (!callback(name, out)) {
624*9356374aSAndroid Build Coastguard Worker      break;
625*9356374aSAndroid Build Coastguard Worker    }
626*9356374aSAndroid Build Coastguard Worker  }
627*9356374aSAndroid Build Coastguard Worker  return true;
628*9356374aSAndroid Build Coastguard Worker}
629*9356374aSAndroid Build Coastguard Worker
630*9356374aSAndroid Build Coastguard Worker// name_len should include terminating '\0'.
631*9356374aSAndroid Build Coastguard Workerbool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
632*9356374aSAndroid Build Coastguard Worker                            ElfW(Shdr) * out) {
633*9356374aSAndroid Build Coastguard Worker  char header_name[kMaxSectionNameLen];
634*9356374aSAndroid Build Coastguard Worker  if (sizeof(header_name) < name_len) {
635*9356374aSAndroid Build Coastguard Worker    ABSL_RAW_LOG(WARNING,
636*9356374aSAndroid Build Coastguard Worker                 "Section name '%s' is too long (%zu); "
637*9356374aSAndroid Build Coastguard Worker                 "section will not be found (even if present).",
638*9356374aSAndroid Build Coastguard Worker                 name, name_len);
639*9356374aSAndroid Build Coastguard Worker    // No point in even trying.
640*9356374aSAndroid Build Coastguard Worker    return false;
641*9356374aSAndroid Build Coastguard Worker  }
642*9356374aSAndroid Build Coastguard Worker
643*9356374aSAndroid Build Coastguard Worker  char buf[kSmallFileCacheSize];
644*9356374aSAndroid Build Coastguard Worker  CachingFile file(fd, buf, sizeof(buf));
645*9356374aSAndroid Build Coastguard Worker  ElfW(Ehdr) elf_header;
646*9356374aSAndroid Build Coastguard Worker  if (!file.ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) {
647*9356374aSAndroid Build Coastguard Worker    return false;
648*9356374aSAndroid Build Coastguard Worker  }
649*9356374aSAndroid Build Coastguard Worker
650*9356374aSAndroid Build Coastguard Worker  // Technically it can be larger, but in practice this never happens.
651*9356374aSAndroid Build Coastguard Worker  if (elf_header.e_shentsize != sizeof(ElfW(Shdr))) {
652*9356374aSAndroid Build Coastguard Worker    return false;
653*9356374aSAndroid Build Coastguard Worker  }
654*9356374aSAndroid Build Coastguard Worker
655*9356374aSAndroid Build Coastguard Worker  ElfW(Shdr) shstrtab;
656*9356374aSAndroid Build Coastguard Worker  off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +
657*9356374aSAndroid Build Coastguard Worker                          elf_header.e_shentsize * elf_header.e_shstrndx;
658*9356374aSAndroid Build Coastguard Worker  if (!file.ReadFromOffsetExact(&shstrtab, sizeof(shstrtab), shstrtab_offset)) {
659*9356374aSAndroid Build Coastguard Worker    return false;
660*9356374aSAndroid Build Coastguard Worker  }
661*9356374aSAndroid Build Coastguard Worker
662*9356374aSAndroid Build Coastguard Worker  for (int i = 0; i < elf_header.e_shnum; ++i) {
663*9356374aSAndroid Build Coastguard Worker    off_t section_header_offset =
664*9356374aSAndroid Build Coastguard Worker        static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i;
665*9356374aSAndroid Build Coastguard Worker    if (!file.ReadFromOffsetExact(out, sizeof(*out), section_header_offset)) {
666*9356374aSAndroid Build Coastguard Worker      return false;
667*9356374aSAndroid Build Coastguard Worker    }
668*9356374aSAndroid Build Coastguard Worker    off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out->sh_name;
669*9356374aSAndroid Build Coastguard Worker    ssize_t n_read = file.ReadFromOffset(&header_name, name_len, name_offset);
670*9356374aSAndroid Build Coastguard Worker    if (n_read < 0) {
671*9356374aSAndroid Build Coastguard Worker      return false;
672*9356374aSAndroid Build Coastguard Worker    } else if (static_cast<size_t>(n_read) != name_len) {
673*9356374aSAndroid Build Coastguard Worker      // Short read -- name could be at end of file.
674*9356374aSAndroid Build Coastguard Worker      continue;
675*9356374aSAndroid Build Coastguard Worker    }
676*9356374aSAndroid Build Coastguard Worker    if (memcmp(header_name, name, name_len) == 0) {
677*9356374aSAndroid Build Coastguard Worker      return true;
678*9356374aSAndroid Build Coastguard Worker    }
679*9356374aSAndroid Build Coastguard Worker  }
680*9356374aSAndroid Build Coastguard Worker  return false;
681*9356374aSAndroid Build Coastguard Worker}
682*9356374aSAndroid Build Coastguard Worker
683*9356374aSAndroid Build Coastguard Worker// Compare symbols at in the same address.
684*9356374aSAndroid Build Coastguard Worker// Return true if we should pick symbol1.
685*9356374aSAndroid Build Coastguard Workerstatic bool ShouldPickFirstSymbol(const ElfW(Sym) & symbol1,
686*9356374aSAndroid Build Coastguard Worker                                  const ElfW(Sym) & symbol2) {
687*9356374aSAndroid Build Coastguard Worker  // If one of the symbols is weak and the other is not, pick the one
688*9356374aSAndroid Build Coastguard Worker  // this is not a weak symbol.
689*9356374aSAndroid Build Coastguard Worker  char bind1 = ELF_ST_BIND(symbol1.st_info);
690*9356374aSAndroid Build Coastguard Worker  char bind2 = ELF_ST_BIND(symbol1.st_info);
691*9356374aSAndroid Build Coastguard Worker  if (bind1 == STB_WEAK && bind2 != STB_WEAK) return false;
692*9356374aSAndroid Build Coastguard Worker  if (bind2 == STB_WEAK && bind1 != STB_WEAK) return true;
693*9356374aSAndroid Build Coastguard Worker
694*9356374aSAndroid Build Coastguard Worker  // If one of the symbols has zero size and the other is not, pick the
695*9356374aSAndroid Build Coastguard Worker  // one that has non-zero size.
696*9356374aSAndroid Build Coastguard Worker  if (symbol1.st_size != 0 && symbol2.st_size == 0) {
697*9356374aSAndroid Build Coastguard Worker    return true;
698*9356374aSAndroid Build Coastguard Worker  }
699*9356374aSAndroid Build Coastguard Worker  if (symbol1.st_size == 0 && symbol2.st_size != 0) {
700*9356374aSAndroid Build Coastguard Worker    return false;
701*9356374aSAndroid Build Coastguard Worker  }
702*9356374aSAndroid Build Coastguard Worker
703*9356374aSAndroid Build Coastguard Worker  // If one of the symbols has no type and the other is not, pick the
704*9356374aSAndroid Build Coastguard Worker  // one that has a type.
705*9356374aSAndroid Build Coastguard Worker  char type1 = ELF_ST_TYPE(symbol1.st_info);
706*9356374aSAndroid Build Coastguard Worker  char type2 = ELF_ST_TYPE(symbol1.st_info);
707*9356374aSAndroid Build Coastguard Worker  if (type1 != STT_NOTYPE && type2 == STT_NOTYPE) {
708*9356374aSAndroid Build Coastguard Worker    return true;
709*9356374aSAndroid Build Coastguard Worker  }
710*9356374aSAndroid Build Coastguard Worker  if (type1 == STT_NOTYPE && type2 != STT_NOTYPE) {
711*9356374aSAndroid Build Coastguard Worker    return false;
712*9356374aSAndroid Build Coastguard Worker  }
713*9356374aSAndroid Build Coastguard Worker
714*9356374aSAndroid Build Coastguard Worker  // Pick the first one, if we still cannot decide.
715*9356374aSAndroid Build Coastguard Worker  return true;
716*9356374aSAndroid Build Coastguard Worker}
717*9356374aSAndroid Build Coastguard Worker
718*9356374aSAndroid Build Coastguard Worker// Return true if an address is inside a section.
719*9356374aSAndroid Build Coastguard Workerstatic bool InSection(const void *address, ptrdiff_t relocation,
720*9356374aSAndroid Build Coastguard Worker                      const ElfW(Shdr) * section) {
721*9356374aSAndroid Build Coastguard Worker  const char *start = reinterpret_cast<const char *>(
722*9356374aSAndroid Build Coastguard Worker      section->sh_addr + static_cast<ElfW(Addr)>(relocation));
723*9356374aSAndroid Build Coastguard Worker  size_t size = static_cast<size_t>(section->sh_size);
724*9356374aSAndroid Build Coastguard Worker  return start <= address && address < (start + size);
725*9356374aSAndroid Build Coastguard Worker}
726*9356374aSAndroid Build Coastguard Worker
727*9356374aSAndroid Build Coastguard Workerstatic const char *ComputeOffset(const char *base, ptrdiff_t offset) {
728*9356374aSAndroid Build Coastguard Worker  // Note: cast to intptr_t to avoid undefined behavior when base evaluates to
729*9356374aSAndroid Build Coastguard Worker  // zero and offset is non-zero.
730*9356374aSAndroid Build Coastguard Worker  return reinterpret_cast<const char *>(reinterpret_cast<intptr_t>(base) +
731*9356374aSAndroid Build Coastguard Worker                                        offset);
732*9356374aSAndroid Build Coastguard Worker}
733*9356374aSAndroid Build Coastguard Worker
734*9356374aSAndroid Build Coastguard Worker// Read a symbol table and look for the symbol containing the
735*9356374aSAndroid Build Coastguard Worker// pc. Iterate over symbols in a symbol table and look for the symbol
736*9356374aSAndroid Build Coastguard Worker// containing "pc".  If the symbol is found, and its name fits in
737*9356374aSAndroid Build Coastguard Worker// out_size, the name is written into out and SYMBOL_FOUND is returned.
738*9356374aSAndroid Build Coastguard Worker// If the name does not fit, truncated name is written into out,
739*9356374aSAndroid Build Coastguard Worker// and SYMBOL_TRUNCATED is returned. Out is NUL-terminated.
740*9356374aSAndroid Build Coastguard Worker// If the symbol is not found, SYMBOL_NOT_FOUND is returned;
741*9356374aSAndroid Build Coastguard Worker// To keep stack consumption low, we would like this function to not get
742*9356374aSAndroid Build Coastguard Worker// inlined.
743*9356374aSAndroid Build Coastguard Workerstatic ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
744*9356374aSAndroid Build Coastguard Worker    const void *const pc, CachingFile *file, char *out, size_t out_size,
745*9356374aSAndroid Build Coastguard Worker    ptrdiff_t relocation, const ElfW(Shdr) * strtab, const ElfW(Shdr) * symtab,
746*9356374aSAndroid Build Coastguard Worker    const ElfW(Shdr) * opd, char *tmp_buf, size_t tmp_buf_size) {
747*9356374aSAndroid Build Coastguard Worker  if (symtab == nullptr) {
748*9356374aSAndroid Build Coastguard Worker    return SYMBOL_NOT_FOUND;
749*9356374aSAndroid Build Coastguard Worker  }
750*9356374aSAndroid Build Coastguard Worker
751*9356374aSAndroid Build Coastguard Worker  // Read multiple symbols at once to save read() calls.
752*9356374aSAndroid Build Coastguard Worker  ElfW(Sym) *buf = reinterpret_cast<ElfW(Sym) *>(tmp_buf);
753*9356374aSAndroid Build Coastguard Worker  const size_t buf_entries = tmp_buf_size / sizeof(buf[0]);
754*9356374aSAndroid Build Coastguard Worker
755*9356374aSAndroid Build Coastguard Worker  const size_t num_symbols = symtab->sh_size / symtab->sh_entsize;
756*9356374aSAndroid Build Coastguard Worker
757*9356374aSAndroid Build Coastguard Worker  // On platforms using an .opd section (PowerPC & IA64), a function symbol
758*9356374aSAndroid Build Coastguard Worker  // has the address of a function descriptor, which contains the real
759*9356374aSAndroid Build Coastguard Worker  // starting address.  However, we do not always want to use the real
760*9356374aSAndroid Build Coastguard Worker  // starting address because we sometimes want to symbolize a function
761*9356374aSAndroid Build Coastguard Worker  // pointer into the .opd section, e.g. FindSymbol(&foo,...).
762*9356374aSAndroid Build Coastguard Worker  const bool pc_in_opd = kPlatformUsesOPDSections && opd != nullptr &&
763*9356374aSAndroid Build Coastguard Worker                         InSection(pc, relocation, opd);
764*9356374aSAndroid Build Coastguard Worker  const bool deref_function_descriptor_pointer =
765*9356374aSAndroid Build Coastguard Worker      kPlatformUsesOPDSections && opd != nullptr && !pc_in_opd;
766*9356374aSAndroid Build Coastguard Worker
767*9356374aSAndroid Build Coastguard Worker  ElfW(Sym) best_match;
768*9356374aSAndroid Build Coastguard Worker  SafeMemZero(&best_match, sizeof(best_match));
769*9356374aSAndroid Build Coastguard Worker  bool found_match = false;
770*9356374aSAndroid Build Coastguard Worker  for (size_t i = 0; i < num_symbols;) {
771*9356374aSAndroid Build Coastguard Worker    off_t offset =
772*9356374aSAndroid Build Coastguard Worker        static_cast<off_t>(symtab->sh_offset + i * symtab->sh_entsize);
773*9356374aSAndroid Build Coastguard Worker    const size_t num_remaining_symbols = num_symbols - i;
774*9356374aSAndroid Build Coastguard Worker    const size_t entries_in_chunk =
775*9356374aSAndroid Build Coastguard Worker        std::min(num_remaining_symbols, buf_entries);
776*9356374aSAndroid Build Coastguard Worker    const size_t bytes_in_chunk = entries_in_chunk * sizeof(buf[0]);
777*9356374aSAndroid Build Coastguard Worker    const ssize_t len = file->ReadFromOffset(buf, bytes_in_chunk, offset);
778*9356374aSAndroid Build Coastguard Worker    SAFE_ASSERT(len >= 0);
779*9356374aSAndroid Build Coastguard Worker    SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
780*9356374aSAndroid Build Coastguard Worker    const size_t num_symbols_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
781*9356374aSAndroid Build Coastguard Worker    SAFE_ASSERT(num_symbols_in_buf <= entries_in_chunk);
782*9356374aSAndroid Build Coastguard Worker    for (size_t j = 0; j < num_symbols_in_buf; ++j) {
783*9356374aSAndroid Build Coastguard Worker      const ElfW(Sym) &symbol = buf[j];
784*9356374aSAndroid Build Coastguard Worker
785*9356374aSAndroid Build Coastguard Worker      // For a DSO, a symbol address is relocated by the loading address.
786*9356374aSAndroid Build Coastguard Worker      // We keep the original address for opd redirection below.
787*9356374aSAndroid Build Coastguard Worker      const char *const original_start_address =
788*9356374aSAndroid Build Coastguard Worker          reinterpret_cast<const char *>(symbol.st_value);
789*9356374aSAndroid Build Coastguard Worker      const char *start_address =
790*9356374aSAndroid Build Coastguard Worker          ComputeOffset(original_start_address, relocation);
791*9356374aSAndroid Build Coastguard Worker
792*9356374aSAndroid Build Coastguard Worker#ifdef __arm__
793*9356374aSAndroid Build Coastguard Worker      // ARM functions are always aligned to multiples of two bytes; the
794*9356374aSAndroid Build Coastguard Worker      // lowest-order bit in start_address is ignored by the CPU and indicates
795*9356374aSAndroid Build Coastguard Worker      // whether the function contains ARM (0) or Thumb (1) code. We don't care
796*9356374aSAndroid Build Coastguard Worker      // about what encoding is being used; we just want the real start address
797*9356374aSAndroid Build Coastguard Worker      // of the function.
798*9356374aSAndroid Build Coastguard Worker      start_address = reinterpret_cast<const char *>(
799*9356374aSAndroid Build Coastguard Worker          reinterpret_cast<uintptr_t>(start_address) & ~1u);
800*9356374aSAndroid Build Coastguard Worker#endif
801*9356374aSAndroid Build Coastguard Worker
802*9356374aSAndroid Build Coastguard Worker      if (deref_function_descriptor_pointer &&
803*9356374aSAndroid Build Coastguard Worker          InSection(original_start_address, /*relocation=*/0, opd)) {
804*9356374aSAndroid Build Coastguard Worker        // The opd section is mapped into memory.  Just dereference
805*9356374aSAndroid Build Coastguard Worker        // start_address to get the first double word, which points to the
806*9356374aSAndroid Build Coastguard Worker        // function entry.
807*9356374aSAndroid Build Coastguard Worker        start_address = *reinterpret_cast<const char *const *>(start_address);
808*9356374aSAndroid Build Coastguard Worker      }
809*9356374aSAndroid Build Coastguard Worker
810*9356374aSAndroid Build Coastguard Worker      // If pc is inside the .opd section, it points to a function descriptor.
811*9356374aSAndroid Build Coastguard Worker      const size_t size = pc_in_opd ? kFunctionDescriptorSize : symbol.st_size;
812*9356374aSAndroid Build Coastguard Worker      const void *const end_address =
813*9356374aSAndroid Build Coastguard Worker          ComputeOffset(start_address, static_cast<ptrdiff_t>(size));
814*9356374aSAndroid Build Coastguard Worker      if (symbol.st_value != 0 &&  // Skip null value symbols.
815*9356374aSAndroid Build Coastguard Worker          symbol.st_shndx != 0 &&  // Skip undefined symbols.
816*9356374aSAndroid Build Coastguard Worker#ifdef STT_TLS
817*9356374aSAndroid Build Coastguard Worker          ELF_ST_TYPE(symbol.st_info) != STT_TLS &&  // Skip thread-local data.
818*9356374aSAndroid Build Coastguard Worker#endif                                               // STT_TLS
819*9356374aSAndroid Build Coastguard Worker          ((start_address <= pc && pc < end_address) ||
820*9356374aSAndroid Build Coastguard Worker           (start_address == pc && pc == end_address))) {
821*9356374aSAndroid Build Coastguard Worker        if (!found_match || ShouldPickFirstSymbol(symbol, best_match)) {
822*9356374aSAndroid Build Coastguard Worker          found_match = true;
823*9356374aSAndroid Build Coastguard Worker          best_match = symbol;
824*9356374aSAndroid Build Coastguard Worker        }
825*9356374aSAndroid Build Coastguard Worker      }
826*9356374aSAndroid Build Coastguard Worker    }
827*9356374aSAndroid Build Coastguard Worker    i += num_symbols_in_buf;
828*9356374aSAndroid Build Coastguard Worker  }
829*9356374aSAndroid Build Coastguard Worker
830*9356374aSAndroid Build Coastguard Worker  if (found_match) {
831*9356374aSAndroid Build Coastguard Worker    const off_t off =
832*9356374aSAndroid Build Coastguard Worker        static_cast<off_t>(strtab->sh_offset) + best_match.st_name;
833*9356374aSAndroid Build Coastguard Worker    const ssize_t n_read = file->ReadFromOffset(out, out_size, off);
834*9356374aSAndroid Build Coastguard Worker    if (n_read <= 0) {
835*9356374aSAndroid Build Coastguard Worker      // This should never happen.
836*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING,
837*9356374aSAndroid Build Coastguard Worker                   "Unable to read from fd %d at offset %lld: n_read = %zd",
838*9356374aSAndroid Build Coastguard Worker                   file->fd(), static_cast<long long>(off), n_read);
839*9356374aSAndroid Build Coastguard Worker      return SYMBOL_NOT_FOUND;
840*9356374aSAndroid Build Coastguard Worker    }
841*9356374aSAndroid Build Coastguard Worker    ABSL_RAW_CHECK(static_cast<size_t>(n_read) <= out_size,
842*9356374aSAndroid Build Coastguard Worker                   "ReadFromOffset read too much data.");
843*9356374aSAndroid Build Coastguard Worker
844*9356374aSAndroid Build Coastguard Worker    // strtab->sh_offset points into .strtab-like section that contains
845*9356374aSAndroid Build Coastguard Worker    // NUL-terminated strings: '\0foo\0barbaz\0...".
846*9356374aSAndroid Build Coastguard Worker    //
847*9356374aSAndroid Build Coastguard Worker    // sh_offset+st_name points to the start of symbol name, but we don't know
848*9356374aSAndroid Build Coastguard Worker    // how long the symbol is, so we try to read as much as we have space for,
849*9356374aSAndroid Build Coastguard Worker    // and usually over-read (i.e. there is a NUL somewhere before n_read).
850*9356374aSAndroid Build Coastguard Worker    if (memchr(out, '\0', static_cast<size_t>(n_read)) == nullptr) {
851*9356374aSAndroid Build Coastguard Worker      // Either out_size was too small (n_read == out_size and no NUL), or
852*9356374aSAndroid Build Coastguard Worker      // we tried to read past the EOF (n_read < out_size) and .strtab is
853*9356374aSAndroid Build Coastguard Worker      // corrupt (missing terminating NUL; should never happen for valid ELF).
854*9356374aSAndroid Build Coastguard Worker      out[n_read - 1] = '\0';
855*9356374aSAndroid Build Coastguard Worker      return SYMBOL_TRUNCATED;
856*9356374aSAndroid Build Coastguard Worker    }
857*9356374aSAndroid Build Coastguard Worker    return SYMBOL_FOUND;
858*9356374aSAndroid Build Coastguard Worker  }
859*9356374aSAndroid Build Coastguard Worker
860*9356374aSAndroid Build Coastguard Worker  return SYMBOL_NOT_FOUND;
861*9356374aSAndroid Build Coastguard Worker}
862*9356374aSAndroid Build Coastguard Worker
863*9356374aSAndroid Build Coastguard Worker// Get the symbol name of "pc" from the file pointed by "fd".  Process
864*9356374aSAndroid Build Coastguard Worker// both regular and dynamic symbol tables if necessary.
865*9356374aSAndroid Build Coastguard Worker// See FindSymbol() comment for description of return value.
866*9356374aSAndroid Build Coastguard WorkerFindSymbolResult Symbolizer::GetSymbolFromObjectFile(
867*9356374aSAndroid Build Coastguard Worker    const ObjFile &obj, const void *const pc, const ptrdiff_t relocation,
868*9356374aSAndroid Build Coastguard Worker    char *out, size_t out_size, char *tmp_buf, size_t tmp_buf_size) {
869*9356374aSAndroid Build Coastguard Worker  ElfW(Shdr) symtab;
870*9356374aSAndroid Build Coastguard Worker  ElfW(Shdr) strtab;
871*9356374aSAndroid Build Coastguard Worker  ElfW(Shdr) opd;
872*9356374aSAndroid Build Coastguard Worker  ElfW(Shdr) *opd_ptr = nullptr;
873*9356374aSAndroid Build Coastguard Worker
874*9356374aSAndroid Build Coastguard Worker  // On platforms using an .opd sections for function descriptor, read
875*9356374aSAndroid Build Coastguard Worker  // the section header.  The .opd section is in data segment and should be
876*9356374aSAndroid Build Coastguard Worker  // loaded but we check that it is mapped just to be extra careful.
877*9356374aSAndroid Build Coastguard Worker  if (kPlatformUsesOPDSections) {
878*9356374aSAndroid Build Coastguard Worker    if (GetSectionHeaderByName(obj.fd, kOpdSectionName,
879*9356374aSAndroid Build Coastguard Worker                               sizeof(kOpdSectionName) - 1, &opd) &&
880*9356374aSAndroid Build Coastguard Worker        FindObjFile(reinterpret_cast<const char *>(opd.sh_addr) + relocation,
881*9356374aSAndroid Build Coastguard Worker                    opd.sh_size) != nullptr) {
882*9356374aSAndroid Build Coastguard Worker      opd_ptr = &opd;
883*9356374aSAndroid Build Coastguard Worker    } else {
884*9356374aSAndroid Build Coastguard Worker      return SYMBOL_NOT_FOUND;
885*9356374aSAndroid Build Coastguard Worker    }
886*9356374aSAndroid Build Coastguard Worker  }
887*9356374aSAndroid Build Coastguard Worker
888*9356374aSAndroid Build Coastguard Worker  CachingFile file(obj.fd, file_cache_, sizeof(file_cache_));
889*9356374aSAndroid Build Coastguard Worker
890*9356374aSAndroid Build Coastguard Worker  // Consult a regular symbol table, then fall back to the dynamic symbol table.
891*9356374aSAndroid Build Coastguard Worker  for (const auto symbol_table_type : {SHT_SYMTAB, SHT_DYNSYM}) {
892*9356374aSAndroid Build Coastguard Worker    if (!GetSectionHeaderByType(&file, obj.elf_header.e_shnum,
893*9356374aSAndroid Build Coastguard Worker                                static_cast<off_t>(obj.elf_header.e_shoff),
894*9356374aSAndroid Build Coastguard Worker                                static_cast<ElfW(Word)>(symbol_table_type),
895*9356374aSAndroid Build Coastguard Worker                                &symtab, tmp_buf, tmp_buf_size)) {
896*9356374aSAndroid Build Coastguard Worker      continue;
897*9356374aSAndroid Build Coastguard Worker    }
898*9356374aSAndroid Build Coastguard Worker    if (!file.ReadFromOffsetExact(
899*9356374aSAndroid Build Coastguard Worker            &strtab, sizeof(strtab),
900*9356374aSAndroid Build Coastguard Worker            static_cast<off_t>(obj.elf_header.e_shoff +
901*9356374aSAndroid Build Coastguard Worker                               symtab.sh_link * sizeof(symtab)))) {
902*9356374aSAndroid Build Coastguard Worker      continue;
903*9356374aSAndroid Build Coastguard Worker    }
904*9356374aSAndroid Build Coastguard Worker    const FindSymbolResult rc =
905*9356374aSAndroid Build Coastguard Worker        FindSymbol(pc, &file, out, out_size, relocation, &strtab, &symtab,
906*9356374aSAndroid Build Coastguard Worker                   opd_ptr, tmp_buf, tmp_buf_size);
907*9356374aSAndroid Build Coastguard Worker    if (rc != SYMBOL_NOT_FOUND) {
908*9356374aSAndroid Build Coastguard Worker      return rc;
909*9356374aSAndroid Build Coastguard Worker    }
910*9356374aSAndroid Build Coastguard Worker  }
911*9356374aSAndroid Build Coastguard Worker
912*9356374aSAndroid Build Coastguard Worker  return SYMBOL_NOT_FOUND;
913*9356374aSAndroid Build Coastguard Worker}
914*9356374aSAndroid Build Coastguard Worker
915*9356374aSAndroid Build Coastguard Workernamespace {
916*9356374aSAndroid Build Coastguard Worker// Thin wrapper around a file descriptor so that the file descriptor
917*9356374aSAndroid Build Coastguard Worker// gets closed for sure.
918*9356374aSAndroid Build Coastguard Workerclass FileDescriptor {
919*9356374aSAndroid Build Coastguard Worker public:
920*9356374aSAndroid Build Coastguard Worker  explicit FileDescriptor(int fd) : fd_(fd) {}
921*9356374aSAndroid Build Coastguard Worker  FileDescriptor(const FileDescriptor &) = delete;
922*9356374aSAndroid Build Coastguard Worker  FileDescriptor &operator=(const FileDescriptor &) = delete;
923*9356374aSAndroid Build Coastguard Worker
924*9356374aSAndroid Build Coastguard Worker  ~FileDescriptor() {
925*9356374aSAndroid Build Coastguard Worker    if (fd_ >= 0) {
926*9356374aSAndroid Build Coastguard Worker      close(fd_);
927*9356374aSAndroid Build Coastguard Worker    }
928*9356374aSAndroid Build Coastguard Worker  }
929*9356374aSAndroid Build Coastguard Worker
930*9356374aSAndroid Build Coastguard Worker  int get() const { return fd_; }
931*9356374aSAndroid Build Coastguard Worker
932*9356374aSAndroid Build Coastguard Worker private:
933*9356374aSAndroid Build Coastguard Worker  const int fd_;
934*9356374aSAndroid Build Coastguard Worker};
935*9356374aSAndroid Build Coastguard Worker
936*9356374aSAndroid Build Coastguard Worker// Helper class for reading lines from file.
937*9356374aSAndroid Build Coastguard Worker//
938*9356374aSAndroid Build Coastguard Worker// Note: we don't use ProcMapsIterator since the object is big (it has
939*9356374aSAndroid Build Coastguard Worker// a 5k array member) and uses async-unsafe functions such as sscanf()
940*9356374aSAndroid Build Coastguard Worker// and snprintf().
941*9356374aSAndroid Build Coastguard Workerclass LineReader {
942*9356374aSAndroid Build Coastguard Worker public:
943*9356374aSAndroid Build Coastguard Worker  explicit LineReader(int fd, char *buf, size_t buf_len)
944*9356374aSAndroid Build Coastguard Worker      : fd_(fd),
945*9356374aSAndroid Build Coastguard Worker        buf_len_(buf_len),
946*9356374aSAndroid Build Coastguard Worker        buf_(buf),
947*9356374aSAndroid Build Coastguard Worker        bol_(buf),
948*9356374aSAndroid Build Coastguard Worker        eol_(buf),
949*9356374aSAndroid Build Coastguard Worker        eod_(buf) {}
950*9356374aSAndroid Build Coastguard Worker
951*9356374aSAndroid Build Coastguard Worker  LineReader(const LineReader &) = delete;
952*9356374aSAndroid Build Coastguard Worker  LineReader &operator=(const LineReader &) = delete;
953*9356374aSAndroid Build Coastguard Worker
954*9356374aSAndroid Build Coastguard Worker  // Read '\n'-terminated line from file.  On success, modify "bol"
955*9356374aSAndroid Build Coastguard Worker  // and "eol", then return true.  Otherwise, return false.
956*9356374aSAndroid Build Coastguard Worker  //
957*9356374aSAndroid Build Coastguard Worker  // Note: if the last line doesn't end with '\n', the line will be
958*9356374aSAndroid Build Coastguard Worker  // dropped.  It's an intentional behavior to make the code simple.
959*9356374aSAndroid Build Coastguard Worker  bool ReadLine(const char **bol, const char **eol) {
960*9356374aSAndroid Build Coastguard Worker    if (BufferIsEmpty()) {  // First time.
961*9356374aSAndroid Build Coastguard Worker      const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_);
962*9356374aSAndroid Build Coastguard Worker      if (num_bytes <= 0) {  // EOF or error.
963*9356374aSAndroid Build Coastguard Worker        return false;
964*9356374aSAndroid Build Coastguard Worker      }
965*9356374aSAndroid Build Coastguard Worker      eod_ = buf_ + num_bytes;
966*9356374aSAndroid Build Coastguard Worker      bol_ = buf_;
967*9356374aSAndroid Build Coastguard Worker    } else {
968*9356374aSAndroid Build Coastguard Worker      bol_ = eol_ + 1;            // Advance to the next line in the buffer.
969*9356374aSAndroid Build Coastguard Worker      SAFE_ASSERT(bol_ <= eod_);  // "bol_" can point to "eod_".
970*9356374aSAndroid Build Coastguard Worker      if (!HasCompleteLine()) {
971*9356374aSAndroid Build Coastguard Worker        const auto incomplete_line_length = static_cast<size_t>(eod_ - bol_);
972*9356374aSAndroid Build Coastguard Worker        // Move the trailing incomplete line to the beginning.
973*9356374aSAndroid Build Coastguard Worker        memmove(buf_, bol_, incomplete_line_length);
974*9356374aSAndroid Build Coastguard Worker        // Read text from file and append it.
975*9356374aSAndroid Build Coastguard Worker        char *const append_pos = buf_ + incomplete_line_length;
976*9356374aSAndroid Build Coastguard Worker        const size_t capacity_left = buf_len_ - incomplete_line_length;
977*9356374aSAndroid Build Coastguard Worker        const ssize_t num_bytes =
978*9356374aSAndroid Build Coastguard Worker            ReadPersistent(fd_, append_pos, capacity_left);
979*9356374aSAndroid Build Coastguard Worker        if (num_bytes <= 0) {  // EOF or error.
980*9356374aSAndroid Build Coastguard Worker          return false;
981*9356374aSAndroid Build Coastguard Worker        }
982*9356374aSAndroid Build Coastguard Worker        eod_ = append_pos + num_bytes;
983*9356374aSAndroid Build Coastguard Worker        bol_ = buf_;
984*9356374aSAndroid Build Coastguard Worker      }
985*9356374aSAndroid Build Coastguard Worker    }
986*9356374aSAndroid Build Coastguard Worker    eol_ = FindLineFeed();
987*9356374aSAndroid Build Coastguard Worker    if (eol_ == nullptr) {  // '\n' not found.  Malformed line.
988*9356374aSAndroid Build Coastguard Worker      return false;
989*9356374aSAndroid Build Coastguard Worker    }
990*9356374aSAndroid Build Coastguard Worker    *eol_ = '\0';  // Replace '\n' with '\0'.
991*9356374aSAndroid Build Coastguard Worker
992*9356374aSAndroid Build Coastguard Worker    *bol = bol_;
993*9356374aSAndroid Build Coastguard Worker    *eol = eol_;
994*9356374aSAndroid Build Coastguard Worker    return true;
995*9356374aSAndroid Build Coastguard Worker  }
996*9356374aSAndroid Build Coastguard Worker
997*9356374aSAndroid Build Coastguard Worker private:
998*9356374aSAndroid Build Coastguard Worker  char *FindLineFeed() const {
999*9356374aSAndroid Build Coastguard Worker    return reinterpret_cast<char *>(
1000*9356374aSAndroid Build Coastguard Worker        memchr(bol_, '\n', static_cast<size_t>(eod_ - bol_)));
1001*9356374aSAndroid Build Coastguard Worker  }
1002*9356374aSAndroid Build Coastguard Worker
1003*9356374aSAndroid Build Coastguard Worker  bool BufferIsEmpty() const { return buf_ == eod_; }
1004*9356374aSAndroid Build Coastguard Worker
1005*9356374aSAndroid Build Coastguard Worker  bool HasCompleteLine() const {
1006*9356374aSAndroid Build Coastguard Worker    return !BufferIsEmpty() && FindLineFeed() != nullptr;
1007*9356374aSAndroid Build Coastguard Worker  }
1008*9356374aSAndroid Build Coastguard Worker
1009*9356374aSAndroid Build Coastguard Worker  const int fd_;
1010*9356374aSAndroid Build Coastguard Worker  const size_t buf_len_;
1011*9356374aSAndroid Build Coastguard Worker  char *const buf_;
1012*9356374aSAndroid Build Coastguard Worker  char *bol_;
1013*9356374aSAndroid Build Coastguard Worker  char *eol_;
1014*9356374aSAndroid Build Coastguard Worker  const char *eod_;  // End of data in "buf_".
1015*9356374aSAndroid Build Coastguard Worker};
1016*9356374aSAndroid Build Coastguard Worker}  // namespace
1017*9356374aSAndroid Build Coastguard Worker
1018*9356374aSAndroid Build Coastguard Worker// Place the hex number read from "start" into "*hex".  The pointer to
1019*9356374aSAndroid Build Coastguard Worker// the first non-hex character or "end" is returned.
1020*9356374aSAndroid Build Coastguard Workerstatic const char *GetHex(const char *start, const char *end,
1021*9356374aSAndroid Build Coastguard Worker                          uint64_t *const value) {
1022*9356374aSAndroid Build Coastguard Worker  uint64_t hex = 0;
1023*9356374aSAndroid Build Coastguard Worker  const char *p;
1024*9356374aSAndroid Build Coastguard Worker  for (p = start; p < end; ++p) {
1025*9356374aSAndroid Build Coastguard Worker    int ch = *p;
1026*9356374aSAndroid Build Coastguard Worker    if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') ||
1027*9356374aSAndroid Build Coastguard Worker        (ch >= 'a' && ch <= 'f')) {
1028*9356374aSAndroid Build Coastguard Worker      hex = (hex << 4) |
1029*9356374aSAndroid Build Coastguard Worker            static_cast<uint64_t>(ch < 'A' ? ch - '0' : (ch & 0xF) + 9);
1030*9356374aSAndroid Build Coastguard Worker    } else {  // Encountered the first non-hex character.
1031*9356374aSAndroid Build Coastguard Worker      break;
1032*9356374aSAndroid Build Coastguard Worker    }
1033*9356374aSAndroid Build Coastguard Worker  }
1034*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(p <= end);
1035*9356374aSAndroid Build Coastguard Worker  *value = hex;
1036*9356374aSAndroid Build Coastguard Worker  return p;
1037*9356374aSAndroid Build Coastguard Worker}
1038*9356374aSAndroid Build Coastguard Worker
1039*9356374aSAndroid Build Coastguard Workerstatic const char *GetHex(const char *start, const char *end,
1040*9356374aSAndroid Build Coastguard Worker                          const void **const addr) {
1041*9356374aSAndroid Build Coastguard Worker  uint64_t hex = 0;
1042*9356374aSAndroid Build Coastguard Worker  const char *p = GetHex(start, end, &hex);
1043*9356374aSAndroid Build Coastguard Worker  *addr = reinterpret_cast<void *>(hex);
1044*9356374aSAndroid Build Coastguard Worker  return p;
1045*9356374aSAndroid Build Coastguard Worker}
1046*9356374aSAndroid Build Coastguard Worker
1047*9356374aSAndroid Build Coastguard Worker// Normally we are only interested in "r?x" maps.
1048*9356374aSAndroid Build Coastguard Worker// On the PowerPC, function pointers point to descriptors in the .opd
1049*9356374aSAndroid Build Coastguard Worker// section.  The descriptors themselves are not executable code, so
1050*9356374aSAndroid Build Coastguard Worker// we need to relax the check below to "r??".
1051*9356374aSAndroid Build Coastguard Workerstatic bool ShouldUseMapping(const char *const flags) {
1052*9356374aSAndroid Build Coastguard Worker  return flags[0] == 'r' && (kPlatformUsesOPDSections || flags[2] == 'x');
1053*9356374aSAndroid Build Coastguard Worker}
1054*9356374aSAndroid Build Coastguard Worker
1055*9356374aSAndroid Build Coastguard Worker// Read /proc/self/maps and run "callback" for each mmapped file found.  If
1056*9356374aSAndroid Build Coastguard Worker// "callback" returns false, stop scanning and return true. Else continue
1057*9356374aSAndroid Build Coastguard Worker// scanning /proc/self/maps. Return true if no parse error is found.
1058*9356374aSAndroid Build Coastguard Workerstatic ABSL_ATTRIBUTE_NOINLINE bool ReadAddrMap(
1059*9356374aSAndroid Build Coastguard Worker    bool (*callback)(const char *filename, const void *const start_addr,
1060*9356374aSAndroid Build Coastguard Worker                     const void *const end_addr, uint64_t offset, void *arg),
1061*9356374aSAndroid Build Coastguard Worker    void *arg, void *tmp_buf, size_t tmp_buf_size) {
1062*9356374aSAndroid Build Coastguard Worker  // Use /proc/self/task/<pid>/maps instead of /proc/self/maps. The latter
1063*9356374aSAndroid Build Coastguard Worker  // requires kernel to stop all threads, and is significantly slower when there
1064*9356374aSAndroid Build Coastguard Worker  // are 1000s of threads.
1065*9356374aSAndroid Build Coastguard Worker  char maps_path[80];
1066*9356374aSAndroid Build Coastguard Worker  snprintf(maps_path, sizeof(maps_path), "/proc/self/task/%d/maps", getpid());
1067*9356374aSAndroid Build Coastguard Worker
1068*9356374aSAndroid Build Coastguard Worker  int maps_fd;
1069*9356374aSAndroid Build Coastguard Worker  NO_INTR(maps_fd = open(maps_path, O_RDONLY));
1070*9356374aSAndroid Build Coastguard Worker  FileDescriptor wrapped_maps_fd(maps_fd);
1071*9356374aSAndroid Build Coastguard Worker  if (wrapped_maps_fd.get() < 0) {
1072*9356374aSAndroid Build Coastguard Worker    ABSL_RAW_LOG(WARNING, "%s: errno=%d", maps_path, errno);
1073*9356374aSAndroid Build Coastguard Worker    return false;
1074*9356374aSAndroid Build Coastguard Worker  }
1075*9356374aSAndroid Build Coastguard Worker
1076*9356374aSAndroid Build Coastguard Worker  // Iterate over maps and look for the map containing the pc.  Then
1077*9356374aSAndroid Build Coastguard Worker  // look into the symbol tables inside.
1078*9356374aSAndroid Build Coastguard Worker  LineReader reader(wrapped_maps_fd.get(), static_cast<char *>(tmp_buf),
1079*9356374aSAndroid Build Coastguard Worker                    tmp_buf_size);
1080*9356374aSAndroid Build Coastguard Worker  while (true) {
1081*9356374aSAndroid Build Coastguard Worker    const char *cursor;
1082*9356374aSAndroid Build Coastguard Worker    const char *eol;
1083*9356374aSAndroid Build Coastguard Worker    if (!reader.ReadLine(&cursor, &eol)) {  // EOF or malformed line.
1084*9356374aSAndroid Build Coastguard Worker      break;
1085*9356374aSAndroid Build Coastguard Worker    }
1086*9356374aSAndroid Build Coastguard Worker
1087*9356374aSAndroid Build Coastguard Worker    const char *line = cursor;
1088*9356374aSAndroid Build Coastguard Worker    const void *start_address;
1089*9356374aSAndroid Build Coastguard Worker    // Start parsing line in /proc/self/maps.  Here is an example:
1090*9356374aSAndroid Build Coastguard Worker    //
1091*9356374aSAndroid Build Coastguard Worker    // 08048000-0804c000 r-xp 00000000 08:01 2142121    /bin/cat
1092*9356374aSAndroid Build Coastguard Worker    //
1093*9356374aSAndroid Build Coastguard Worker    // We want start address (08048000), end address (0804c000), flags
1094*9356374aSAndroid Build Coastguard Worker    // (r-xp) and file name (/bin/cat).
1095*9356374aSAndroid Build Coastguard Worker
1096*9356374aSAndroid Build Coastguard Worker    // Read start address.
1097*9356374aSAndroid Build Coastguard Worker    cursor = GetHex(cursor, eol, &start_address);
1098*9356374aSAndroid Build Coastguard Worker    if (cursor == eol || *cursor != '-') {
1099*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "Corrupt /proc/self/maps line: %s", line);
1100*9356374aSAndroid Build Coastguard Worker      return false;
1101*9356374aSAndroid Build Coastguard Worker    }
1102*9356374aSAndroid Build Coastguard Worker    ++cursor;  // Skip '-'.
1103*9356374aSAndroid Build Coastguard Worker
1104*9356374aSAndroid Build Coastguard Worker    // Read end address.
1105*9356374aSAndroid Build Coastguard Worker    const void *end_address;
1106*9356374aSAndroid Build Coastguard Worker    cursor = GetHex(cursor, eol, &end_address);
1107*9356374aSAndroid Build Coastguard Worker    if (cursor == eol || *cursor != ' ') {
1108*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "Corrupt /proc/self/maps line: %s", line);
1109*9356374aSAndroid Build Coastguard Worker      return false;
1110*9356374aSAndroid Build Coastguard Worker    }
1111*9356374aSAndroid Build Coastguard Worker    ++cursor;  // Skip ' '.
1112*9356374aSAndroid Build Coastguard Worker
1113*9356374aSAndroid Build Coastguard Worker    // Read flags.  Skip flags until we encounter a space or eol.
1114*9356374aSAndroid Build Coastguard Worker    const char *const flags_start = cursor;
1115*9356374aSAndroid Build Coastguard Worker    while (cursor < eol && *cursor != ' ') {
1116*9356374aSAndroid Build Coastguard Worker      ++cursor;
1117*9356374aSAndroid Build Coastguard Worker    }
1118*9356374aSAndroid Build Coastguard Worker    // We expect at least four letters for flags (ex. "r-xp").
1119*9356374aSAndroid Build Coastguard Worker    if (cursor == eol || cursor < flags_start + 4) {
1120*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "Corrupt /proc/self/maps: %s", line);
1121*9356374aSAndroid Build Coastguard Worker      return false;
1122*9356374aSAndroid Build Coastguard Worker    }
1123*9356374aSAndroid Build Coastguard Worker
1124*9356374aSAndroid Build Coastguard Worker    // Check flags.
1125*9356374aSAndroid Build Coastguard Worker    if (!ShouldUseMapping(flags_start)) {
1126*9356374aSAndroid Build Coastguard Worker      continue;  // We skip this map.
1127*9356374aSAndroid Build Coastguard Worker    }
1128*9356374aSAndroid Build Coastguard Worker    ++cursor;  // Skip ' '.
1129*9356374aSAndroid Build Coastguard Worker
1130*9356374aSAndroid Build Coastguard Worker    // Read file offset.
1131*9356374aSAndroid Build Coastguard Worker    uint64_t offset;
1132*9356374aSAndroid Build Coastguard Worker    cursor = GetHex(cursor, eol, &offset);
1133*9356374aSAndroid Build Coastguard Worker    ++cursor;  // Skip ' '.
1134*9356374aSAndroid Build Coastguard Worker
1135*9356374aSAndroid Build Coastguard Worker    // Skip to file name.  "cursor" now points to dev.  We need to skip at least
1136*9356374aSAndroid Build Coastguard Worker    // two spaces for dev and inode.
1137*9356374aSAndroid Build Coastguard Worker    int num_spaces = 0;
1138*9356374aSAndroid Build Coastguard Worker    while (cursor < eol) {
1139*9356374aSAndroid Build Coastguard Worker      if (*cursor == ' ') {
1140*9356374aSAndroid Build Coastguard Worker        ++num_spaces;
1141*9356374aSAndroid Build Coastguard Worker      } else if (num_spaces >= 2) {
1142*9356374aSAndroid Build Coastguard Worker        // The first non-space character after  skipping two spaces
1143*9356374aSAndroid Build Coastguard Worker        // is the beginning of the file name.
1144*9356374aSAndroid Build Coastguard Worker        break;
1145*9356374aSAndroid Build Coastguard Worker      }
1146*9356374aSAndroid Build Coastguard Worker      ++cursor;
1147*9356374aSAndroid Build Coastguard Worker    }
1148*9356374aSAndroid Build Coastguard Worker
1149*9356374aSAndroid Build Coastguard Worker    // Check whether this entry corresponds to our hint table for the true
1150*9356374aSAndroid Build Coastguard Worker    // filename.
1151*9356374aSAndroid Build Coastguard Worker    bool hinted =
1152*9356374aSAndroid Build Coastguard Worker        GetFileMappingHint(&start_address, &end_address, &offset, &cursor);
1153*9356374aSAndroid Build Coastguard Worker    if (!hinted && (cursor == eol || cursor[0] == '[')) {
1154*9356374aSAndroid Build Coastguard Worker      // not an object file, typically [vdso] or [vsyscall]
1155*9356374aSAndroid Build Coastguard Worker      continue;
1156*9356374aSAndroid Build Coastguard Worker    }
1157*9356374aSAndroid Build Coastguard Worker    if (!callback(cursor, start_address, end_address, offset, arg)) break;
1158*9356374aSAndroid Build Coastguard Worker  }
1159*9356374aSAndroid Build Coastguard Worker  return true;
1160*9356374aSAndroid Build Coastguard Worker}
1161*9356374aSAndroid Build Coastguard Worker
1162*9356374aSAndroid Build Coastguard Worker// Find the objfile mapped in address region containing [addr, addr + len).
1163*9356374aSAndroid Build Coastguard WorkerObjFile *Symbolizer::FindObjFile(const void *const addr, size_t len) {
1164*9356374aSAndroid Build Coastguard Worker  for (int i = 0; i < 2; ++i) {
1165*9356374aSAndroid Build Coastguard Worker    if (!ok_) return nullptr;
1166*9356374aSAndroid Build Coastguard Worker
1167*9356374aSAndroid Build Coastguard Worker    // Read /proc/self/maps if necessary
1168*9356374aSAndroid Build Coastguard Worker    if (!addr_map_read_) {
1169*9356374aSAndroid Build Coastguard Worker      addr_map_read_ = true;
1170*9356374aSAndroid Build Coastguard Worker      if (!ReadAddrMap(RegisterObjFile, this, tmp_buf_, TMP_BUF_SIZE)) {
1171*9356374aSAndroid Build Coastguard Worker        ok_ = false;
1172*9356374aSAndroid Build Coastguard Worker        return nullptr;
1173*9356374aSAndroid Build Coastguard Worker      }
1174*9356374aSAndroid Build Coastguard Worker    }
1175*9356374aSAndroid Build Coastguard Worker
1176*9356374aSAndroid Build Coastguard Worker    size_t lo = 0;
1177*9356374aSAndroid Build Coastguard Worker    size_t hi = addr_map_.Size();
1178*9356374aSAndroid Build Coastguard Worker    while (lo < hi) {
1179*9356374aSAndroid Build Coastguard Worker      size_t mid = (lo + hi) / 2;
1180*9356374aSAndroid Build Coastguard Worker      if (addr < addr_map_.At(mid)->end_addr) {
1181*9356374aSAndroid Build Coastguard Worker        hi = mid;
1182*9356374aSAndroid Build Coastguard Worker      } else {
1183*9356374aSAndroid Build Coastguard Worker        lo = mid + 1;
1184*9356374aSAndroid Build Coastguard Worker      }
1185*9356374aSAndroid Build Coastguard Worker    }
1186*9356374aSAndroid Build Coastguard Worker    if (lo != addr_map_.Size()) {
1187*9356374aSAndroid Build Coastguard Worker      ObjFile *obj = addr_map_.At(lo);
1188*9356374aSAndroid Build Coastguard Worker      SAFE_ASSERT(obj->end_addr > addr);
1189*9356374aSAndroid Build Coastguard Worker      if (addr >= obj->start_addr &&
1190*9356374aSAndroid Build Coastguard Worker          reinterpret_cast<const char *>(addr) + len <= obj->end_addr)
1191*9356374aSAndroid Build Coastguard Worker        return obj;
1192*9356374aSAndroid Build Coastguard Worker    }
1193*9356374aSAndroid Build Coastguard Worker
1194*9356374aSAndroid Build Coastguard Worker    // The address mapping may have changed since it was last read.  Retry.
1195*9356374aSAndroid Build Coastguard Worker    ClearAddrMap();
1196*9356374aSAndroid Build Coastguard Worker  }
1197*9356374aSAndroid Build Coastguard Worker  return nullptr;
1198*9356374aSAndroid Build Coastguard Worker}
1199*9356374aSAndroid Build Coastguard Worker
1200*9356374aSAndroid Build Coastguard Workervoid Symbolizer::ClearAddrMap() {
1201*9356374aSAndroid Build Coastguard Worker  for (size_t i = 0; i != addr_map_.Size(); i++) {
1202*9356374aSAndroid Build Coastguard Worker    ObjFile *o = addr_map_.At(i);
1203*9356374aSAndroid Build Coastguard Worker    base_internal::LowLevelAlloc::Free(o->filename);
1204*9356374aSAndroid Build Coastguard Worker    if (o->fd >= 0) {
1205*9356374aSAndroid Build Coastguard Worker      close(o->fd);
1206*9356374aSAndroid Build Coastguard Worker    }
1207*9356374aSAndroid Build Coastguard Worker  }
1208*9356374aSAndroid Build Coastguard Worker  addr_map_.Clear();
1209*9356374aSAndroid Build Coastguard Worker  addr_map_read_ = false;
1210*9356374aSAndroid Build Coastguard Worker}
1211*9356374aSAndroid Build Coastguard Worker
1212*9356374aSAndroid Build Coastguard Worker// Callback for ReadAddrMap to register objfiles in an in-memory table.
1213*9356374aSAndroid Build Coastguard Workerbool Symbolizer::RegisterObjFile(const char *filename,
1214*9356374aSAndroid Build Coastguard Worker                                 const void *const start_addr,
1215*9356374aSAndroid Build Coastguard Worker                                 const void *const end_addr, uint64_t offset,
1216*9356374aSAndroid Build Coastguard Worker                                 void *arg) {
1217*9356374aSAndroid Build Coastguard Worker  Symbolizer *impl = static_cast<Symbolizer *>(arg);
1218*9356374aSAndroid Build Coastguard Worker
1219*9356374aSAndroid Build Coastguard Worker  // Files are supposed to be added in the increasing address order.  Make
1220*9356374aSAndroid Build Coastguard Worker  // sure that's the case.
1221*9356374aSAndroid Build Coastguard Worker  size_t addr_map_size = impl->addr_map_.Size();
1222*9356374aSAndroid Build Coastguard Worker  if (addr_map_size != 0) {
1223*9356374aSAndroid Build Coastguard Worker    ObjFile *old = impl->addr_map_.At(addr_map_size - 1);
1224*9356374aSAndroid Build Coastguard Worker    if (old->end_addr > end_addr) {
1225*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(ERROR,
1226*9356374aSAndroid Build Coastguard Worker                   "Unsorted addr map entry: 0x%" PRIxPTR ": %s <-> 0x%" PRIxPTR
1227*9356374aSAndroid Build Coastguard Worker                   ": %s",
1228*9356374aSAndroid Build Coastguard Worker                   reinterpret_cast<uintptr_t>(end_addr), filename,
1229*9356374aSAndroid Build Coastguard Worker                   reinterpret_cast<uintptr_t>(old->end_addr), old->filename);
1230*9356374aSAndroid Build Coastguard Worker      return true;
1231*9356374aSAndroid Build Coastguard Worker    } else if (old->end_addr == end_addr) {
1232*9356374aSAndroid Build Coastguard Worker      // The same entry appears twice. This sometimes happens for [vdso].
1233*9356374aSAndroid Build Coastguard Worker      if (old->start_addr != start_addr ||
1234*9356374aSAndroid Build Coastguard Worker          strcmp(old->filename, filename) != 0) {
1235*9356374aSAndroid Build Coastguard Worker        ABSL_RAW_LOG(ERROR,
1236*9356374aSAndroid Build Coastguard Worker                     "Duplicate addr 0x%" PRIxPTR ": %s <-> 0x%" PRIxPTR ": %s",
1237*9356374aSAndroid Build Coastguard Worker                     reinterpret_cast<uintptr_t>(end_addr), filename,
1238*9356374aSAndroid Build Coastguard Worker                     reinterpret_cast<uintptr_t>(old->end_addr), old->filename);
1239*9356374aSAndroid Build Coastguard Worker      }
1240*9356374aSAndroid Build Coastguard Worker      return true;
1241*9356374aSAndroid Build Coastguard Worker    } else if (old->end_addr == start_addr &&
1242*9356374aSAndroid Build Coastguard Worker               reinterpret_cast<uintptr_t>(old->start_addr) - old->offset ==
1243*9356374aSAndroid Build Coastguard Worker                   reinterpret_cast<uintptr_t>(start_addr) - offset &&
1244*9356374aSAndroid Build Coastguard Worker               strcmp(old->filename, filename) == 0) {
1245*9356374aSAndroid Build Coastguard Worker      // Two contiguous map entries that span a contiguous region of the file,
1246*9356374aSAndroid Build Coastguard Worker      // perhaps because some part of the file was mlock()ed. Combine them.
1247*9356374aSAndroid Build Coastguard Worker      old->end_addr = end_addr;
1248*9356374aSAndroid Build Coastguard Worker      return true;
1249*9356374aSAndroid Build Coastguard Worker    }
1250*9356374aSAndroid Build Coastguard Worker  }
1251*9356374aSAndroid Build Coastguard Worker  ObjFile *obj = impl->addr_map_.Add();
1252*9356374aSAndroid Build Coastguard Worker  obj->filename = impl->CopyString(filename);
1253*9356374aSAndroid Build Coastguard Worker  obj->start_addr = start_addr;
1254*9356374aSAndroid Build Coastguard Worker  obj->end_addr = end_addr;
1255*9356374aSAndroid Build Coastguard Worker  obj->offset = offset;
1256*9356374aSAndroid Build Coastguard Worker  obj->elf_type = -1;  // filled on demand
1257*9356374aSAndroid Build Coastguard Worker  obj->fd = -1;        // opened on demand
1258*9356374aSAndroid Build Coastguard Worker  return true;
1259*9356374aSAndroid Build Coastguard Worker}
1260*9356374aSAndroid Build Coastguard Worker
1261*9356374aSAndroid Build Coastguard Worker// This function wraps the Demangle function to provide an interface
1262*9356374aSAndroid Build Coastguard Worker// where the input symbol is demangled in-place.
1263*9356374aSAndroid Build Coastguard Worker// To keep stack consumption low, we would like this function to not
1264*9356374aSAndroid Build Coastguard Worker// get inlined.
1265*9356374aSAndroid Build Coastguard Workerstatic ABSL_ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size,
1266*9356374aSAndroid Build Coastguard Worker                                                    char *tmp_buf,
1267*9356374aSAndroid Build Coastguard Worker                                                    size_t tmp_buf_size) {
1268*9356374aSAndroid Build Coastguard Worker  if (Demangle(out, tmp_buf, tmp_buf_size)) {
1269*9356374aSAndroid Build Coastguard Worker    // Demangling succeeded. Copy to out if the space allows.
1270*9356374aSAndroid Build Coastguard Worker    size_t len = strlen(tmp_buf);
1271*9356374aSAndroid Build Coastguard Worker    if (len + 1 <= out_size) {  // +1 for '\0'.
1272*9356374aSAndroid Build Coastguard Worker      SAFE_ASSERT(len < tmp_buf_size);
1273*9356374aSAndroid Build Coastguard Worker      memmove(out, tmp_buf, len + 1);
1274*9356374aSAndroid Build Coastguard Worker    }
1275*9356374aSAndroid Build Coastguard Worker  }
1276*9356374aSAndroid Build Coastguard Worker}
1277*9356374aSAndroid Build Coastguard Worker
1278*9356374aSAndroid Build Coastguard WorkerSymbolCacheLine *Symbolizer::GetCacheLine(const void *const pc) {
1279*9356374aSAndroid Build Coastguard Worker  uintptr_t pc0 = reinterpret_cast<uintptr_t>(pc);
1280*9356374aSAndroid Build Coastguard Worker  pc0 >>= 3;  // drop the low 3 bits
1281*9356374aSAndroid Build Coastguard Worker
1282*9356374aSAndroid Build Coastguard Worker  // Shuffle bits.
1283*9356374aSAndroid Build Coastguard Worker  pc0 ^= (pc0 >> 6) ^ (pc0 >> 12) ^ (pc0 >> 18);
1284*9356374aSAndroid Build Coastguard Worker  return &symbol_cache_[pc0 % SYMBOL_CACHE_LINES];
1285*9356374aSAndroid Build Coastguard Worker}
1286*9356374aSAndroid Build Coastguard Worker
1287*9356374aSAndroid Build Coastguard Workervoid Symbolizer::AgeSymbols(SymbolCacheLine *line) {
1288*9356374aSAndroid Build Coastguard Worker  for (uint32_t &age : line->age) {
1289*9356374aSAndroid Build Coastguard Worker    ++age;
1290*9356374aSAndroid Build Coastguard Worker  }
1291*9356374aSAndroid Build Coastguard Worker}
1292*9356374aSAndroid Build Coastguard Worker
1293*9356374aSAndroid Build Coastguard Workerconst char *Symbolizer::FindSymbolInCache(const void *const pc) {
1294*9356374aSAndroid Build Coastguard Worker  if (pc == nullptr) return nullptr;
1295*9356374aSAndroid Build Coastguard Worker
1296*9356374aSAndroid Build Coastguard Worker  SymbolCacheLine *line = GetCacheLine(pc);
1297*9356374aSAndroid Build Coastguard Worker  for (size_t i = 0; i < ABSL_ARRAYSIZE(line->pc); ++i) {
1298*9356374aSAndroid Build Coastguard Worker    if (line->pc[i] == pc) {
1299*9356374aSAndroid Build Coastguard Worker      AgeSymbols(line);
1300*9356374aSAndroid Build Coastguard Worker      line->age[i] = 0;
1301*9356374aSAndroid Build Coastguard Worker      return line->name[i];
1302*9356374aSAndroid Build Coastguard Worker    }
1303*9356374aSAndroid Build Coastguard Worker  }
1304*9356374aSAndroid Build Coastguard Worker  return nullptr;
1305*9356374aSAndroid Build Coastguard Worker}
1306*9356374aSAndroid Build Coastguard Worker
1307*9356374aSAndroid Build Coastguard Workerconst char *Symbolizer::InsertSymbolInCache(const void *const pc,
1308*9356374aSAndroid Build Coastguard Worker                                            const char *name) {
1309*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(pc != nullptr);
1310*9356374aSAndroid Build Coastguard Worker
1311*9356374aSAndroid Build Coastguard Worker  SymbolCacheLine *line = GetCacheLine(pc);
1312*9356374aSAndroid Build Coastguard Worker  uint32_t max_age = 0;
1313*9356374aSAndroid Build Coastguard Worker  size_t oldest_index = 0;
1314*9356374aSAndroid Build Coastguard Worker  bool found_oldest_index = false;
1315*9356374aSAndroid Build Coastguard Worker  for (size_t i = 0; i < ABSL_ARRAYSIZE(line->pc); ++i) {
1316*9356374aSAndroid Build Coastguard Worker    if (line->pc[i] == nullptr) {
1317*9356374aSAndroid Build Coastguard Worker      AgeSymbols(line);
1318*9356374aSAndroid Build Coastguard Worker      line->pc[i] = pc;
1319*9356374aSAndroid Build Coastguard Worker      line->name[i] = CopyString(name);
1320*9356374aSAndroid Build Coastguard Worker      line->age[i] = 0;
1321*9356374aSAndroid Build Coastguard Worker      return line->name[i];
1322*9356374aSAndroid Build Coastguard Worker    }
1323*9356374aSAndroid Build Coastguard Worker    if (line->age[i] >= max_age) {
1324*9356374aSAndroid Build Coastguard Worker      max_age = line->age[i];
1325*9356374aSAndroid Build Coastguard Worker      oldest_index = i;
1326*9356374aSAndroid Build Coastguard Worker      found_oldest_index = true;
1327*9356374aSAndroid Build Coastguard Worker    }
1328*9356374aSAndroid Build Coastguard Worker  }
1329*9356374aSAndroid Build Coastguard Worker
1330*9356374aSAndroid Build Coastguard Worker  AgeSymbols(line);
1331*9356374aSAndroid Build Coastguard Worker  ABSL_RAW_CHECK(found_oldest_index, "Corrupt cache");
1332*9356374aSAndroid Build Coastguard Worker  base_internal::LowLevelAlloc::Free(line->name[oldest_index]);
1333*9356374aSAndroid Build Coastguard Worker  line->pc[oldest_index] = pc;
1334*9356374aSAndroid Build Coastguard Worker  line->name[oldest_index] = CopyString(name);
1335*9356374aSAndroid Build Coastguard Worker  line->age[oldest_index] = 0;
1336*9356374aSAndroid Build Coastguard Worker  return line->name[oldest_index];
1337*9356374aSAndroid Build Coastguard Worker}
1338*9356374aSAndroid Build Coastguard Worker
1339*9356374aSAndroid Build Coastguard Workerstatic void MaybeOpenFdFromSelfExe(ObjFile *obj) {
1340*9356374aSAndroid Build Coastguard Worker  if (memcmp(obj->start_addr, ELFMAG, SELFMAG) != 0) {
1341*9356374aSAndroid Build Coastguard Worker    return;
1342*9356374aSAndroid Build Coastguard Worker  }
1343*9356374aSAndroid Build Coastguard Worker  int fd = open("/proc/self/exe", O_RDONLY);
1344*9356374aSAndroid Build Coastguard Worker  if (fd == -1) {
1345*9356374aSAndroid Build Coastguard Worker    return;
1346*9356374aSAndroid Build Coastguard Worker  }
1347*9356374aSAndroid Build Coastguard Worker  // Verify that contents of /proc/self/exe matches in-memory image of
1348*9356374aSAndroid Build Coastguard Worker  // the binary. This can fail if the "deleted" binary is in fact not
1349*9356374aSAndroid Build Coastguard Worker  // the main executable, or for binaries that have the first PT_LOAD
1350*9356374aSAndroid Build Coastguard Worker  // segment smaller than 4K. We do it in four steps so that the
1351*9356374aSAndroid Build Coastguard Worker  // buffer is smaller and we don't consume too much stack space.
1352*9356374aSAndroid Build Coastguard Worker  const char *mem = reinterpret_cast<const char *>(obj->start_addr);
1353*9356374aSAndroid Build Coastguard Worker  for (int i = 0; i < 4; ++i) {
1354*9356374aSAndroid Build Coastguard Worker    char buf[1024];
1355*9356374aSAndroid Build Coastguard Worker    ssize_t n = read(fd, buf, sizeof(buf));
1356*9356374aSAndroid Build Coastguard Worker    if (n != sizeof(buf) || memcmp(buf, mem, sizeof(buf)) != 0) {
1357*9356374aSAndroid Build Coastguard Worker      close(fd);
1358*9356374aSAndroid Build Coastguard Worker      return;
1359*9356374aSAndroid Build Coastguard Worker    }
1360*9356374aSAndroid Build Coastguard Worker    mem += sizeof(buf);
1361*9356374aSAndroid Build Coastguard Worker  }
1362*9356374aSAndroid Build Coastguard Worker  obj->fd = fd;
1363*9356374aSAndroid Build Coastguard Worker}
1364*9356374aSAndroid Build Coastguard Worker
1365*9356374aSAndroid Build Coastguard Workerstatic bool MaybeInitializeObjFile(ObjFile *obj) {
1366*9356374aSAndroid Build Coastguard Worker  if (obj->fd < 0) {
1367*9356374aSAndroid Build Coastguard Worker    obj->fd = open(obj->filename, O_RDONLY);
1368*9356374aSAndroid Build Coastguard Worker
1369*9356374aSAndroid Build Coastguard Worker    if (obj->fd < 0) {
1370*9356374aSAndroid Build Coastguard Worker      // Getting /proc/self/exe here means that we were hinted.
1371*9356374aSAndroid Build Coastguard Worker      if (strcmp(obj->filename, "/proc/self/exe") == 0) {
1372*9356374aSAndroid Build Coastguard Worker        // /proc/self/exe may be inaccessible (due to setuid, etc.), so try
1373*9356374aSAndroid Build Coastguard Worker        // accessing the binary via argv0.
1374*9356374aSAndroid Build Coastguard Worker        if (argv0_value != nullptr) {
1375*9356374aSAndroid Build Coastguard Worker          obj->fd = open(argv0_value, O_RDONLY);
1376*9356374aSAndroid Build Coastguard Worker        }
1377*9356374aSAndroid Build Coastguard Worker      } else {
1378*9356374aSAndroid Build Coastguard Worker        MaybeOpenFdFromSelfExe(obj);
1379*9356374aSAndroid Build Coastguard Worker      }
1380*9356374aSAndroid Build Coastguard Worker    }
1381*9356374aSAndroid Build Coastguard Worker
1382*9356374aSAndroid Build Coastguard Worker    if (obj->fd < 0) {
1383*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "%s: open failed: errno=%d", obj->filename, errno);
1384*9356374aSAndroid Build Coastguard Worker      return false;
1385*9356374aSAndroid Build Coastguard Worker    }
1386*9356374aSAndroid Build Coastguard Worker
1387*9356374aSAndroid Build Coastguard Worker    char buf[kSmallFileCacheSize];
1388*9356374aSAndroid Build Coastguard Worker    CachingFile file(obj->fd, buf, sizeof(buf));
1389*9356374aSAndroid Build Coastguard Worker
1390*9356374aSAndroid Build Coastguard Worker    obj->elf_type = FileGetElfType(&file);
1391*9356374aSAndroid Build Coastguard Worker    if (obj->elf_type < 0) {
1392*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "%s: wrong elf type: %d", obj->filename,
1393*9356374aSAndroid Build Coastguard Worker                   obj->elf_type);
1394*9356374aSAndroid Build Coastguard Worker      return false;
1395*9356374aSAndroid Build Coastguard Worker    }
1396*9356374aSAndroid Build Coastguard Worker
1397*9356374aSAndroid Build Coastguard Worker    if (!file.ReadFromOffsetExact(&obj->elf_header, sizeof(obj->elf_header),
1398*9356374aSAndroid Build Coastguard Worker                                  0)) {
1399*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "%s: failed to read elf header", obj->filename);
1400*9356374aSAndroid Build Coastguard Worker      return false;
1401*9356374aSAndroid Build Coastguard Worker    }
1402*9356374aSAndroid Build Coastguard Worker    const int phnum = obj->elf_header.e_phnum;
1403*9356374aSAndroid Build Coastguard Worker    const int phentsize = obj->elf_header.e_phentsize;
1404*9356374aSAndroid Build Coastguard Worker    auto phoff = static_cast<off_t>(obj->elf_header.e_phoff);
1405*9356374aSAndroid Build Coastguard Worker    size_t num_interesting_load_segments = 0;
1406*9356374aSAndroid Build Coastguard Worker    for (int j = 0; j < phnum; j++) {
1407*9356374aSAndroid Build Coastguard Worker      ElfW(Phdr) phdr;
1408*9356374aSAndroid Build Coastguard Worker      if (!file.ReadFromOffsetExact(&phdr, sizeof(phdr), phoff)) {
1409*9356374aSAndroid Build Coastguard Worker        ABSL_RAW_LOG(WARNING, "%s: failed to read program header %d",
1410*9356374aSAndroid Build Coastguard Worker                     obj->filename, j);
1411*9356374aSAndroid Build Coastguard Worker        return false;
1412*9356374aSAndroid Build Coastguard Worker      }
1413*9356374aSAndroid Build Coastguard Worker      phoff += phentsize;
1414*9356374aSAndroid Build Coastguard Worker
1415*9356374aSAndroid Build Coastguard Worker#if defined(__powerpc__) && !(_CALL_ELF > 1)
1416*9356374aSAndroid Build Coastguard Worker      // On the PowerPC ELF v1 ABI, function pointers actually point to function
1417*9356374aSAndroid Build Coastguard Worker      // descriptors. These descriptors are stored in an .opd section, which is
1418*9356374aSAndroid Build Coastguard Worker      // mapped read-only. We thus need to look at all readable segments, not
1419*9356374aSAndroid Build Coastguard Worker      // just the executable ones.
1420*9356374aSAndroid Build Coastguard Worker      constexpr int interesting = PF_R;
1421*9356374aSAndroid Build Coastguard Worker#else
1422*9356374aSAndroid Build Coastguard Worker      constexpr int interesting = PF_X | PF_R;
1423*9356374aSAndroid Build Coastguard Worker#endif
1424*9356374aSAndroid Build Coastguard Worker
1425*9356374aSAndroid Build Coastguard Worker      if (phdr.p_type != PT_LOAD
1426*9356374aSAndroid Build Coastguard Worker          || (phdr.p_flags & interesting) != interesting) {
1427*9356374aSAndroid Build Coastguard Worker        // Not a LOAD segment, not executable code, and not a function
1428*9356374aSAndroid Build Coastguard Worker        // descriptor.
1429*9356374aSAndroid Build Coastguard Worker        continue;
1430*9356374aSAndroid Build Coastguard Worker      }
1431*9356374aSAndroid Build Coastguard Worker      if (num_interesting_load_segments < obj->phdr.size()) {
1432*9356374aSAndroid Build Coastguard Worker        memcpy(&obj->phdr[num_interesting_load_segments++], &phdr, sizeof(phdr));
1433*9356374aSAndroid Build Coastguard Worker      } else {
1434*9356374aSAndroid Build Coastguard Worker        ABSL_RAW_LOG(
1435*9356374aSAndroid Build Coastguard Worker            WARNING, "%s: too many interesting LOAD segments: %zu >= %zu",
1436*9356374aSAndroid Build Coastguard Worker            obj->filename, num_interesting_load_segments, obj->phdr.size());
1437*9356374aSAndroid Build Coastguard Worker        break;
1438*9356374aSAndroid Build Coastguard Worker      }
1439*9356374aSAndroid Build Coastguard Worker    }
1440*9356374aSAndroid Build Coastguard Worker    if (num_interesting_load_segments == 0) {
1441*9356374aSAndroid Build Coastguard Worker      // This object has no interesting LOAD segments. That's unexpected.
1442*9356374aSAndroid Build Coastguard Worker      ABSL_RAW_LOG(WARNING, "%s: no interesting LOAD segments", obj->filename);
1443*9356374aSAndroid Build Coastguard Worker      return false;
1444*9356374aSAndroid Build Coastguard Worker    }
1445*9356374aSAndroid Build Coastguard Worker  }
1446*9356374aSAndroid Build Coastguard Worker  return true;
1447*9356374aSAndroid Build Coastguard Worker}
1448*9356374aSAndroid Build Coastguard Worker
1449*9356374aSAndroid Build Coastguard Worker// The implementation of our symbolization routine.  If it
1450*9356374aSAndroid Build Coastguard Worker// successfully finds the symbol containing "pc" and obtains the
1451*9356374aSAndroid Build Coastguard Worker// symbol name, returns pointer to that symbol. Otherwise, returns nullptr.
1452*9356374aSAndroid Build Coastguard Worker// If any symbol decorators have been installed via InstallSymbolDecorator(),
1453*9356374aSAndroid Build Coastguard Worker// they are called here as well.
1454*9356374aSAndroid Build Coastguard Worker// To keep stack consumption low, we would like this function to not
1455*9356374aSAndroid Build Coastguard Worker// get inlined.
1456*9356374aSAndroid Build Coastguard Workerconst char *Symbolizer::GetUncachedSymbol(const void *pc) {
1457*9356374aSAndroid Build Coastguard Worker  ObjFile *const obj = FindObjFile(pc, 1);
1458*9356374aSAndroid Build Coastguard Worker  ptrdiff_t relocation = 0;
1459*9356374aSAndroid Build Coastguard Worker  int fd = -1;
1460*9356374aSAndroid Build Coastguard Worker  if (obj != nullptr) {
1461*9356374aSAndroid Build Coastguard Worker    if (MaybeInitializeObjFile(obj)) {
1462*9356374aSAndroid Build Coastguard Worker      const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
1463*9356374aSAndroid Build Coastguard Worker      if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {
1464*9356374aSAndroid Build Coastguard Worker        // This object was relocated.
1465*9356374aSAndroid Build Coastguard Worker        //
1466*9356374aSAndroid Build Coastguard Worker        // For obj->offset > 0, adjust the relocation since a mapping at offset
1467*9356374aSAndroid Build Coastguard Worker        // X in the file will have a start address of [true relocation]+X.
1468*9356374aSAndroid Build Coastguard Worker        relocation = static_cast<ptrdiff_t>(start_addr - obj->offset);
1469*9356374aSAndroid Build Coastguard Worker
1470*9356374aSAndroid Build Coastguard Worker        // Note: some binaries have multiple LOAD segments that can contain
1471*9356374aSAndroid Build Coastguard Worker        // function pointers. We must find the right one.
1472*9356374aSAndroid Build Coastguard Worker        ElfW(Phdr) *phdr = nullptr;
1473*9356374aSAndroid Build Coastguard Worker        for (size_t j = 0; j < obj->phdr.size(); j++) {
1474*9356374aSAndroid Build Coastguard Worker          ElfW(Phdr) &p = obj->phdr[j];
1475*9356374aSAndroid Build Coastguard Worker          if (p.p_type != PT_LOAD) {
1476*9356374aSAndroid Build Coastguard Worker            // We only expect PT_LOADs. This must be PT_NULL that we didn't
1477*9356374aSAndroid Build Coastguard Worker            // write over (i.e. we exhausted all interesting PT_LOADs).
1478*9356374aSAndroid Build Coastguard Worker            ABSL_RAW_CHECK(p.p_type == PT_NULL, "unexpected p_type");
1479*9356374aSAndroid Build Coastguard Worker            break;
1480*9356374aSAndroid Build Coastguard Worker          }
1481*9356374aSAndroid Build Coastguard Worker          if (pc < reinterpret_cast<void *>(start_addr + p.p_vaddr + p.p_memsz)) {
1482*9356374aSAndroid Build Coastguard Worker            phdr = &p;
1483*9356374aSAndroid Build Coastguard Worker            break;
1484*9356374aSAndroid Build Coastguard Worker          }
1485*9356374aSAndroid Build Coastguard Worker        }
1486*9356374aSAndroid Build Coastguard Worker        if (phdr == nullptr) {
1487*9356374aSAndroid Build Coastguard Worker          // That's unexpected. Hope for the best.
1488*9356374aSAndroid Build Coastguard Worker          ABSL_RAW_LOG(
1489*9356374aSAndroid Build Coastguard Worker              WARNING,
1490*9356374aSAndroid Build Coastguard Worker              "%s: unable to find LOAD segment for pc: %p, start_addr: %zx",
1491*9356374aSAndroid Build Coastguard Worker              obj->filename, pc, start_addr);
1492*9356374aSAndroid Build Coastguard Worker        } else {
1493*9356374aSAndroid Build Coastguard Worker          // Adjust relocation in case phdr.p_vaddr != 0.
1494*9356374aSAndroid Build Coastguard Worker          // This happens for binaries linked with `lld --rosegment`, and for
1495*9356374aSAndroid Build Coastguard Worker          // binaries linked with BFD `ld -z separate-code`.
1496*9356374aSAndroid Build Coastguard Worker          relocation -= phdr->p_vaddr - phdr->p_offset;
1497*9356374aSAndroid Build Coastguard Worker        }
1498*9356374aSAndroid Build Coastguard Worker      }
1499*9356374aSAndroid Build Coastguard Worker
1500*9356374aSAndroid Build Coastguard Worker      fd = obj->fd;
1501*9356374aSAndroid Build Coastguard Worker      if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
1502*9356374aSAndroid Build Coastguard Worker                                  sizeof(symbol_buf_), tmp_buf_,
1503*9356374aSAndroid Build Coastguard Worker                                  sizeof(tmp_buf_)) == SYMBOL_FOUND) {
1504*9356374aSAndroid Build Coastguard Worker        // Only try to demangle the symbol name if it fit into symbol_buf_.
1505*9356374aSAndroid Build Coastguard Worker        DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
1506*9356374aSAndroid Build Coastguard Worker                        sizeof(tmp_buf_));
1507*9356374aSAndroid Build Coastguard Worker      }
1508*9356374aSAndroid Build Coastguard Worker    }
1509*9356374aSAndroid Build Coastguard Worker  } else {
1510*9356374aSAndroid Build Coastguard Worker#if ABSL_HAVE_VDSO_SUPPORT
1511*9356374aSAndroid Build Coastguard Worker    VDSOSupport vdso;
1512*9356374aSAndroid Build Coastguard Worker    if (vdso.IsPresent()) {
1513*9356374aSAndroid Build Coastguard Worker      VDSOSupport::SymbolInfo symbol_info;
1514*9356374aSAndroid Build Coastguard Worker      if (vdso.LookupSymbolByAddress(pc, &symbol_info)) {
1515*9356374aSAndroid Build Coastguard Worker        // All VDSO symbols are known to be short.
1516*9356374aSAndroid Build Coastguard Worker        size_t len = strlen(symbol_info.name);
1517*9356374aSAndroid Build Coastguard Worker        ABSL_RAW_CHECK(len + 1 < sizeof(symbol_buf_),
1518*9356374aSAndroid Build Coastguard Worker                       "VDSO symbol unexpectedly long");
1519*9356374aSAndroid Build Coastguard Worker        memcpy(symbol_buf_, symbol_info.name, len + 1);
1520*9356374aSAndroid Build Coastguard Worker      }
1521*9356374aSAndroid Build Coastguard Worker    }
1522*9356374aSAndroid Build Coastguard Worker#endif
1523*9356374aSAndroid Build Coastguard Worker  }
1524*9356374aSAndroid Build Coastguard Worker
1525*9356374aSAndroid Build Coastguard Worker  if (g_decorators_mu.TryLock()) {
1526*9356374aSAndroid Build Coastguard Worker    if (g_num_decorators > 0) {
1527*9356374aSAndroid Build Coastguard Worker      SymbolDecoratorArgs decorator_args = {
1528*9356374aSAndroid Build Coastguard Worker          pc,       relocation,       fd,     symbol_buf_, sizeof(symbol_buf_),
1529*9356374aSAndroid Build Coastguard Worker          tmp_buf_, sizeof(tmp_buf_), nullptr};
1530*9356374aSAndroid Build Coastguard Worker      for (int i = 0; i < g_num_decorators; ++i) {
1531*9356374aSAndroid Build Coastguard Worker        decorator_args.arg = g_decorators[i].arg;
1532*9356374aSAndroid Build Coastguard Worker        g_decorators[i].fn(&decorator_args);
1533*9356374aSAndroid Build Coastguard Worker      }
1534*9356374aSAndroid Build Coastguard Worker    }
1535*9356374aSAndroid Build Coastguard Worker    g_decorators_mu.Unlock();
1536*9356374aSAndroid Build Coastguard Worker  }
1537*9356374aSAndroid Build Coastguard Worker  if (symbol_buf_[0] == '\0') {
1538*9356374aSAndroid Build Coastguard Worker    return nullptr;
1539*9356374aSAndroid Build Coastguard Worker  }
1540*9356374aSAndroid Build Coastguard Worker  symbol_buf_[sizeof(symbol_buf_) - 1] = '\0';  // Paranoia.
1541*9356374aSAndroid Build Coastguard Worker  return InsertSymbolInCache(pc, symbol_buf_);
1542*9356374aSAndroid Build Coastguard Worker}
1543*9356374aSAndroid Build Coastguard Worker
1544*9356374aSAndroid Build Coastguard Workerconst char *Symbolizer::GetSymbol(const void *pc) {
1545*9356374aSAndroid Build Coastguard Worker  const char *entry = FindSymbolInCache(pc);
1546*9356374aSAndroid Build Coastguard Worker  if (entry != nullptr) {
1547*9356374aSAndroid Build Coastguard Worker    return entry;
1548*9356374aSAndroid Build Coastguard Worker  }
1549*9356374aSAndroid Build Coastguard Worker  symbol_buf_[0] = '\0';
1550*9356374aSAndroid Build Coastguard Worker
1551*9356374aSAndroid Build Coastguard Worker#ifdef __hppa__
1552*9356374aSAndroid Build Coastguard Worker  {
1553*9356374aSAndroid Build Coastguard Worker    // In some contexts (e.g., return addresses), PA-RISC uses the lowest two
1554*9356374aSAndroid Build Coastguard Worker    // bits of the address to indicate the privilege level. Clear those bits
1555*9356374aSAndroid Build Coastguard Worker    // before trying to symbolize.
1556*9356374aSAndroid Build Coastguard Worker    const auto pc_bits = reinterpret_cast<uintptr_t>(pc);
1557*9356374aSAndroid Build Coastguard Worker    const auto address = pc_bits & ~0x3;
1558*9356374aSAndroid Build Coastguard Worker    entry = GetUncachedSymbol(reinterpret_cast<const void *>(address));
1559*9356374aSAndroid Build Coastguard Worker    if (entry != nullptr) {
1560*9356374aSAndroid Build Coastguard Worker      return entry;
1561*9356374aSAndroid Build Coastguard Worker    }
1562*9356374aSAndroid Build Coastguard Worker
1563*9356374aSAndroid Build Coastguard Worker    // In some contexts, PA-RISC also uses bit 1 of the address to indicate that
1564*9356374aSAndroid Build Coastguard Worker    // this is a cross-DSO function pointer. Such function pointers actually
1565*9356374aSAndroid Build Coastguard Worker    // point to a procedure label, a struct whose first 32-bit (pointer) element
1566*9356374aSAndroid Build Coastguard Worker    // actually points to the function text. With no symbol found for this
1567*9356374aSAndroid Build Coastguard Worker    // address so far, try interpreting it as a cross-DSO function pointer and
1568*9356374aSAndroid Build Coastguard Worker    // see how that goes.
1569*9356374aSAndroid Build Coastguard Worker    if (pc_bits & 0x2) {
1570*9356374aSAndroid Build Coastguard Worker      return GetUncachedSymbol(*reinterpret_cast<const void *const *>(address));
1571*9356374aSAndroid Build Coastguard Worker    }
1572*9356374aSAndroid Build Coastguard Worker
1573*9356374aSAndroid Build Coastguard Worker    return nullptr;
1574*9356374aSAndroid Build Coastguard Worker  }
1575*9356374aSAndroid Build Coastguard Worker#else
1576*9356374aSAndroid Build Coastguard Worker  return GetUncachedSymbol(pc);
1577*9356374aSAndroid Build Coastguard Worker#endif
1578*9356374aSAndroid Build Coastguard Worker}
1579*9356374aSAndroid Build Coastguard Worker
1580*9356374aSAndroid Build Coastguard Workerbool RemoveAllSymbolDecorators(void) {
1581*9356374aSAndroid Build Coastguard Worker  if (!g_decorators_mu.TryLock()) {
1582*9356374aSAndroid Build Coastguard Worker    // Someone else is using decorators. Get out.
1583*9356374aSAndroid Build Coastguard Worker    return false;
1584*9356374aSAndroid Build Coastguard Worker  }
1585*9356374aSAndroid Build Coastguard Worker  g_num_decorators = 0;
1586*9356374aSAndroid Build Coastguard Worker  g_decorators_mu.Unlock();
1587*9356374aSAndroid Build Coastguard Worker  return true;
1588*9356374aSAndroid Build Coastguard Worker}
1589*9356374aSAndroid Build Coastguard Worker
1590*9356374aSAndroid Build Coastguard Workerbool RemoveSymbolDecorator(int ticket) {
1591*9356374aSAndroid Build Coastguard Worker  if (!g_decorators_mu.TryLock()) {
1592*9356374aSAndroid Build Coastguard Worker    // Someone else is using decorators. Get out.
1593*9356374aSAndroid Build Coastguard Worker    return false;
1594*9356374aSAndroid Build Coastguard Worker  }
1595*9356374aSAndroid Build Coastguard Worker  for (int i = 0; i < g_num_decorators; ++i) {
1596*9356374aSAndroid Build Coastguard Worker    if (g_decorators[i].ticket == ticket) {
1597*9356374aSAndroid Build Coastguard Worker      while (i < g_num_decorators - 1) {
1598*9356374aSAndroid Build Coastguard Worker        g_decorators[i] = g_decorators[i + 1];
1599*9356374aSAndroid Build Coastguard Worker        ++i;
1600*9356374aSAndroid Build Coastguard Worker      }
1601*9356374aSAndroid Build Coastguard Worker      g_num_decorators = i;
1602*9356374aSAndroid Build Coastguard Worker      break;
1603*9356374aSAndroid Build Coastguard Worker    }
1604*9356374aSAndroid Build Coastguard Worker  }
1605*9356374aSAndroid Build Coastguard Worker  g_decorators_mu.Unlock();
1606*9356374aSAndroid Build Coastguard Worker  return true;  // Decorator is known to be removed.
1607*9356374aSAndroid Build Coastguard Worker}
1608*9356374aSAndroid Build Coastguard Worker
1609*9356374aSAndroid Build Coastguard Workerint InstallSymbolDecorator(SymbolDecorator decorator, void *arg) {
1610*9356374aSAndroid Build Coastguard Worker  static int ticket = 0;
1611*9356374aSAndroid Build Coastguard Worker
1612*9356374aSAndroid Build Coastguard Worker  if (!g_decorators_mu.TryLock()) {
1613*9356374aSAndroid Build Coastguard Worker    // Someone else is using decorators. Get out.
1614*9356374aSAndroid Build Coastguard Worker    return -2;
1615*9356374aSAndroid Build Coastguard Worker  }
1616*9356374aSAndroid Build Coastguard Worker  int ret = ticket;
1617*9356374aSAndroid Build Coastguard Worker  if (g_num_decorators >= kMaxDecorators) {
1618*9356374aSAndroid Build Coastguard Worker    ret = -1;
1619*9356374aSAndroid Build Coastguard Worker  } else {
1620*9356374aSAndroid Build Coastguard Worker    g_decorators[g_num_decorators] = {decorator, arg, ticket++};
1621*9356374aSAndroid Build Coastguard Worker    ++g_num_decorators;
1622*9356374aSAndroid Build Coastguard Worker  }
1623*9356374aSAndroid Build Coastguard Worker  g_decorators_mu.Unlock();
1624*9356374aSAndroid Build Coastguard Worker  return ret;
1625*9356374aSAndroid Build Coastguard Worker}
1626*9356374aSAndroid Build Coastguard Worker
1627*9356374aSAndroid Build Coastguard Workerbool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset,
1628*9356374aSAndroid Build Coastguard Worker                             const char *filename) {
1629*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(start <= end);
1630*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(filename != nullptr);
1631*9356374aSAndroid Build Coastguard Worker
1632*9356374aSAndroid Build Coastguard Worker  InitSigSafeArena();
1633*9356374aSAndroid Build Coastguard Worker
1634*9356374aSAndroid Build Coastguard Worker  if (!g_file_mapping_mu.TryLock()) {
1635*9356374aSAndroid Build Coastguard Worker    return false;
1636*9356374aSAndroid Build Coastguard Worker  }
1637*9356374aSAndroid Build Coastguard Worker
1638*9356374aSAndroid Build Coastguard Worker  bool ret = true;
1639*9356374aSAndroid Build Coastguard Worker  if (g_num_file_mapping_hints >= kMaxFileMappingHints) {
1640*9356374aSAndroid Build Coastguard Worker    ret = false;
1641*9356374aSAndroid Build Coastguard Worker  } else {
1642*9356374aSAndroid Build Coastguard Worker    // TODO(ckennelly): Move this into a string copy routine.
1643*9356374aSAndroid Build Coastguard Worker    size_t len = strlen(filename);
1644*9356374aSAndroid Build Coastguard Worker    char *dst = static_cast<char *>(
1645*9356374aSAndroid Build Coastguard Worker        base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena()));
1646*9356374aSAndroid Build Coastguard Worker    ABSL_RAW_CHECK(dst != nullptr, "out of memory");
1647*9356374aSAndroid Build Coastguard Worker    memcpy(dst, filename, len + 1);
1648*9356374aSAndroid Build Coastguard Worker
1649*9356374aSAndroid Build Coastguard Worker    auto &hint = g_file_mapping_hints[g_num_file_mapping_hints++];
1650*9356374aSAndroid Build Coastguard Worker    hint.start = start;
1651*9356374aSAndroid Build Coastguard Worker    hint.end = end;
1652*9356374aSAndroid Build Coastguard Worker    hint.offset = offset;
1653*9356374aSAndroid Build Coastguard Worker    hint.filename = dst;
1654*9356374aSAndroid Build Coastguard Worker  }
1655*9356374aSAndroid Build Coastguard Worker
1656*9356374aSAndroid Build Coastguard Worker  g_file_mapping_mu.Unlock();
1657*9356374aSAndroid Build Coastguard Worker  return ret;
1658*9356374aSAndroid Build Coastguard Worker}
1659*9356374aSAndroid Build Coastguard Worker
1660*9356374aSAndroid Build Coastguard Workerbool GetFileMappingHint(const void **start, const void **end, uint64_t *offset,
1661*9356374aSAndroid Build Coastguard Worker                        const char **filename) {
1662*9356374aSAndroid Build Coastguard Worker  if (!g_file_mapping_mu.TryLock()) {
1663*9356374aSAndroid Build Coastguard Worker    return false;
1664*9356374aSAndroid Build Coastguard Worker  }
1665*9356374aSAndroid Build Coastguard Worker  bool found = false;
1666*9356374aSAndroid Build Coastguard Worker  for (int i = 0; i < g_num_file_mapping_hints; i++) {
1667*9356374aSAndroid Build Coastguard Worker    if (g_file_mapping_hints[i].start <= *start &&
1668*9356374aSAndroid Build Coastguard Worker        *end <= g_file_mapping_hints[i].end) {
1669*9356374aSAndroid Build Coastguard Worker      // We assume that the start_address for the mapping is the base
1670*9356374aSAndroid Build Coastguard Worker      // address of the ELF section, but when [start_address,end_address) is
1671*9356374aSAndroid Build Coastguard Worker      // not strictly equal to [hint.start, hint.end), that assumption is
1672*9356374aSAndroid Build Coastguard Worker      // invalid.
1673*9356374aSAndroid Build Coastguard Worker      //
1674*9356374aSAndroid Build Coastguard Worker      // This uses the hint's start address (even though hint.start is not
1675*9356374aSAndroid Build Coastguard Worker      // necessarily equal to start_address) to ensure the correct
1676*9356374aSAndroid Build Coastguard Worker      // relocation is computed later.
1677*9356374aSAndroid Build Coastguard Worker      *start = g_file_mapping_hints[i].start;
1678*9356374aSAndroid Build Coastguard Worker      *end = g_file_mapping_hints[i].end;
1679*9356374aSAndroid Build Coastguard Worker      *offset = g_file_mapping_hints[i].offset;
1680*9356374aSAndroid Build Coastguard Worker      *filename = g_file_mapping_hints[i].filename;
1681*9356374aSAndroid Build Coastguard Worker      found = true;
1682*9356374aSAndroid Build Coastguard Worker      break;
1683*9356374aSAndroid Build Coastguard Worker    }
1684*9356374aSAndroid Build Coastguard Worker  }
1685*9356374aSAndroid Build Coastguard Worker  g_file_mapping_mu.Unlock();
1686*9356374aSAndroid Build Coastguard Worker  return found;
1687*9356374aSAndroid Build Coastguard Worker}
1688*9356374aSAndroid Build Coastguard Worker
1689*9356374aSAndroid Build Coastguard Worker}  // namespace debugging_internal
1690*9356374aSAndroid Build Coastguard Worker
1691*9356374aSAndroid Build Coastguard Workerbool Symbolize(const void *pc, char *out, int out_size) {
1692*9356374aSAndroid Build Coastguard Worker  // Symbolization is very slow under tsan.
1693*9356374aSAndroid Build Coastguard Worker  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
1694*9356374aSAndroid Build Coastguard Worker  SAFE_ASSERT(out_size >= 0);
1695*9356374aSAndroid Build Coastguard Worker  debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer();
1696*9356374aSAndroid Build Coastguard Worker  const char *name = s->GetSymbol(pc);
1697*9356374aSAndroid Build Coastguard Worker  bool ok = false;
1698*9356374aSAndroid Build Coastguard Worker  if (name != nullptr && out_size > 0) {
1699*9356374aSAndroid Build Coastguard Worker    strncpy(out, name, static_cast<size_t>(out_size));
1700*9356374aSAndroid Build Coastguard Worker    ok = true;
1701*9356374aSAndroid Build Coastguard Worker    if (out[static_cast<size_t>(out_size) - 1] != '\0') {
1702*9356374aSAndroid Build Coastguard Worker      // strncpy() does not '\0' terminate when it truncates.  Do so, with
1703*9356374aSAndroid Build Coastguard Worker      // trailing ellipsis.
1704*9356374aSAndroid Build Coastguard Worker      static constexpr char kEllipsis[] = "...";
1705*9356374aSAndroid Build Coastguard Worker      size_t ellipsis_size =
1706*9356374aSAndroid Build Coastguard Worker          std::min(strlen(kEllipsis), static_cast<size_t>(out_size) - 1);
1707*9356374aSAndroid Build Coastguard Worker      memcpy(out + static_cast<size_t>(out_size) - ellipsis_size - 1, kEllipsis,
1708*9356374aSAndroid Build Coastguard Worker             ellipsis_size);
1709*9356374aSAndroid Build Coastguard Worker      out[static_cast<size_t>(out_size) - 1] = '\0';
1710*9356374aSAndroid Build Coastguard Worker    }
1711*9356374aSAndroid Build Coastguard Worker  }
1712*9356374aSAndroid Build Coastguard Worker  debugging_internal::FreeSymbolizer(s);
1713*9356374aSAndroid Build Coastguard Worker  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
1714*9356374aSAndroid Build Coastguard Worker  return ok;
1715*9356374aSAndroid Build Coastguard Worker}
1716*9356374aSAndroid Build Coastguard Worker
1717*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_END
1718*9356374aSAndroid Build Coastguard Worker}  // namespace absl
1719*9356374aSAndroid Build Coastguard Worker
1720*9356374aSAndroid Build Coastguard Workerextern "C" bool AbslInternalGetFileMappingHint(const void **start,
1721*9356374aSAndroid Build Coastguard Worker                                               const void **end, uint64_t *offset,
1722*9356374aSAndroid Build Coastguard Worker                                               const char **filename) {
1723*9356374aSAndroid Build Coastguard Worker  return absl::debugging_internal::GetFileMappingHint(start, end, offset,
1724*9356374aSAndroid Build Coastguard Worker                                                      filename);
1725*9356374aSAndroid Build Coastguard Worker}
1726