Skip to content

[5.9][Reflection] Improve ownsAddress and metadataIsActor logic. #68637

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 20, 2023
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
55 changes: 34 additions & 21 deletions include/swift/RemoteInspection/ReflectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ class ReflectionContext
/// All buffers we need to keep around long term. This will automatically free them
/// when this object is destroyed.
std::vector<MemoryReader::ReadBytesResult> savedBuffers;
std::vector<std::tuple<RemoteAddress, RemoteAddress>> imageRanges;
std::vector<std::tuple<RemoteAddress, RemoteAddress>> textRanges;
std::vector<std::tuple<RemoteAddress, RemoteAddress>> dataRanges;

bool setupTargetPointers = false;
typename super::StoredPointer target_non_future_adapter = 0;
Expand Down Expand Up @@ -251,7 +252,7 @@ class ReflectionContext
uint64_t Offset = 0;

// Find the __TEXT segment.
typename T::SegmentCmd *Command = nullptr;
typename T::SegmentCmd *TextCommand = nullptr;
for (unsigned I = 0; I < NumCommands; ++I) {
auto CmdBuf = this->getReader().readBytes(
RemoteAddress(CmdStartAddress.getAddressData() + Offset),
Expand All @@ -260,15 +261,15 @@ class ReflectionContext
return false;
auto CmdHdr = reinterpret_cast<typename T::SegmentCmd *>(CmdBuf.get());
if (strncmp(CmdHdr->segname, "__TEXT", sizeof(CmdHdr->segname)) == 0) {
Command = CmdHdr;
TextCommand = CmdHdr;
savedBuffers.push_back(std::move(CmdBuf));
break;
}
Offset += CmdHdr->cmdsize;
}

// No __TEXT segment, bail out.
if (!Command)
if (!TextCommand)
return false;

// Find the load command offset.
Expand All @@ -291,7 +292,7 @@ class ReflectionContext
if (!Sections)
return false;

auto Slide = ImageStart.getAddressData() - Command->vmaddr;
auto Slide = ImageStart.getAddressData() - TextCommand->vmaddr;
auto SectionsBuf = reinterpret_cast<const char *>(Sections.get());

auto findMachOSectionByName = [&](llvm::StringRef Name)
Expand Down Expand Up @@ -355,22 +356,27 @@ class ReflectionContext

auto InfoID = this->addReflectionInfo(info);

// Find the __DATA segment.
auto TextSegmentStart = Slide + TextCommand->vmaddr;
auto TextSegmentEnd = TextSegmentStart + TextCommand->vmsize;
textRanges.push_back(std::make_tuple(RemoteAddress(TextSegmentStart),
RemoteAddress(TextSegmentEnd)));

// Find the __DATA segments.
for (unsigned I = 0; I < NumCommands; ++I) {
auto CmdBuf = this->getReader().readBytes(
RemoteAddress(CmdStartAddress.getAddressData() + Offset),
SegmentCmdHdrSize);
if (!CmdBuf)
return false;
auto CmdHdr = reinterpret_cast<typename T::SegmentCmd *>(CmdBuf.get());
if (strncmp(CmdHdr->segname, "__DATA", sizeof(CmdHdr->segname)) == 0) {
auto DataSegmentEnd =
ImageStart.getAddressData() + CmdHdr->vmaddr + CmdHdr->vmsize;
assert(DataSegmentEnd > ImageStart.getAddressData() &&
// Look for any segment name starting with __DATA.
if (strncmp(CmdHdr->segname, "__DATA", 6) == 0) {
auto DataSegmentStart = Slide + CmdHdr->vmaddr;
auto DataSegmentEnd = DataSegmentStart + CmdHdr->vmsize;
assert(DataSegmentStart > ImageStart.getAddressData() &&
"invalid range for __DATA");
imageRanges.push_back(
std::make_tuple(ImageStart, RemoteAddress(DataSegmentEnd)));
break;
dataRanges.push_back(std::make_tuple(RemoteAddress(DataSegmentStart),
RemoteAddress(DataSegmentEnd)));
}
Offset += CmdHdr->cmdsize;
}
Expand Down Expand Up @@ -829,9 +835,11 @@ class ReflectionContext
return ownsAddress(RemoteAddress(*MetadataAddress));
}

/// Returns true if the address falls within a registered image.
bool ownsAddressRaw(RemoteAddress Address) {
for (auto Range : imageRanges) {
/// Returns true if the address falls within the given address ranges.
bool ownsAddress(
RemoteAddress Address,
const std::vector<std::tuple<RemoteAddress, RemoteAddress>> &ranges) {
for (auto Range : ranges) {
auto Start = std::get<0>(Range);
auto End = std::get<1>(Range);
if (Start.getAddressData() <= Address.getAddressData()
Expand All @@ -843,11 +851,14 @@ class ReflectionContext
}

/// Returns true if the address is known to the reflection context.
/// Currently, that means that either the address falls within a registered
/// image, or the address points to a Metadata whose type context descriptor
/// is within a registered image.
/// Currently, that means that either the address falls within the text or
/// data segments of a registered image, or the address points to a Metadata
/// whose type context descriptor is within the text segment of a registered
/// image.
bool ownsAddress(RemoteAddress Address) {
if (ownsAddressRaw(Address))
if (ownsAddress(Address, textRanges))
return true;
if (ownsAddress(Address, dataRanges))
return true;

// This is usually called on a Metadata address which might have been
Expand All @@ -856,7 +867,7 @@ class ReflectionContext
if (auto Metadata = readMetadata(Address.getAddressData()))
if (auto DescriptorAddress =
super::readAddressOfNominalTypeDescriptor(Metadata, true))
if (ownsAddressRaw(RemoteAddress(DescriptorAddress)))
if (ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
return true;

return false;
Expand Down Expand Up @@ -1206,6 +1217,8 @@ class ReflectionContext
super::readAddressOfNominalTypeDescriptor(Metadata);
if (!DescriptorAddress)
return false;
if (!ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
return false;

auto DescriptorBytes =
getReader().readBytes(RemoteAddress(DescriptorAddress),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,17 @@ fileprivate class ConcurrencyDumper {
print(" no jobs queued")
} else {
print(" job queue: \(jobStr(job))")
while job != 0 {
let limit = 1000
for i in 1 ... limit {
job = swift_reflection_nextJob(context, job);
if job != 0 {
print(" \(jobStr(job))")
} else {
break
}

if i == limit {
print(" ...truncated...")
}
}
}
Expand Down