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