Skip to content

Commit a456d20

Browse files
Merge pull request #11718 from augusto2112/remote-mirr-indirect-addr-6.2
[lldb] Fix LLDBMemoryReader resolving GOT pointers incorrectly
2 parents aeffdf3 + 774ece6 commit a456d20

File tree

7 files changed

+159
-0
lines changed

7 files changed

+159
-0
lines changed

lldb/include/lldb/Core/Section.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ class Section : public std::enable_shared_from_this<Section>,
262262
/// return true.
263263
bool ContainsOnlyDebugInfo() const;
264264

265+
/// Returns true if this is a global offset table section.
266+
bool IsGOTSection() const;
267+
265268
protected:
266269
ObjectFile *m_obj_file; // The object file that data for this section should
267270
// be read from

lldb/include/lldb/Symbol/ObjectFile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,12 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
740740
return false;
741741
}
742742

743+
/// Returns true if the section is a global offset table section.
744+
virtual bool IsGOTSection(const lldb_private::Section &section) const {
745+
assert(section.GetObjectFile() == this && "Wrong object file!");
746+
return false;
747+
}
748+
743749
/// Get a hash that can be used for caching object file releated information.
744750
///
745751
/// Data for object files can be cached between runs of debug sessions and

lldb/source/Core/Section.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,9 @@ bool Section::ContainsOnlyDebugInfo() const {
471471
return false;
472472
}
473473

474+
bool Section::IsGOTSection() const {
475+
return GetObjectFile()->IsGOTSection(*this);
476+
}
474477

475478
#pragma mark SectionList
476479

lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
316442
bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address,
317443
uint8_t *dest, uint64_t size) {
318444
auto [success, _] = readBytesImpl(address, dest, size);

lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
8080
std::optional<swift::remote::RemoteAddress>
8181
resolveRemoteAddress(swift::remote::RemoteAddress address) const override;
8282

83+
swift::reflection::RemoteAddress
84+
resolveIndirectAddressAtOffset(swift::reflection::RemoteAddress address,
85+
uint64_t offset,
86+
bool directnessEncodedInOffset) override;
87+
8388
bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest,
8489
uint64_t size) override;
8590

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6305,6 +6305,20 @@ Section *ObjectFileMachO::GetMachHeaderSection() {
63056305
return nullptr;
63066306
}
63076307

6308+
bool ObjectFileMachO::IsGOTSection(const lldb_private::Section &section) const {
6309+
assert(section.GetObjectFile() == this && "Wrong object file!");
6310+
SectionSP segment = section.GetParent();
6311+
if (!segment)
6312+
return false;
6313+
6314+
bool is_data_const_got =
6315+
segment->GetName() == "__DATA_CONST" && section.GetName() == "__got";
6316+
bool is_auth_const_ptr =
6317+
segment->GetName() == "__AUTH_CONST" &&
6318+
(section.GetName() == "__auth_got" || section.GetName() == "__auth_ptr");
6319+
return is_data_const_got || is_auth_const_ptr;
6320+
}
6321+
63086322
bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
63096323
if (!section)
63106324
return false;

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class ObjectFileMachO : public lldb_private::ObjectFile {
159159

160160
lldb_private::Section *GetMachHeaderSection();
161161

162+
bool IsGOTSection(const lldb_private::Section &section) const override;
163+
162164
// PluginInterface protocol
163165
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
164166

0 commit comments

Comments
 (0)