mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 06:10:12 +00:00
[lld][WebAssembly] Delay the merging of data section when dynamic linking
With dynamic linking we have the current limitation that there can be only a single active data segment (since we use __memory_base as the load address and we can't do arithmetic in constant expresions). This change delays the merging of active segments until a little later in the linking process which means that the grouping of data by section, and the magic __start/__end symbols work as expected under dynamic linking. Differential Revision: https://reviews.llvm.org/D96453
This commit is contained in:
parent
a680bc3a31
commit
70f3c6e9e6
@ -121,8 +121,8 @@
|
||||
; PASSIVE32-PIC-NEXT: - Type: I32
|
||||
; PASSIVE64-PIC-NEXT: - Type: I64
|
||||
; PASSIVE-PIC-NEXT: Count: 1
|
||||
; PASSIVE32-PIC-NEXT: Body: 230141B4CE006A2100200041004101FE480200044020004101427FFE0102001A05410023016A410041B1CE00FC08000020004102FE1702002000417FFE0002001A0BFC09000B
|
||||
; PASSIVE64-PIC-NEXT: Body: 230142B4CE006A2100200041004101FE480200044020004101427FFE0102001A05420023016A410041B1CE00FC08000020004102FE1702002000417FFE0002001A0BFC09000B
|
||||
; PASSIVE32-PIC-NEXT: Body: 230141B4CE006A2100200041004101FE480200044020004101427FFE0102001A05410023016A410041B4CE00FC08000020004102FE1702002000417FFE0002001A0BFC09000B
|
||||
; PASSIVE64-PIC-NEXT: Body: 230142B4CE006A2100200041004101FE480200044020004101427FFE0102001A05420023016A410041B4CE00FC08000020004102FE1702002000417FFE0002001A0BFC09000B
|
||||
; PASSIVE-PIC-NEXT: - Index: 3
|
||||
; PASSIVE-PIC-NEXT: Locals: []
|
||||
; PASSIVE-PIC-NEXT: Body: 0B
|
||||
|
@ -54,7 +54,7 @@ tls1:
|
||||
# CHECK-NEXT: Mutable: false
|
||||
# CHECK-NEXT: InitExpr:
|
||||
# CHECK-NEXT: Opcode: I32_CONST
|
||||
# CHECK-NEXT: Value: 1028
|
||||
# CHECK-NEXT: Value: 1024
|
||||
# CHECK-NEXT: - Type: EXPORT
|
||||
|
||||
# CHECK: - Type: DATA
|
||||
@ -65,11 +65,11 @@ tls1:
|
||||
# CHECK-NEXT: Offset:
|
||||
# CHECK-NEXT: Opcode: I32_CONST
|
||||
# CHECK-NEXT: Value: 1024
|
||||
# CHECK-NEXT: Content: 2A000000
|
||||
# CHECK-NEXT: Content: 2B000000
|
||||
# .tdata
|
||||
# CHECK-NEXT: - SectionOffset: 17
|
||||
# CHECK-NEXT: InitFlags: 0
|
||||
# CHECK-NEXT: Offset:
|
||||
# CHECK-NEXT: Opcode: I32_CONST
|
||||
# CHECK-NEXT: Value: 1028
|
||||
# CHECK-NEXT: Content: 2B000000
|
||||
# CHECK-NEXT: Content: 2A000000
|
||||
|
@ -353,6 +353,10 @@ void InputFunction::writeTo(uint8_t *buf) const {
|
||||
LLVM_DEBUG(dbgs() << " total: " << (buf + chunkSize - orig) << "\n");
|
||||
}
|
||||
|
||||
uint64_t InputSegment::getVA() const {
|
||||
return outputSeg->startVA + outputSegmentOffset;
|
||||
}
|
||||
|
||||
// Generate code to apply relocations to the data section at runtime.
|
||||
// This is only called when generating shared libaries (PIC) where address are
|
||||
// not known at static link time.
|
||||
@ -370,10 +374,9 @@ void InputSegment::generateRelocationCode(raw_ostream &os) const {
|
||||
auto tombstone = getTombstone();
|
||||
// TODO(sbc): Encode the relocations in the data section and write a loop
|
||||
// here to apply them.
|
||||
uint64_t segmentVA = outputSeg->startVA + outputSegmentOffset;
|
||||
for (const WasmRelocation &rel : relocations) {
|
||||
uint64_t offset = rel.Offset - getInputSectionOffset();
|
||||
uint64_t outputOffset = segmentVA + offset;
|
||||
uint64_t outputOffset = getVA() + offset;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type)
|
||||
<< " addend=" << rel.Addend << " index=" << rel.Index
|
||||
|
@ -108,6 +108,7 @@ public:
|
||||
uint32_t getInputSectionOffset() const override {
|
||||
return segment.SectionOffset;
|
||||
}
|
||||
uint64_t getVA() const;
|
||||
|
||||
const OutputSegment *outputSeg = nullptr;
|
||||
int32_t outputSegmentOffset = 0;
|
||||
|
@ -138,7 +138,7 @@ void lld::wasm::writeMapFile(ArrayRef<OutputSection *> outputSections) {
|
||||
oseg->size);
|
||||
os << oseg->name << '\n';
|
||||
for (auto *chunk : oseg->inputSegments) {
|
||||
writeHeader(os, oseg->startVA + chunk->outputSegmentOffset,
|
||||
writeHeader(os, chunk->getVA(),
|
||||
chunk->outputSec->getOffset() + chunk->outputOffset,
|
||||
chunk->getSize());
|
||||
os.indent(8) << toString(chunk) << '\n';
|
||||
|
@ -22,10 +22,11 @@ class OutputSegment {
|
||||
public:
|
||||
OutputSegment(StringRef n) : name(n) {}
|
||||
|
||||
void addInputSegment(InputSegment *inSeg) {
|
||||
alignment = std::max(alignment, inSeg->getAlignment());
|
||||
void addInputSegment(InputSegment *inSeg, uint32_t forceAlignment = 0) {
|
||||
uint32_t segAlign = std::max(forceAlignment, inSeg->getAlignment());
|
||||
alignment = std::max(alignment, segAlign);
|
||||
inputSegments.push_back(inSeg);
|
||||
size = llvm::alignTo(size, 1ULL << inSeg->getAlignment());
|
||||
size = llvm::alignTo(size, 1ULL << segAlign);
|
||||
inSeg->outputSeg = this;
|
||||
inSeg->outputSegmentOffset = size;
|
||||
size += inSeg->getSize();
|
||||
|
@ -279,7 +279,7 @@ DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
|
||||
uint64_t DefinedData::getVirtualAddress() const {
|
||||
LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
|
||||
if (segment)
|
||||
return segment->outputSeg->startVA + segment->outputSegmentOffset + offset;
|
||||
return segment->getVA() + offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ private:
|
||||
void calculateCustomSections();
|
||||
void calculateTypes();
|
||||
void createOutputSegments();
|
||||
void combineOutputSegments();
|
||||
void layoutMemory();
|
||||
void createHeader();
|
||||
|
||||
@ -86,6 +87,7 @@ private:
|
||||
|
||||
void createCustomSections();
|
||||
void createSyntheticSections();
|
||||
void createSyntheticSectionsPostLayout();
|
||||
void finalizeSections();
|
||||
|
||||
// Custom sections
|
||||
@ -795,10 +797,6 @@ static StringRef getOutputDataSegmentName(StringRef name) {
|
||||
// We also need to merge .tbss into .tdata so they share the same offsets.
|
||||
if (name.startswith(".tdata") || name.startswith(".tbss"))
|
||||
return ".tdata";
|
||||
// With PIC code we currently only support a single data segment since
|
||||
// we only have a single __memory_base to use as our base address.
|
||||
if (config->isPic)
|
||||
return ".data";
|
||||
if (!config->mergeDataSegments)
|
||||
return name;
|
||||
if (name.startswith(".text."))
|
||||
@ -843,9 +841,9 @@ void Writer::createOutputSegments() {
|
||||
[](const OutputSegment *a, const OutputSegment *b) {
|
||||
auto order = [](StringRef name) {
|
||||
return StringSwitch<int>(name)
|
||||
.StartsWith(".rodata", 0)
|
||||
.StartsWith(".data", 1)
|
||||
.StartsWith(".tdata", 2)
|
||||
.StartsWith(".tdata", 0)
|
||||
.StartsWith(".rodata", 1)
|
||||
.StartsWith(".data", 2)
|
||||
.StartsWith(".bss", 4)
|
||||
.Default(3);
|
||||
};
|
||||
@ -856,6 +854,52 @@ void Writer::createOutputSegments() {
|
||||
segments[i]->index = i;
|
||||
}
|
||||
|
||||
void Writer::combineOutputSegments() {
|
||||
// With PIC code we currently only support a single data segment since
|
||||
// we only have a single __memory_base to use as our base address.
|
||||
// This pass combines all non-TLS data segments into a single .data
|
||||
// segment.
|
||||
// This restructions can be relaxed once we have extended constant
|
||||
// expressions available:
|
||||
// https://github.com/WebAssembly/extended-const
|
||||
assert(config->isPic);
|
||||
if (segments.size() <= 1)
|
||||
return;
|
||||
OutputSegment *combined = nullptr;
|
||||
std::vector<OutputSegment *> new_segments;
|
||||
for (OutputSegment *s : segments) {
|
||||
if (s->name == ".tdata") {
|
||||
new_segments.push_back(s);
|
||||
} else {
|
||||
if (!combined) {
|
||||
combined = make<OutputSegment>(".data");
|
||||
combined->startVA = s->startVA;
|
||||
if (config->sharedMemory)
|
||||
combined->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
|
||||
}
|
||||
bool first = true;
|
||||
for (InputSegment *inSeg : s->inputSegments) {
|
||||
uint32_t alignment = first ? s->alignment : 0;
|
||||
first = false;
|
||||
#ifndef NDEBUG
|
||||
uint64_t oldVA = inSeg->getVA();
|
||||
#endif
|
||||
combined->addInputSegment(inSeg, alignment);
|
||||
#ifndef NDEBUG
|
||||
uint64_t newVA = inSeg->getVA();
|
||||
assert(oldVA == newVA);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if (combined) {
|
||||
new_segments.push_back(combined);
|
||||
segments = new_segments;
|
||||
for (size_t i = 0; i < segments.size(); ++i)
|
||||
segments[i]->index = i;
|
||||
}
|
||||
}
|
||||
|
||||
static void createFunction(DefinedFunction *func, StringRef bodyContent) {
|
||||
std::string functionBody;
|
||||
{
|
||||
@ -1295,11 +1339,14 @@ void Writer::createSyntheticSections() {
|
||||
out.exportSec = make<ExportSection>();
|
||||
out.startSec = make<StartSection>();
|
||||
out.elemSec = make<ElemSection>();
|
||||
out.producersSec = make<ProducersSection>();
|
||||
out.targetFeaturesSec = make<TargetFeaturesSection>();
|
||||
}
|
||||
|
||||
void Writer::createSyntheticSectionsPostLayout() {
|
||||
out.dataCountSec = make<DataCountSection>(segments);
|
||||
out.linkingSec = make<LinkingSection>(initFunctions, segments);
|
||||
out.nameSec = make<NameSection>(segments);
|
||||
out.producersSec = make<ProducersSection>();
|
||||
out.targetFeaturesSec = make<TargetFeaturesSection>();
|
||||
}
|
||||
|
||||
void Writer::run() {
|
||||
@ -1318,18 +1365,15 @@ void Writer::run() {
|
||||
createOutputSegments();
|
||||
log("-- createSyntheticSections");
|
||||
createSyntheticSections();
|
||||
log("-- populateProducers");
|
||||
populateProducers();
|
||||
log("-- calculateImports");
|
||||
calculateImports();
|
||||
log("-- layoutMemory");
|
||||
layoutMemory();
|
||||
|
||||
if (!config->relocatable) {
|
||||
// Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
|
||||
// This has to be done after memory layout is performed.
|
||||
for (const OutputSegment *seg : segments)
|
||||
for (const OutputSegment *seg : segments) {
|
||||
addStartStopSymbols(seg);
|
||||
}
|
||||
}
|
||||
|
||||
// Delay reporting error about explict exports until after addStartStopSymbols
|
||||
@ -1345,6 +1389,17 @@ void Writer::run() {
|
||||
warn(Twine("symbol exported via --export not found: ") + name);
|
||||
}
|
||||
|
||||
if (config->isPic) {
|
||||
log("-- combineOutputSegments");
|
||||
combineOutputSegments();
|
||||
}
|
||||
|
||||
log("-- createSyntheticSectionsPostLayout");
|
||||
createSyntheticSectionsPostLayout();
|
||||
log("-- populateProducers");
|
||||
populateProducers();
|
||||
log("-- calculateImports");
|
||||
calculateImports();
|
||||
log("-- scanRelocations");
|
||||
scanRelocations();
|
||||
log("-- finalizeIndirectFunctionTable");
|
||||
|
Loading…
Reference in New Issue
Block a user