Skip to content

Commit ce6de7e

Browse files
committed
swift-reflection-dump: ELF ObjectMemoryReader support for relocations
Collect the relative and symbol relocations from ELF images in order to resolve pointer values read from disk. This allows us to enable symbolic-referencing-all-the-things for ELF platforms.
1 parent 333f0db commit ce6de7e

File tree

3 files changed

+77
-6
lines changed

3 files changed

+77
-6
lines changed

lib/IRGen/IRGenMangler.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,11 @@ IRGenMangler::withSymbolicReferences(IRGenModule &IGM,
119119
}
120120
}
121121

122-
// TODO: ObjectMemoryReader for ELF and PE platforms still does not
122+
// TODO: ObjectMemoryReader for PE platforms still does not
123123
// implement symbol relocations. For now, on non-Mach-O platforms,
124124
// only symbolic reference things in the same module.
125-
if (IGM.TargetInfo.OutputObjectFormat != llvm::Triple::MachO) {
125+
if (IGM.TargetInfo.OutputObjectFormat != llvm::Triple::MachO
126+
&& IGM.TargetInfo.OutputObjectFormat != llvm::Triple::ELF) {
126127
auto formalAccessScope = type->getFormalAccessScope(nullptr, true);
127128
if ((formalAccessScope.isPublic() || formalAccessScope.isInternal()) &&
128129
(!IGM.CurSourceFile ||

test/Reflection/typeref_lowering.swift

+4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
// REQUIRES: no_asan
22
// RUN: %empty-directory(%t)
3+
34
// RUN: %target-build-swift -Xfrontend -disable-availability-checking %S/Inputs/TypeLowering.swift -parse-as-library -emit-module -emit-library -module-name TypeLowering -o %t/%target-library-name(TypesToReflect)
5+
// RUN: %target-build-swift -Xfrontend -disable-availability-checking %S/Inputs/TypeLowering.swift %S/Inputs/main.swift -emit-module -emit-executable -module-name TypeLowering -o %t/TypesToReflect
6+
47
// RUN: %target-swift-reflection-dump -binary-filename %t/%target-library-name(TypesToReflect) -binary-filename %platform-module-dir/%target-library-name(swiftCore) -dump-type-lowering < %s | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
8+
// RUN: %target-swift-reflection-dump -binary-filename %t/TypesToReflect -binary-filename %platform-module-dir/%target-library-name(swiftCore) -dump-type-lowering < %s | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
59

610
12TypeLowering11BasicStructV
711
// CHECK-64: (struct TypeLowering.BasicStruct)

tools/swift-reflection-dump/swift-reflection-dump.cpp

+70-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/Object/ELF.h"
2626
#include "llvm/Object/ELFObjectFile.h"
2727
#include "llvm/Object/MachOUniversal.h"
28+
#include "llvm/Object/RelocationResolver.h"
2829
#include "llvm/Support/CommandLine.h"
2930
#include "llvm/Support/Error.h"
3031

@@ -96,7 +97,11 @@ class Image {
9697
const ObjectFile *O;
9798
uint64_t HeaderAddress;
9899
std::vector<Segment> Segments;
99-
llvm::DenseMap<uint64_t, StringRef> DynamicRelocations;
100+
struct DynamicRelocation {
101+
StringRef Symbol;
102+
uint64_t Offset;
103+
};
104+
llvm::DenseMap<uint64_t, DynamicRelocation> DynamicRelocations;
100105

101106
void scanMachO(const MachOObjectFile *O) {
102107
using namespace llvm::MachO;
@@ -144,7 +149,25 @@ class Image {
144149
llvm::consumeError(std::move(error));
145150
break;
146151
}
147-
DynamicRelocations.insert({bind.address(), bind.symbolName()});
152+
153+
// The offset from the symbol is stored at the target address.
154+
uint64_t Offset;
155+
auto OffsetContent = getContentsAtAddress(bind.address(),
156+
O->getBytesInAddress());
157+
if (OffsetContent.empty())
158+
continue;
159+
160+
if (O->getBytesInAddress() == 8) {
161+
memcpy(&Offset, OffsetContent.data(), sizeof(Offset));
162+
} else if (O->getBytesInAddress() == 4) {
163+
uint32_t OffsetValue;
164+
memcpy(&OffsetValue, OffsetContent.data(), sizeof(OffsetValue));
165+
Offset = OffsetValue;
166+
} else {
167+
assert(false && "unexpected word size?!");
168+
}
169+
170+
DynamicRelocations.insert({bind.address(), {bind.symbolName(), Offset}});
148171
}
149172
if (error) {
150173
llvm::consumeError(std::move(error));
@@ -160,7 +183,6 @@ class Image {
160183
auto phdrs = O->getELFFile()->program_headers();
161184
if (!phdrs) {
162185
llvm::consumeError(phdrs.takeError());
163-
return;
164186
}
165187

166188
for (auto &ph : *phdrs) {
@@ -175,6 +197,45 @@ class Image {
175197
Segments.push_back({ph.p_vaddr, contents});
176198
HeaderAddress = std::min(HeaderAddress, (uint64_t)ph.p_vaddr);
177199
}
200+
201+
// Collect the dynamic relocations.
202+
auto resolver = getRelocationResolver(*O);
203+
auto resolverSupports = resolver.first;
204+
auto resolve = resolver.second;
205+
206+
if (!resolverSupports || !resolve)
207+
return;
208+
209+
auto machine = O->getELFFile()->getHeader()->e_machine;
210+
auto relativeRelocType = getELFRelativeRelocationType(machine);
211+
212+
for (auto &S : static_cast<const ELFObjectFileBase*>(O)
213+
->dynamic_relocation_sections()) {
214+
bool isRela = O->getSection(S.getRawDataRefImpl())->sh_type
215+
== llvm::ELF::SHT_RELA;
216+
217+
for (const RelocationRef &R : S.relocations()) {
218+
// `getRelocationResolver` doesn't handle RELATIVE relocations, so we
219+
// have to do that ourselves.
220+
if (isRela && R.getType() == relativeRelocType) {
221+
auto rela = O->getRela(R.getRawDataRefImpl());
222+
DynamicRelocations.insert({R.getOffset(),
223+
{{}, HeaderAddress + rela->r_addend}});
224+
continue;
225+
}
226+
227+
if (!resolverSupports(R.getType()))
228+
continue;
229+
auto symbol = R.getSymbol();
230+
auto name = symbol->getName();
231+
if (!name) {
232+
llvm::consumeError(name.takeError());
233+
continue;
234+
}
235+
uint64_t offset = resolve(R, 0, 0);
236+
DynamicRelocations.insert({R.getOffset(), {*name, offset}});
237+
}
238+
}
178239
}
179240

180241
void scanELF(const ELFObjectFileBase *O) {
@@ -186,6 +247,8 @@ class Image {
186247
scanELFType(le64);
187248
} else if (auto be64 = dyn_cast<ELFObjectFile<ELF64BE>>(O)) {
188249
scanELFType(be64);
250+
} else {
251+
return;
189252
}
190253

191254
// FIXME: ReflectionContext tries to read bits of the ELF structure that
@@ -215,6 +278,8 @@ class Image {
215278
Segments.push_back({SectionBase, SectionContent});
216279
}
217280

281+
// FIXME: We need to map the header at least, but how much of it does
282+
// Windows typically map?
218283
Segments.push_back({HeaderAddress, O->getData()});
219284
}
220285

@@ -272,7 +337,8 @@ class Image {
272337
if (found == DynamicRelocations.end())
273338
result = RemoteAbsolutePointer("", pointerValue);
274339
else
275-
result = RemoteAbsolutePointer(found->second, pointerValue);
340+
result = RemoteAbsolutePointer(found->second.Symbol,
341+
found->second.Offset);
276342
return result;
277343
}
278344
};

0 commit comments

Comments
 (0)