Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lldb/include/lldb/Core/Section.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ class Section : public std::enable_shared_from_this<Section>,
/// return true.
bool ContainsOnlyDebugInfo() const;

/// Returns true if this is a global offset table section.
bool IsGOTSection() const;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please upstream this afterwards!


protected:
ObjectFile *m_obj_file; // The object file that data for this section should
// be read from
Expand Down
6 changes: 6 additions & 0 deletions lldb/include/lldb/Symbol/ObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,12 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
return false;
}

/// Returns true if the section is a global offset table section.
virtual bool IsGOTSection(const lldb_private::Section &section) const {
assert(section.GetObjectFile() == this && "Wrong object file!");
return false;
}

/// Get a hash that can be used for caching object file releated information.
///
/// Data for object files can be cached between runs of debug sessions and
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Core/Section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,10 @@ bool Section::ContainsOnlyDebugInfo() const {
return false;
}

bool Section::IsGOTSection() const {
return GetObjectFile()->IsGOTSection(*this);
}

#pragma mark SectionList

SectionList &SectionList::operator=(const SectionList &rhs) {
Expand Down
126 changes: 126 additions & 0 deletions lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,132 @@ LLDBMemoryReader::resolvePointer(swift::remote::RemoteAddress address,
return tagged_pointer;
}

swift::reflection::RemoteAddress
LLDBMemoryReader::resolveIndirectAddressAtOffset(
swift::reflection::RemoteAddress address, uint64_t offset,
bool directnessEncodedInOffset) {
// Usually, simply adding the address with the offset will produce the correct
// remote address.
//
// However, on Apple platforms, the shared cache can coalesce pointers in the
// global offset table from multiple images into one location, patch all the
// uses to point to the new location, and zero out the original pointer. In
// this case, LLDBMemoryReader needs to be conservative and re-fetch the
// offset from live memory to ensure it points to the new, coalesced location
// instead.
Log *log = GetLog(LLDBLog::Types);

LLDB_LOGV(log,
"[MemoryReader::resolveAddressAtOffset] Asked to resolve address "
"{0:x} at offset {1:x}",
address.getRawAddress(), offset);

swift::reflection::RemoteAddress offset_address = address + offset;

if (!readMetadataFromFileCacheEnabled())
return offset_address;

// Addresses in the process can be read directly.
if (offset_address.getAddressSpace() ==
swift::reflection::RemoteAddress::DefaultAddressSpace)
return offset_address;

// Check if offset_address points to a GOT entry.
std::optional<Address> maybeAddr =
resolveRemoteAddressFromSymbolObjectFile(offset_address);

if (!maybeAddr)
maybeAddr = remoteAddressToLLDBAddress(offset_address);

if (!maybeAddr) {
LLDB_LOGV(log,
"[MemoryReader::resolveAddressAtOffset] could not resolve "
"address {0:x}",
offset_address.getRawAddress());
return offset_address;
}

Address lldb_offset_address = *maybeAddr;
if (!lldb_offset_address.IsSectionOffset()) {
LLDB_LOGV(
log,
"[MemoryReader::resolveAddressAtOffset] lldb offset address has no "
"section {0:x}",
offset_address.getRawAddress());
return offset_address;
}

// This is only necessary on Apple platforms.
ObjectFile *obj_file = lldb_offset_address.GetModule()->GetObjectFile();
if (!obj_file || !obj_file->GetArchitecture().GetTriple().isOSDarwin())
return offset_address;

SectionSP section = lldb_offset_address.GetSection();
if (!section->IsGOTSection())
return offset_address;

// offset_address is in a GOT section. Re-read the offset from the base
// address in live memory, since the offset in live memory can have been
// patched in the shared cache to point somewhere else.
std::optional<Address> maybe_lldb_addr =
resolveRemoteAddressFromSymbolObjectFile(address);

if (!maybe_lldb_addr)
maybe_lldb_addr = remoteAddressToLLDBAddress(address);

if (!maybe_lldb_addr) {
LLDB_LOGV(log,
"[MemoryReader::resolveAddressAtOffset] could not resolve offset "
"address {0:x}",
address.getRawAddress());
return offset_address;
}

auto lldb_addr = *maybe_lldb_addr;
Target &target(m_process.GetTarget());
Status error;
const bool force_live_memory = true;
bool did_read_live_memory = false;

// Relative offsets are always 4 bytes long, regardless of target.
uint32_t live_offset = 0;
size_t size = sizeof(live_offset);
if (size !=
target.ReadMemory(lldb_addr, &live_offset, size, error, force_live_memory,
/*load_addr_ptr=*/nullptr, &did_read_live_memory)) {
LLDB_LOG(log,
"[MemoryReader::resolveAddressAtOffset] Resolve address returned "
"different bytes than asked "
"for {0:x}",
lldb_addr.GetLoadAddress(&target));
return offset_address;
}
if (error.Fail()) {
LLDB_LOG(log,
"[MemoryReader::resolveAddressAtOffset] memory read returned "
"error: {0}",
error.AsCString());
return offset_address;
}
// Some Swift metadata encodes the directness directly into the offset,
// in that case clear the directness bit.
if (directnessEncodedInOffset)
live_offset &= ~1u;

// Now, get the live address counterpart of the lldb address this function
// started with, and add the live offset we just read to it.
addr_t live_address = lldb_addr.GetLoadAddress(&target);
LLDB_LOGV(
log,
"[MemoryReader::resolveAddressAtOffset] Succesfully resolved address "
"into live address {0:x} and offset {1:x} resulting in address {2:x}",
live_address, live_offset, live_address + live_offset);

return swift::remote::RemoteAddress(
live_address + live_offset,
swift::remote::RemoteAddress::DefaultAddressSpace);
}

bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address,
uint8_t *dest, uint64_t size) {
auto read_bytes_result = readBytesImpl(address, dest, size);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
std::optional<swift::remote::RemoteAddress>
resolveRemoteAddress(swift::remote::RemoteAddress address) const override;

swift::reflection::RemoteAddress
resolveIndirectAddressAtOffset(swift::reflection::RemoteAddress address,
uint64_t offset,
bool directnessEncodedInOffset) override;

bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest,
uint64_t size) override;

Expand Down
14 changes: 14 additions & 0 deletions lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6069,6 +6069,20 @@ Section *ObjectFileMachO::GetMachHeaderSection() {
return nullptr;
}

bool ObjectFileMachO::IsGOTSection(const lldb_private::Section &section) const {
assert(section.GetObjectFile() == this && "Wrong object file!");
SectionSP segment = section.GetParent();
if (!segment)
return false;

bool is_data_const_got =
segment->GetName() == "__DATA_CONST" && section.GetName() == "__got";
bool is_auth_const_ptr =
segment->GetName() == "__AUTH_CONST" &&
(section.GetName() == "__auth_got" || section.GetName() == "__auth_ptr");
return is_data_const_got || is_auth_const_ptr;
}

bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
if (!section)
return false;
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ class ObjectFileMachO : public lldb_private::ObjectFile {

lldb_private::Section *GetMachHeaderSection();

bool IsGOTSection(const lldb_private::Section &section) const override;

// PluginInterface protocol
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }

Expand Down