Skip to content

Commit

Permalink
Support new dylink.0 custom section format (#4141)
Browse files Browse the repository at this point in the history
  • Loading branch information
sbc100 authored Sep 11, 2021
1 parent fc310a6 commit 5b90e03
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 11 deletions.
8 changes: 7 additions & 1 deletion src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ namespace UserSections {
extern const char* Name;
extern const char* SourceMapUrl;
extern const char* Dylink;
extern const char* Dylink0;
extern const char* Linking;
extern const char* Producers;
extern const char* TargetFeatures;
Expand Down Expand Up @@ -435,7 +436,10 @@ enum Subsection {
NameElem = 8,
NameData = 9,
// see: https://github.com/WebAssembly/gc/issues/193
NameField = 10
NameField = 10,

DylinkMemInfo = 1,
DylinkNeeded = 2,
};

} // namespace UserSections
Expand Down Expand Up @@ -1230,6 +1234,7 @@ class WasmBinaryWriter {
void writeUserSection(const UserSection& section);
void writeFeaturesSection();
void writeDylinkSection();
void writeLegacyDylinkSection();

void initializeDebugInfo();
void writeSourceMapProlog();
Expand Down Expand Up @@ -1557,6 +1562,7 @@ class WasmBinaryBuilder {
void readNames(size_t);
void readFeatures(size_t);
void readDylink(size_t);
void readDylink0(size_t);

// Debug information reading helpers
void setDebugLocations(std::istream* sourceMap_) { sourceMap = sourceMap_; }
Expand Down
1 change: 1 addition & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,7 @@ class UserSection {
// The optional "dylink" section is used in dynamic linking.
class DylinkSection {
public:
bool isLegacy = false;
Index memorySize, memoryAlignment, tableSize, tableAlignment;
std::vector<Name> neededDynlibs;
std::vector<char> tail;
Expand Down
88 changes: 81 additions & 7 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,7 @@ void WasmBinaryWriter::writeFeaturesSection() {
finishSection(start);
}

void WasmBinaryWriter::writeDylinkSection() {
void WasmBinaryWriter::writeLegacyDylinkSection() {
if (!wasm->dylinkSection) {
return;
}
Expand All @@ -1082,9 +1082,41 @@ void WasmBinaryWriter::writeDylinkSection() {
for (auto& neededDynlib : wasm->dylinkSection->neededDynlibs) {
writeInlineString(neededDynlib.c_str());
}
finishSection(start);
}

writeData(wasm->dylinkSection->tail.data(), wasm->dylinkSection->tail.size());
void WasmBinaryWriter::writeDylinkSection() {
if (!wasm->dylinkSection) {
return;
}

if (wasm->dylinkSection->isLegacy) {
writeLegacyDylinkSection();
return;
}

auto start = startSection(BinaryConsts::User);
writeInlineString(BinaryConsts::UserSections::Dylink0);

auto substart =
startSubsection(BinaryConsts::UserSections::Subsection::DylinkMemInfo);
o << U32LEB(wasm->dylinkSection->memorySize);
o << U32LEB(wasm->dylinkSection->memoryAlignment);
o << U32LEB(wasm->dylinkSection->tableSize);
o << U32LEB(wasm->dylinkSection->tableAlignment);
finishSubsection(substart);

if (wasm->dylinkSection->neededDynlibs.size()) {
substart =
startSubsection(BinaryConsts::UserSections::Subsection::DylinkNeeded);
o << U32LEB(wasm->dylinkSection->neededDynlibs.size());
for (auto& neededDynlib : wasm->dylinkSection->neededDynlibs) {
writeInlineString(neededDynlib.c_str());
}
finishSubsection(substart);
}

writeData(wasm->dylinkSection->tail.data(), wasm->dylinkSection->tail.size());
finishSection(start);
}

Expand Down Expand Up @@ -1435,6 +1467,7 @@ void WasmBinaryBuilder::read() {
}

void WasmBinaryBuilder::readUserSection(size_t payloadLen) {
BYN_TRACE("== readUserSection\n");
auto oldPos = pos;
Name sectionName = getInlineString();
size_t read = pos - oldPos;
Expand All @@ -1452,6 +1485,8 @@ void WasmBinaryBuilder::readUserSection(size_t payloadLen) {
readFeatures(payloadLen);
} else if (sectionName.equals(BinaryConsts::UserSections::Dylink)) {
readDylink(payloadLen);
} else if (sectionName.equals(BinaryConsts::UserSections::Dylink0)) {
readDylink0(payloadLen);
} else {
// an unfamiliar custom section
if (sectionName.equals(BinaryConsts::UserSections::Linking)) {
Expand Down Expand Up @@ -3252,6 +3287,7 @@ void WasmBinaryBuilder::readDylink(size_t payloadLen) {

auto sectionPos = pos;

wasm.dylinkSection->isLegacy = true;
wasm.dylinkSection->memorySize = getU32LEB();
wasm.dylinkSection->memoryAlignment = getU32LEB();
wasm.dylinkSection->tableSize = getU32LEB();
Expand All @@ -3262,12 +3298,50 @@ void WasmBinaryBuilder::readDylink(size_t payloadLen) {
wasm.dylinkSection->neededDynlibs.push_back(getInlineString());
}

size_t remaining = (sectionPos + payloadLen) - pos;
auto tail = getByteView(remaining);
wasm.dylinkSection->tail = {tail.first, tail.second};

if (pos != sectionPos + payloadLen) {
throwError("bad features section size");
throwError("bad dylink section size");
}
}

void WasmBinaryBuilder::readDylink0(size_t payloadLen) {
BYN_TRACE("== readDylink0\n");
auto sectionPos = pos;
uint32_t lastType = 0;

wasm.dylinkSection = make_unique<DylinkSection>();
while (pos < sectionPos + payloadLen) {
auto oldPos = pos;
auto dylinkType = getU32LEB();
if (lastType && dylinkType <= lastType) {
std::cerr << "warning: out-of-order dylink.0 subsection: " << dylinkType
<< std::endl;
}
lastType = dylinkType;
auto subsectionSize = getU32LEB();
auto subsectionPos = pos;
if (dylinkType == BinaryConsts::UserSections::Subsection::DylinkMemInfo) {
wasm.dylinkSection->memorySize = getU32LEB();
wasm.dylinkSection->memoryAlignment = getU32LEB();
wasm.dylinkSection->tableSize = getU32LEB();
wasm.dylinkSection->tableAlignment = getU32LEB();
} else if (dylinkType ==
BinaryConsts::UserSections::Subsection::DylinkNeeded) {
size_t numNeededDynlibs = getU32LEB();
for (size_t i = 0; i < numNeededDynlibs; ++i) {
wasm.dylinkSection->neededDynlibs.push_back(getInlineString());
}
} else {
// Unknown subsection. Stop parsing now and store the rest of
// the section verbatim.
pos = oldPos;
size_t remaining = (sectionPos + payloadLen) - pos;
auto tail = getByteView(remaining);
wasm.dylinkSection->tail = {tail.first, tail.second};
break;
}
if (pos != subsectionPos + subsectionSize) {
throwError("bad dylink.0 subsection position change");
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/wasm/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace UserSections {
const char* Name = "name";
const char* SourceMapUrl = "sourceMappingURL";
const char* Dylink = "dylink";
const char* Dylink0 = "dylink.0";
const char* Linking = "linking";
const char* Producers = "producers";
const char* TargetFeatures = "target_features";
Expand Down
6 changes: 3 additions & 3 deletions test/lit/binary/dylink.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
# `dylink.test.wasm` was generated using emscripten to build a side
# module with two TLS exports (which adds extra information to the
# dylink section) using:
# `emcc -s SIDE_MODULE side.c`
# `emcc -s USE_PTHREAD -s SIDE_MODULE side.c`
#
# side.c:
# _Thread_local int foo = 10;
# _Thread_local int bar = 11;
#
# and then removing all sections except the dylink section using:
# `llvm-objcopy --only-section=dylink`
# and then removing all sections except the dylink.0 section using:
# `llvm-objcopy --only-section=dylink.0`
RUN: wasm-opt -O1 %s.wasm -o %t.o
RUN: cmp %s.wasm %t.o
Binary file modified test/lit/binary/dylink.test.wasm
Binary file not shown.

0 comments on commit 5b90e03

Please sign in to comment.