@@ -317,6 +317,132 @@ LLDBMemoryReader::resolvePointer(swift::remote::RemoteAddress address,
317317  return  tagged_pointer;
318318}
319319
320+ swift::reflection::RemoteAddress
321+ LLDBMemoryReader::resolveIndirectAddressAtOffset (
322+     swift::reflection::RemoteAddress address, uint64_t  offset,
323+     bool  directnessEncodedInOffset) {
324+   //  Usually, simply adding the address with the offset will produce the correct
325+   //  remote address.
326+   // 
327+   //  However, on Apple platforms, the shared cache can coalesce pointers in the
328+   //  global offset table from multiple images into one location, patch all the
329+   //  uses to point to the new location, and zero out the original pointer. In
330+   //  this case, LLDBMemoryReader needs to be conservative and re-fetch the
331+   //  offset from live memory to ensure it points to the new, coalesced location
332+   //  instead.
333+   Log *log = GetLog (LLDBLog::Types);
334+ 
335+   LLDB_LOGV (log,
336+             " [MemoryReader::resolveAddressAtOffset] Asked to resolve address " 
337+             " {0:x} at offset {1:x}" 
338+             address.getRawAddress (), offset);
339+ 
340+   swift::reflection::RemoteAddress offset_address = address + offset;
341+ 
342+   if  (!readMetadataFromFileCacheEnabled ())
343+     return  offset_address;
344+ 
345+   //  Addresses in the process can be read directly.
346+   if  (offset_address.getAddressSpace () ==
347+       swift::reflection::RemoteAddress::DefaultAddressSpace)
348+     return  offset_address;
349+ 
350+   //  Check if offset_address points to a GOT entry.
351+   std::optional<Address> maybeAddr =
352+       resolveRemoteAddressFromSymbolObjectFile (offset_address);
353+ 
354+   if  (!maybeAddr)
355+     maybeAddr = remoteAddressToLLDBAddress (offset_address);
356+ 
357+   if  (!maybeAddr) {
358+     LLDB_LOGV (log,
359+               " [MemoryReader::resolveAddressAtOffset] could not resolve " 
360+               " address {0:x}" 
361+               offset_address.getRawAddress ());
362+     return  offset_address;
363+   }
364+ 
365+   Address lldb_offset_address = *maybeAddr;
366+   if  (!lldb_offset_address.IsSectionOffset ()) {
367+     LLDB_LOGV (
368+         log,
369+         " [MemoryReader::resolveAddressAtOffset] lldb offset address has no " 
370+         " section {0:x}" 
371+         offset_address.getRawAddress ());
372+     return  offset_address;
373+   }
374+ 
375+   //  This is only necessary on Apple platforms.
376+   ObjectFile *obj_file = lldb_offset_address.GetModule ()->GetObjectFile ();
377+   if  (!obj_file || !obj_file->GetArchitecture ().GetTriple ().isOSDarwin ())
378+     return  offset_address;
379+ 
380+   SectionSP section = lldb_offset_address.GetSection ();
381+   if  (!section->IsGOTSection ())
382+     return  offset_address;
383+ 
384+   //  offset_address is in a GOT section. Re-read the offset from the base
385+   //  address in live memory, since the offset in live memory can have been
386+   //  patched in the shared cache to point somewhere else.
387+   std::optional<Address> maybe_lldb_addr =
388+       resolveRemoteAddressFromSymbolObjectFile (address);
389+ 
390+   if  (!maybe_lldb_addr)
391+     maybe_lldb_addr = remoteAddressToLLDBAddress (address);
392+ 
393+   if  (!maybe_lldb_addr) {
394+     LLDB_LOGV (log,
395+               " [MemoryReader::resolveAddressAtOffset] could not resolve offset " 
396+               " address {0:x}" 
397+               address.getRawAddress ());
398+     return  offset_address;
399+   }
400+ 
401+   auto  lldb_addr = *maybe_lldb_addr;
402+   Target &target (m_process.GetTarget ());
403+   Status error;
404+   const  bool  force_live_memory = true ;
405+   bool  did_read_live_memory = false ;
406+ 
407+   //  Relative offsets are always 4 bytes long, regardless of target.
408+   uint32_t  live_offset = 0 ;
409+   size_t  size = sizeof (live_offset);
410+   if  (size !=
411+       target.ReadMemory (lldb_addr, &live_offset, size, error, force_live_memory,
412+                         /* load_addr_ptr=*/ nullptr , &did_read_live_memory)) {
413+     LLDB_LOG (log,
414+              " [MemoryReader::resolveAddressAtOffset] Resolve address returned " 
415+              " different bytes than asked " 
416+              " for {0:x}" 
417+              lldb_addr.GetLoadAddress (&target));
418+     return  offset_address;
419+   }
420+   if  (error.Fail ()) {
421+     LLDB_LOG (log,
422+              " [MemoryReader::resolveAddressAtOffset] memory read returned " 
423+              " error: {0}" 
424+              error.AsCString ());
425+     return  offset_address;
426+   }
427+   //  Some Swift metadata encodes the directness directly into the offset,
428+   //  in that case clear the directness bit.
429+   if  (directnessEncodedInOffset)
430+     live_offset &= ~1u ;
431+ 
432+   //  Now, get the live address counterpart of the lldb address this function
433+   //  started with, and add the live offset we just read to it.
434+   addr_t  live_address = lldb_addr.GetLoadAddress (&target);
435+   LLDB_LOGV (
436+       log,
437+       " [MemoryReader::resolveAddressAtOffset] Succesfully resolved address " 
438+       " into live address {0:x} and offset {1:x} resulting in address {2:x}" 
439+       live_address, live_offset, live_address + live_offset);
440+ 
441+   return  swift::remote::RemoteAddress (
442+       live_address + live_offset,
443+       swift::remote::RemoteAddress::DefaultAddressSpace);
444+ }
445+ 
320446bool  LLDBMemoryReader::readBytes (swift::remote::RemoteAddress address,
321447                                 uint8_t  *dest, uint64_t  size) {
322448  auto  read_bytes_result = readBytesImpl (address, dest, size);
0 commit comments