@@ -293,6 +293,27 @@ struct DirectMemoryAccessor {
293293 void Init (uptr begin, uptr end) {};
294294 void *LoadPtr (uptr p) const { return *reinterpret_cast <void **>(p); }
295295};
296+
297+ struct CopyMemoryAccessor {
298+ void Init (uptr begin, uptr end) {
299+ this ->begin = begin;
300+ buffer.clear ();
301+ buffer.resize (end - begin);
302+ MemCpyAccessible (buffer.data (), reinterpret_cast <void *>(begin),
303+ buffer.size ());
304+ };
305+
306+ void *LoadPtr (uptr p) const {
307+ uptr offset = p - begin;
308+ CHECK_LE (offset + sizeof (void *), reinterpret_cast <uptr>(buffer.size ()));
309+ return *reinterpret_cast <void **>(offset +
310+ reinterpret_cast <uptr>(buffer.data ()));
311+ }
312+
313+ private:
314+ uptr begin;
315+ InternalMmapVector<char > buffer;
316+ };
296317} // namespace
297318
298319// Scans the memory range, looking for byte patterns that point into allocator
@@ -373,18 +394,18 @@ void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
373394}
374395
375396template <class Accessor >
376- void ScanExtraStack (const InternalMmapVector<Range> &ranges, Frontier *frontier,
377- Accessor &accessor) {
397+ void ScanRanges (const InternalMmapVector<Range> &ranges, Frontier *frontier,
398+ const char *region_type, Accessor &accessor) {
378399 for (uptr i = 0 ; i < ranges.size (); i++) {
379- ScanForPointers (ranges[i].begin , ranges[i].end , frontier, " FAKE STACK " ,
400+ ScanForPointers (ranges[i].begin , ranges[i].end , frontier, region_type ,
380401 kReachable , accessor);
381402 }
382403}
383404
384405void ScanExtraStackRanges (const InternalMmapVector<Range> &ranges,
385406 Frontier *frontier) {
386407 DirectMemoryAccessor accessor;
387- ScanExtraStack (ranges, frontier, accessor);
408+ ScanRanges (ranges, frontier, " FAKE STACK " , accessor);
388409}
389410
390411# if SANITIZER_FUCHSIA
@@ -478,7 +499,7 @@ static void ProcessThread(tid_t os_id, uptr sp,
478499 ScanForPointers (stack_begin, stack_end, frontier, " STACK" , kReachable ,
479500 accessor);
480501 GetThreadExtraStackRangesLocked (os_id, &extra_ranges);
481- ScanExtraStack (extra_ranges, frontier, accessor);
502+ ScanRanges (extra_ranges, frontier, " FAKE STACK " , accessor);
482503 }
483504
484505 if (flags ()->use_tls ) {
@@ -500,13 +521,14 @@ static void ProcessThread(tid_t os_id, uptr sp,
500521 }
501522 }
502523# if SANITIZER_ANDROID
524+ extra_ranges.clear ();
503525 auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /* dso_idd*/ ,
504526 void *arg) -> void {
505- ScanForPointers (
506- reinterpret_cast <uptr>(dtls_begin), reinterpret_cast <uptr>(dtls_end ),
507- reinterpret_cast <Frontier *>(arg), " DTLS " , kReachable , accessor );
527+ reinterpret_cast <InternalMmapVector<Range> *>(arg)-> push_back (
528+ { reinterpret_cast <uptr>(dtls_begin),
529+ reinterpret_cast <uptr>(dtls_end)} );
508530 };
509-
531+ ScanRanges (extra_ranges, frontier, " DTLS " , accessor);
510532 // FIXME: There might be a race-condition here (and in Bionic) if the
511533 // thread is suspended in the middle of updating its DTLS. IOWs, we
512534 // could scan already freed memory. (probably fine for now)
@@ -535,6 +557,7 @@ static void ProcessThread(tid_t os_id, uptr sp,
535557static void ProcessThreads (SuspendedThreadsList const &suspended_threads,
536558 Frontier *frontier, tid_t caller_tid,
537559 uptr caller_sp) {
560+ InternalMmapVector<tid_t > done_threads;
538561 InternalMmapVector<uptr> registers;
539562 InternalMmapVector<Range> extra_ranges;
540563 for (uptr i = 0 ; i < suspended_threads.ThreadCount (); i++) {
@@ -559,6 +582,25 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
559582
560583 DirectMemoryAccessor accessor;
561584 ProcessThread (os_id, sp, registers, extra_ranges, frontier, accessor);
585+ if (flags ()->use_detached )
586+ done_threads.push_back (os_id);
587+ }
588+
589+ if (flags ()->use_detached ) {
590+ CopyMemoryAccessor accessor;
591+ InternalMmapVector<tid_t > known_threads;
592+ GetRunningThreadsLocked (&known_threads);
593+ Sort (done_threads.data (), done_threads.size ());
594+ for (tid_t os_id : known_threads) {
595+ registers.clear ();
596+ extra_ranges.clear ();
597+
598+ uptr i = InternalLowerBound (done_threads, os_id);
599+ if (i >= done_threads.size () || done_threads[i] != os_id) {
600+ uptr sp = (os_id == caller_tid) ? caller_sp : 0 ;
601+ ProcessThread (os_id, sp, registers, extra_ranges, frontier, accessor);
602+ }
603+ }
562604 }
563605
564606 // Add pointers reachable from ThreadContexts
0 commit comments