Skip to content

Commit 1433fd8

Browse files
authored
Merge pull request #11687 from augusto2112/remote-mirr-indirect-addr
[lldb] Fix LLDBMemoryReader resolving GOT pointers incorrectly
2 parents 96caf55 + eddff61 commit 1433fd8

File tree

7 files changed

+160
-0
lines changed

7 files changed

+160
-0
lines changed

lldb/include/lldb/Core/Section.h

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

281+
/// Returns true if this is a global offset table section.
282+
bool IsGOTSection() const;
283+
281284
protected:
282285
ObjectFile *m_obj_file; // The object file that data for this section should
283286
// be read from

lldb/include/lldb/Symbol/ObjectFile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,12 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
761761
return false;
762762
}
763763

764+
/// Returns true if the section is a global offset table section.
765+
virtual bool IsGOTSection(const lldb_private::Section &section) const {
766+
assert(section.GetObjectFile() == this && "Wrong object file!");
767+
return false;
768+
}
769+
764770
/// Get a hash that can be used for caching object file releated information.
765771
///
766772
/// Data for object files can be cached between runs of debug sessions and

lldb/source/Core/Section.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,10 @@ bool Section::ContainsOnlyDebugInfo() const {
473473
return false;
474474
}
475475

476+
bool Section::IsGOTSection() const {
477+
return GetObjectFile()->IsGOTSection(*this);
478+
}
479+
476480
#pragma mark SectionList
477481

478482
SectionList &SectionList::operator=(const SectionList &rhs) {

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

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
320446
bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address,
321447
uint8_t *dest, uint64_t size) {
322448
auto read_bytes_result = 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
@@ -87,6 +87,11 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
8787
std::optional<swift::remote::RemoteAddress>
8888
resolveRemoteAddress(swift::remote::RemoteAddress address) const override;
8989

90+
swift::reflection::RemoteAddress
91+
resolveIndirectAddressAtOffset(swift::reflection::RemoteAddress address,
92+
uint64_t offset,
93+
bool directnessEncodedInOffset) override;
94+
9095
bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest,
9196
uint64_t size) override;
9297

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6069,6 +6069,20 @@ Section *ObjectFileMachO::GetMachHeaderSection() {
60696069
return nullptr;
60706070
}
60716071

6072+
bool ObjectFileMachO::IsGOTSection(const lldb_private::Section &section) const {
6073+
assert(section.GetObjectFile() == this && "Wrong object file!");
6074+
SectionSP segment = section.GetParent();
6075+
if (!segment)
6076+
return false;
6077+
6078+
bool is_data_const_got =
6079+
segment->GetName() == "__DATA_CONST" && section.GetName() == "__got";
6080+
bool is_auth_const_ptr =
6081+
segment->GetName() == "__AUTH_CONST" &&
6082+
(section.GetName() == "__auth_got" || section.GetName() == "__auth_ptr");
6083+
return is_data_const_got || is_auth_const_ptr;
6084+
}
6085+
60726086
bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
60736087
if (!section)
60746088
return false;

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

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

163163
lldb_private::Section *GetMachHeaderSection();
164164

165+
bool IsGOTSection(const lldb_private::Section &section) const override;
166+
165167
// PluginInterface protocol
166168
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
167169

0 commit comments

Comments
 (0)