@@ -288,23 +288,33 @@ static inline bool MaybeUserPointer(uptr p) {
288288# endif
289289}
290290
291+ namespace {
292+ struct DirectMemoryAccessor {
293+ void Init (uptr begin, uptr end) {};
294+ void *LoadPtr (uptr p) const { return *reinterpret_cast <void **>(p); }
295+ };
296+ } // namespace
297+
291298// Scans the memory range, looking for byte patterns that point into allocator
292299// chunks. Marks those chunks with |tag| and adds them to |frontier|.
293300// There are two usage modes for this function: finding reachable chunks
294301// (|tag| = kReachable) and finding indirectly leaked chunks
295302// (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
296303// so |frontier| = 0.
297- void ScanRangeForPointers (uptr begin, uptr end, Frontier *frontier,
298- const char *region_type, ChunkTag tag) {
304+ template <class Accessor >
305+ void ScanForPointers (uptr begin, uptr end, Frontier *frontier,
306+ const char *region_type, ChunkTag tag,
307+ Accessor &accessor) {
299308 CHECK (tag == kReachable || tag == kIndirectlyLeaked );
300309 const uptr alignment = flags ()->pointer_alignment ();
301310 LOG_POINTERS (" Scanning %s range %p-%p.\n " , region_type, (void *)begin,
302311 (void *)end);
312+ accessor.Init (begin, end);
303313 uptr pp = begin;
304314 if (pp % alignment)
305315 pp = pp + alignment - pp % alignment;
306316 for (; pp + sizeof (void *) <= end; pp += alignment) {
307- void *p = * reinterpret_cast < void **> (pp);
317+ void *p = accessor. LoadPtr (pp);
308318# if SANITIZER_APPLE
309319 p = TransformPointer (p);
310320# endif
@@ -339,6 +349,12 @@ void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
339349 }
340350}
341351
352+ void ScanRangeForPointers (uptr begin, uptr end, Frontier *frontier,
353+ const char *region_type, ChunkTag tag) {
354+ DirectMemoryAccessor accessor;
355+ ScanForPointers (begin, end, frontier, region_type, tag, accessor);
356+ }
357+
342358// Scans a global range for pointers
343359void ScanGlobalRange (uptr begin, uptr end, Frontier *frontier) {
344360 uptr allocator_begin = 0 , allocator_end = 0 ;
@@ -356,14 +372,21 @@ void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
356372 }
357373}
358374
359- void ScanExtraStackRanges (const InternalMmapVector<Range> &ranges,
360- Frontier *frontier) {
375+ template <class Accessor >
376+ void ScanExtraStack (const InternalMmapVector<Range> &ranges, Frontier *frontier,
377+ Accessor &accessor) {
361378 for (uptr i = 0 ; i < ranges.size (); i++) {
362- ScanRangeForPointers (ranges[i].begin , ranges[i].end , frontier, " FAKE STACK" ,
363- kReachable );
379+ ScanForPointers (ranges[i].begin , ranges[i].end , frontier, " FAKE STACK" ,
380+ kReachable , accessor );
364381 }
365382}
366383
384+ void ScanExtraStackRanges (const InternalMmapVector<Range> &ranges,
385+ Frontier *frontier) {
386+ DirectMemoryAccessor accessor;
387+ ScanExtraStack (ranges, frontier, accessor);
388+ }
389+
367390# if SANITIZER_FUCHSIA
368391
369392// Fuchsia handles all threads together with its own callback.
@@ -399,10 +422,11 @@ static void ProcessThreadRegistry(Frontier *frontier) {
399422}
400423
401424// Scans thread data (stacks and TLS) for heap pointers.
425+ template <class Accessor >
402426static void ProcessThread (tid_t os_id, uptr sp,
403427 const InternalMmapVector<uptr> ®isters,
404428 InternalMmapVector<Range> &extra_ranges,
405- Frontier *frontier) {
429+ Frontier *frontier, Accessor &accessor ) {
406430 // `extra_ranges` is outside of the function and the loop to reused mapped
407431 // memory.
408432 CHECK (extra_ranges.empty ());
@@ -426,8 +450,8 @@ static void ProcessThread(tid_t os_id, uptr sp,
426450 uptr registers_begin = reinterpret_cast <uptr>(registers.data ());
427451 uptr registers_end =
428452 reinterpret_cast <uptr>(registers.data () + registers.size ());
429- ScanRangeForPointers (registers_begin, registers_end, frontier, " REGISTERS" ,
430- kReachable );
453+ ScanForPointers (registers_begin, registers_end, frontier, " REGISTERS" ,
454+ kReachable , accessor );
431455 }
432456
433457 if (flags ()->use_stacks ) {
@@ -451,9 +475,10 @@ static void ProcessThread(tid_t os_id, uptr sp,
451475 // Shrink the stack range to ignore out-of-scope values.
452476 stack_begin = sp;
453477 }
454- ScanRangeForPointers (stack_begin, stack_end, frontier, " STACK" , kReachable );
478+ ScanForPointers (stack_begin, stack_end, frontier, " STACK" , kReachable ,
479+ accessor);
455480 GetThreadExtraStackRangesLocked (os_id, &extra_ranges);
456- ScanExtraStackRanges (extra_ranges, frontier);
481+ ScanExtraStack (extra_ranges, frontier, accessor );
457482 }
458483
459484 if (flags ()->use_tls ) {
@@ -463,21 +488,23 @@ static void ProcessThread(tid_t os_id, uptr sp,
463488 // otherwise, only scan the non-overlapping portions
464489 if (cache_begin == cache_end || tls_end < cache_begin ||
465490 tls_begin > cache_end) {
466- ScanRangeForPointers (tls_begin, tls_end, frontier, " TLS" , kReachable );
491+ ScanForPointers (tls_begin, tls_end, frontier, " TLS" , kReachable ,
492+ accessor);
467493 } else {
468494 if (tls_begin < cache_begin)
469- ScanRangeForPointers (tls_begin, cache_begin, frontier, " TLS" ,
470- kReachable );
495+ ScanForPointers (tls_begin, cache_begin, frontier, " TLS" , kReachable ,
496+ accessor );
471497 if (tls_end > cache_end)
472- ScanRangeForPointers (cache_end, tls_end, frontier, " TLS" , kReachable );
498+ ScanForPointers (cache_end, tls_end, frontier, " TLS" , kReachable ,
499+ accessor);
473500 }
474501 }
475502# if SANITIZER_ANDROID
476503 auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /* dso_idd*/ ,
477504 void *arg) -> void {
478- ScanRangeForPointers (
505+ ScanForPointers (
479506 reinterpret_cast <uptr>(dtls_begin), reinterpret_cast <uptr>(dtls_end),
480- reinterpret_cast <Frontier *>(arg), " DTLS" , kReachable );
507+ reinterpret_cast <Frontier *>(arg), " DTLS" , kReachable , accessor );
481508 };
482509
483510 // FIXME: There might be a race-condition here (and in Bionic) if the
@@ -492,8 +519,8 @@ static void ProcessThread(tid_t os_id, uptr sp,
492519 if (dtls_beg < dtls_end) {
493520 LOG_THREADS (" DTLS %d at %p-%p.\n " , id, (void *)dtls_beg,
494521 (void *)dtls_end);
495- ScanRangeForPointers (dtls_beg, dtls_end, frontier, " DTLS" ,
496- kReachable );
522+ ScanForPointers (dtls_beg, dtls_end, frontier, " DTLS" , kReachable ,
523+ accessor );
497524 }
498525 });
499526 } else {
@@ -530,7 +557,8 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
530557 if (os_id == caller_tid)
531558 sp = caller_sp;
532559
533- ProcessThread (os_id, sp, registers, extra_ranges, frontier);
560+ DirectMemoryAccessor accessor;
561+ ProcessThread (os_id, sp, registers, extra_ranges, frontier, accessor);
534562 }
535563
536564 // Add pointers reachable from ThreadContexts
0 commit comments