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