sanitizer_linux_libcdep.cc revision 7847d77b246635211c3bf465421d49d7af5226c1
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- sanitizer_linux_libcdep.cc ----------------------------------------===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// This file is shared between AddressSanitizer and ThreadSanitizer
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// run-time libraries and implements linux-specific functions from
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sanitizer_libc.h.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_platform.h"
16a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#if SANITIZER_LINUX
17a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sanitizer_common.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sanitizer_linux.h"
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sanitizer_placement_new.h"
21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "sanitizer_procmaps.h"
22a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "sanitizer_stacktrace.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <dlfcn.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/prctl.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/resource.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unwind.h>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !SANITIZER_ANDROID
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <elf.h>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <link.h>
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace __sanitizer {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                uptr *stack_bottom) {
39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  static const uptr kMaxThreadStackSize = 1 << 30;  // 1Gb
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(stack_top);
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CHECK(stack_bottom);
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (at_initialization) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is the main thread. Libpthread may not be initialized yet.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct rlimit rl;
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find the mapping that contains a stack variable.
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MemoryMappingLayout proc_maps(/*cache_enabled*/true);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uptr start, end, offset;
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    uptr prev_end = 0;
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((uptr)&rl < end)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prev_end = end;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK((uptr)&rl >= start && (uptr)&rl < end);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Get stacksize from rlimit, but clip it so that it does not overlap
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with other mappings.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uptr stacksize = rl.rlim_cur;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (stacksize > end - prev_end)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stacksize = end - prev_end;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When running with unlimited stack size, we still want to set some limit.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The unlimited stack size is caused by 'ulimit -s unlimited'.
65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (stacksize > kMaxThreadStackSize)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stacksize = kMaxThreadStackSize;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *stack_top = end;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *stack_bottom = end - stacksize;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_attr_t attr;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uptr stacksize = 0;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *stackaddr = 0;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_attr_destroy(&attr);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_LE(stacksize, kMaxThreadStackSize);  // Sanity check.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *stack_top = (uptr)stackaddr + stacksize;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *stack_bottom = (uptr)stackaddr;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not compile for Go because dlsym() requires -ldl
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SANITIZER_GO
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetEnv(const char *name, const char *value) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *f = dlsym(RTLD_NEXT, "setenv");
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (f == 0)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef int(*setenv_ft)(const char *name, const char *value, int overwrite);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  setenv_ft setenv_f;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(sizeof(setenv_f), sizeof(f));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal_memcpy(&setenv_f, &f, sizeof(f));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return setenv_f(name, value, 1) == 0;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SanitizerSetThreadName(const char *name) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PR_SET_NAME
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);  // NOLINT
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SanitizerGetThreadName(char *name, int max_len) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PR_GET_NAME
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  char buff[17];
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0))  // NOLINT
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal_strncpy(name, buff, max_len);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  name[max_len] = 0;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SANITIZER_GO
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//------------------------- SlowUnwindStack -----------------------------------
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __arm__
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNWIND_STOP _URC_END_OF_STACK
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNWIND_CONTINUE _URC_NO_REASON
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNWIND_STOP _URC_NORMAL_STOP
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNWIND_CONTINUE _URC_NO_REASON
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __arm__
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uptr val;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      15 /* r15 = PC */, _UVRSD_UINT32, &val);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear the Thumb bit.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return val & ~(uptr)1;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _Unwind_GetIP(ctx);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
141
142_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
143  StackTrace *b = (StackTrace*)param;
144  CHECK(b->size < b->max_size);
145  uptr pc = Unwind_GetIP(ctx);
146  b->trace[b->size++] = pc;
147  if (b->size == b->max_size) return UNWIND_STOP;
148  return UNWIND_CONTINUE;
149}
150
151static bool MatchPc(uptr cur_pc, uptr trace_pc) {
152  return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
153}
154
155void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
156  this->size = 0;
157  this->max_size = max_depth;
158  if (max_depth > 1) {
159    _Unwind_Backtrace(Unwind_Trace, this);
160    // We need to pop a few frames so that pc is on top.
161    // trace[0] belongs to the current function so we always pop it.
162    int to_pop = 1;
163    /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
164    else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
165    else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
166    else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
167    else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
168    this->PopStackFrames(to_pop);
169  }
170  this->trace[0] = pc;
171}
172
173#endif  // !SANITIZER_GO
174
175static uptr g_tls_size;
176
177#ifdef __i386__
178# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
179#else
180# define DL_INTERNAL_FUNCTION
181#endif
182
183void InitTlsSize() {
184#if !defined(SANITIZER_GO) && !SANITIZER_ANDROID
185  typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
186  get_tls_func get_tls;
187  void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
188  CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
189  internal_memcpy(&get_tls, &get_tls_static_info_ptr,
190                  sizeof(get_tls_static_info_ptr));
191  CHECK_NE(get_tls, 0);
192  size_t tls_size = 0;
193  size_t tls_align = 0;
194  get_tls(&tls_size, &tls_align);
195  g_tls_size = tls_size;
196#endif
197}
198
199uptr GetTlsSize() {
200  return g_tls_size;
201}
202
203#if defined(__x86_64__) || defined(__i386__)
204// sizeof(struct thread) from glibc.
205// There has been a report of this being different on glibc 2.11 and 2.13. We
206// don't know when this change happened, so 2.14 is a conservative estimate.
207#if __GLIBC_PREREQ(2, 14)
208const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1216, 2304);
209#else
210const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1168, 2304);
211#endif
212
213uptr ThreadDescriptorSize() {
214  return kThreadDescriptorSize;
215}
216
217// The offset at which pointer to self is located in the thread descriptor.
218const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16);
219
220uptr ThreadSelfOffset() {
221  return kThreadSelfOffset;
222}
223
224uptr ThreadSelf() {
225  uptr descr_addr;
226#ifdef __i386__
227  asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
228#else
229  asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
230#endif
231  return descr_addr;
232}
233#endif  // defined(__x86_64__) || defined(__i386__)
234
235void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
236                          uptr *tls_addr, uptr *tls_size) {
237#ifndef SANITIZER_GO
238#if defined(__x86_64__) || defined(__i386__)
239  *tls_addr = ThreadSelf();
240  *tls_size = GetTlsSize();
241  *tls_addr -= *tls_size;
242  *tls_addr += kThreadDescriptorSize;
243#else
244  *tls_addr = 0;
245  *tls_size = 0;
246#endif
247
248  uptr stack_top, stack_bottom;
249  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
250  *stk_addr = stack_bottom;
251  *stk_size = stack_top - stack_bottom;
252
253  if (!main) {
254    // If stack and tls intersect, make them non-intersecting.
255    if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
256      CHECK_GT(*tls_addr + *tls_size, *stk_addr);
257      CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
258      *stk_size -= *tls_size;
259      *tls_addr = *stk_addr + *stk_size;
260    }
261  }
262#else  // SANITIZER_GO
263  *stk_addr = 0;
264  *stk_size = 0;
265  *tls_addr = 0;
266  *tls_size = 0;
267#endif  // SANITIZER_GO
268}
269
270void AdjustStackSizeLinux(void *attr_, int verbosity) {
271  pthread_attr_t *attr = (pthread_attr_t *)attr_;
272  uptr stackaddr = 0;
273  size_t stacksize = 0;
274  pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
275  // GLibC will return (0 - stacksize) as the stack address in the case when
276  // stacksize is set, but stackaddr is not.
277  bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
278  // We place a lot of tool data into TLS, account for that.
279  const uptr minstacksize = GetTlsSize() + 128*1024;
280  if (stacksize < minstacksize) {
281    if (!stack_set) {
282      if (verbosity && stacksize != 0)
283        Printf("Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
284               minstacksize);
285      pthread_attr_setstacksize(attr, minstacksize);
286    } else {
287      Printf("Sanitizer: pre-allocated stack size is insufficient: "
288             "%zu < %zu\n", stacksize, minstacksize);
289      Printf("Sanitizer: pthread_create is likely to fail.\n");
290    }
291  }
292}
293
294#if SANITIZER_ANDROID
295uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
296                      string_predicate_t filter) {
297  return 0;
298}
299#else  // SANITIZER_ANDROID
300typedef ElfW(Phdr) Elf_Phdr;
301
302struct DlIteratePhdrData {
303  LoadedModule *modules;
304  uptr current_n;
305  bool first;
306  uptr max_n;
307  string_predicate_t filter;
308};
309
310static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
311  DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
312  if (data->current_n == data->max_n)
313    return 0;
314  InternalScopedBuffer<char> module_name(kMaxPathLength);
315  module_name.data()[0] = '\0';
316  if (data->first) {
317    data->first = false;
318    // First module is the binary itself.
319    ReadBinaryName(module_name.data(), module_name.size());
320  } else if (info->dlpi_name) {
321    internal_strncpy(module_name.data(), info->dlpi_name, module_name.size());
322  }
323  if (module_name.data()[0] == '\0')
324    return 0;
325  if (data->filter && !data->filter(module_name.data()))
326    return 0;
327  void *mem = &data->modules[data->current_n];
328  LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(),
329                                                   info->dlpi_addr);
330  data->current_n++;
331  for (int i = 0; i < info->dlpi_phnum; i++) {
332    const Elf_Phdr *phdr = &info->dlpi_phdr[i];
333    if (phdr->p_type == PT_LOAD) {
334      uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
335      uptr cur_end = cur_beg + phdr->p_memsz;
336      cur_module->addAddressRange(cur_beg, cur_end);
337    }
338  }
339  return 0;
340}
341
342uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
343                      string_predicate_t filter) {
344  CHECK(modules);
345  DlIteratePhdrData data = {modules, 0, true, max_modules, filter};
346  dl_iterate_phdr(dl_iterate_phdr_cb, &data);
347  return data.current_n;
348}
349#endif  // SANITIZER_ANDROID
350
351}  // namespace __sanitizer
352
353#endif  // SANITIZER_LINUX
354