@@ -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