@@ -288,23 +288,32 @@ static inline bool MaybeUserPointer(uptr p) {
288288# endif
289289}
290290
291+ namespace {
292+ struct DirectLoader {
293+ void Init (uptr begin, uptr end) {};
294+ void *operator ()(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 S >
305+ void ScanForPointers (uptr begin, uptr end, Frontier *frontier,
306+ const char *region_type, ChunkTag tag, S &scanner) {
299307 CHECK (tag == kReachable || tag == kIndirectlyLeaked );
300308 const uptr alignment = flags ()->pointer_alignment ();
301309 LOG_POINTERS (" Scanning %s range %p-%p.\n " , region_type, (void *)begin,
302310 (void *)end);
311+ scanner.Init (begin, end);
303312 uptr pp = begin;
304313 if (pp % alignment)
305314 pp = pp + alignment - pp % alignment;
306315 for (; pp + sizeof (void *) <= end; pp += alignment) {
307- void *p = * reinterpret_cast < void **> (pp);
316+ void *p = scanner (pp);
308317# if SANITIZER_APPLE
309318 p = TransformPointer (p);
310319# endif
@@ -339,6 +348,12 @@ void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
339348 }
340349}
341350
351+ void ScanRangeForPointers (uptr begin, uptr end, Frontier *frontier,
352+ const char *region_type, ChunkTag tag) {
353+ DirectLoader scanner;
354+ ScanForPointers (begin, end, frontier, region_type, tag, scanner);
355+ }
356+
342357// Scans a global range for pointers
343358void ScanGlobalRange (uptr begin, uptr end, Frontier *frontier) {
344359 uptr allocator_begin = 0 , allocator_end = 0 ;
@@ -356,14 +371,21 @@ void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
356371 }
357372}
358373
359- void ScanExtraStackRanges (const InternalMmapVector<Range> &ranges,
360- Frontier *frontier) {
374+ template <class S >
375+ void ScanExtraStack (const InternalMmapVector<Range> &ranges, Frontier *frontier,
376+ S &scanner) {
361377 for (uptr i = 0 ; i < ranges.size (); i++) {
362- ScanRangeForPointers (ranges[i].begin , ranges[i].end , frontier, " FAKE STACK" ,
363- kReachable );
378+ ScanForPointers (ranges[i].begin , ranges[i].end , frontier, " FAKE STACK" ,
379+ kReachable , scanner );
364380 }
365381}
366382
383+ void ScanExtraStackRanges (const InternalMmapVector<Range> &ranges,
384+ Frontier *frontier) {
385+ DirectLoader scanner;
386+ ScanExtraStack (ranges, frontier, scanner);
387+ }
388+
367389# if SANITIZER_FUCHSIA
368390
369391// Fuchsia handles all threads together with its own callback.
@@ -399,10 +421,11 @@ static void ProcessThreadRegistry(Frontier *frontier) {
399421}
400422
401423// Scans thread data (stacks and TLS) for heap pointers.
424+ template <class S >
402425static void ProcessThread (tid_t os_id, uptr sp,
403426 const InternalMmapVector<uptr> ®isters,
404427 InternalMmapVector<Range> &extra_ranges,
405- Frontier *frontier) {
428+ Frontier *frontier, S &scanner ) {
406429 // `extra_ranges` is outside of the function and the loop to reused mapped
407430 // memory.
408431 CHECK (extra_ranges.empty ());
@@ -426,8 +449,8 @@ static void ProcessThread(tid_t os_id, uptr sp,
426449 uptr registers_begin = reinterpret_cast <uptr>(registers.data ());
427450 uptr registers_end =
428451 reinterpret_cast <uptr>(registers.data () + registers.size ());
429- ScanRangeForPointers (registers_begin, registers_end, frontier, " REGISTERS" ,
430- kReachable );
452+ ScanForPointers (registers_begin, registers_end, frontier, " REGISTERS" ,
453+ kReachable , scanner );
431454 }
432455
433456 if (flags ()->use_stacks ) {
@@ -451,9 +474,10 @@ static void ProcessThread(tid_t os_id, uptr sp,
451474 // Shrink the stack range to ignore out-of-scope values.
452475 stack_begin = sp;
453476 }
454- ScanRangeForPointers (stack_begin, stack_end, frontier, " STACK" , kReachable );
477+ ScanForPointers (stack_begin, stack_end, frontier, " STACK" , kReachable ,
478+ scanner);
455479 GetThreadExtraStackRangesLocked (os_id, &extra_ranges);
456- ScanExtraStackRanges (extra_ranges, frontier);
480+ ScanExtraStack (extra_ranges, frontier, scanner );
457481 }
458482
459483 if (flags ()->use_tls ) {
@@ -463,21 +487,23 @@ static void ProcessThread(tid_t os_id, uptr sp,
463487 // otherwise, only scan the non-overlapping portions
464488 if (cache_begin == cache_end || tls_end < cache_begin ||
465489 tls_begin > cache_end) {
466- ScanRangeForPointers (tls_begin, tls_end, frontier, " TLS" , kReachable );
490+ ScanForPointers (tls_begin, tls_end, frontier, " TLS" , kReachable ,
491+ scanner);
467492 } else {
468493 if (tls_begin < cache_begin)
469- ScanRangeForPointers (tls_begin, cache_begin, frontier, " TLS" ,
470- kReachable );
494+ ScanForPointers (tls_begin, cache_begin, frontier, " TLS" , kReachable ,
495+ scanner );
471496 if (tls_end > cache_end)
472- ScanRangeForPointers (cache_end, tls_end, frontier, " TLS" , kReachable );
497+ ScanForPointers (cache_end, tls_end, frontier, " TLS" , kReachable ,
498+ scanner);
473499 }
474500 }
475501# if SANITIZER_ANDROID
476502 auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /* dso_idd*/ ,
477503 void *arg) -> void {
478- ScanRangeForPointers (
504+ ScanForPointers (
479505 reinterpret_cast <uptr>(dtls_begin), reinterpret_cast <uptr>(dtls_end),
480- reinterpret_cast <Frontier *>(arg), " DTLS" , kReachable );
506+ reinterpret_cast <Frontier *>(arg), " DTLS" , kReachable , scanner );
481507 };
482508
483509 // FIXME: There might be a race-condition here (and in Bionic) if the
@@ -492,8 +518,8 @@ static void ProcessThread(tid_t os_id, uptr sp,
492518 if (dtls_beg < dtls_end) {
493519 LOG_THREADS (" DTLS %d at %p-%p.\n " , id, (void *)dtls_beg,
494520 (void *)dtls_end);
495- ScanRangeForPointers (dtls_beg, dtls_end, frontier, " DTLS" ,
496- kReachable );
521+ ScanForPointers (dtls_beg, dtls_end, frontier, " DTLS" , kReachable ,
522+ scanner );
497523 }
498524 });
499525 } else {
@@ -530,7 +556,8 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
530556 if (os_id == caller_tid)
531557 sp = caller_sp;
532558
533- ProcessThread (os_id, sp, registers, extra_ranges, frontier);
559+ DirectLoader scanner;
560+ ProcessThread (os_id, sp, registers, extra_ranges, frontier, scanner);
534561 }
535562
536563 // Add pointers reachable from ThreadContexts
0 commit comments