forked from OSchip/llvm-project
[WebAssembly] Add support for named data sections in wasm binaries
Followup to https://reviews.llvm.org/D91769 which added support for names globals. Differential Revision: https://reviews.llvm.org/D92909
This commit is contained in:
parent
55ea639d3c
commit
9a72d3e3e4
|
@ -156,4 +156,7 @@ define void @call_ptr(i64 (i64)* %arg) {
|
|||
; CHECK-NEXT: GlobalNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: __stack_pointer
|
||||
; CHECK-NEXT: DataSegmentNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: .data
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
; MERGE-NEXT: GlobalNames:
|
||||
; MERGE-NEXT: - Index: 0
|
||||
; MERGE-NEXT: Name: __stack_pointer
|
||||
; MERGE-NOT: - Index:
|
||||
; MERGE-NEXT: DataSegmentNames:
|
||||
; MERGE-NEXT: - Index: 0
|
||||
; MERGE-NEXT: Name: .rodata
|
||||
|
||||
; RUN: wasm-ld -no-gc-sections --no-entry --no-merge-data-segments -o %t.separate.wasm %t.o
|
||||
; RUN: obj2yaml %t.separate.wasm | FileCheck %s --check-prefix=SEPARATE
|
||||
|
@ -71,7 +73,9 @@
|
|||
; SEPARATE-NEXT: GlobalNames:
|
||||
; SEPARATE-NEXT: - Index: 0
|
||||
; SEPARATE-NEXT: Name: __stack_pointer
|
||||
; SEPARATE-NOT: - Index:
|
||||
; SEPARATE-NEXT: DataSegmentNames:
|
||||
; SEPARATE-NEXT: - Index: 0
|
||||
; SEPARATE-NEXT: Name: .rodata
|
||||
|
||||
; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 -o %t.merged.passive.wasm %t.passive.o
|
||||
; RUN: obj2yaml %t.merged.passive.wasm | FileCheck %s --check-prefix=PASSIVE-MERGE
|
||||
|
|
|
@ -87,6 +87,9 @@ entry:
|
|||
; CHECK-NEXT: Name: __stack_pointer
|
||||
; CHECK-NEXT: - Index: 1
|
||||
; CHECK-NEXT: Name: used_global
|
||||
; CHECK-NEXT: DataSegmentNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: .data
|
||||
; CHECK-NEXT: ...
|
||||
|
||||
; RUN: wasm-ld -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm \
|
||||
|
@ -162,6 +165,9 @@ entry:
|
|||
; NO-GC-NEXT: Name: unused_global
|
||||
; NO-GC-NEXT: - Index: 2
|
||||
; NO-GC-NEXT: Name: used_global
|
||||
; NO-GC-NEXT: DataSegmentNames:
|
||||
; NO-GC-NEXT: - Index: 0
|
||||
; NO-GC-NEXT: Name: .data
|
||||
; NO-GC-NEXT: ...
|
||||
|
||||
; RUN: not wasm-ld --gc-sections --relocatable -o %t1.no-gc.wasm %t.o 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR
|
||||
|
|
|
@ -97,4 +97,7 @@ entry:
|
|||
; CHECK-NEXT: GlobalNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: __stack_pointer
|
||||
; CHECK-NEXT: DataSegmentNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: .data
|
||||
; CHECK-NEXT: ...
|
||||
|
|
|
@ -212,6 +212,9 @@
|
|||
; CHECK-NEXT: GlobalNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: __stack_pointer
|
||||
; CHECK-NEXT: DataSegmentNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: .data
|
||||
; CHECK-NEXT: ...
|
||||
|
||||
|
||||
|
@ -546,4 +549,11 @@
|
|||
; RELOC-NEXT: Name: get_func2B
|
||||
; RELOC-NEXT: - Index: 17
|
||||
; RELOC-NEXT: Name: get_func3B
|
||||
; RELOC-NEXT: DataSegmentNames:
|
||||
; RELOC-NEXT: - Index: 0
|
||||
; RELOC-NEXT: Name: .data.colliding_global1
|
||||
; RELOC-NEXT: - Index: 1
|
||||
; RELOC-NEXT: Name: .data.colliding_global2
|
||||
; RELOC-NEXT: - Index: 2
|
||||
; RELOC-NEXT: Name: .data.colliding_global3
|
||||
; RELOC-NEXT: ...
|
||||
|
|
|
@ -40,7 +40,7 @@ somedata:
|
|||
# CHECK-NEXT: 400 5a 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata)
|
||||
# CHECK-NEXT: 400 5a 4 somedata
|
||||
# CHECK-NEXT: - 60 12 CUSTOM(.debug_info)
|
||||
# CHECK-NEXT: - 72 2b CUSTOM(name)
|
||||
# CHECK-NEXT: - 72 35 CUSTOM(name)
|
||||
|
||||
# RUN: not wasm-ld %t1.o -o /dev/null -Map=/ 2>&1 \
|
||||
# RUN: | FileCheck -check-prefix=FAIL %s
|
||||
|
|
|
@ -55,6 +55,9 @@ declare i32 @ret32(i32, i64, i32) local_unnamed_addr
|
|||
; YAML-NEXT: GlobalNames:
|
||||
; YAML-NEXT: - Index: 0
|
||||
; YAML-NEXT: Name: __stack_pointer
|
||||
; YAML-NEXT: DataSegmentNames:
|
||||
; YAML-NEXT: - Index: 0
|
||||
; YAML-NEXT: Name: .data
|
||||
; YAML-NEXT: ...
|
||||
|
||||
; RELOC: Name: linking
|
||||
|
|
|
@ -116,4 +116,7 @@ _start:
|
|||
# CHECK-NEXT: GlobalNames:
|
||||
# CHECK-NEXT: - Index: 0
|
||||
# CHECK-NEXT: Name: __stack_pointer
|
||||
# CHECK-NEXT: DataSegmentNames:
|
||||
# CHECK-NEXT: - Index: 0
|
||||
# CHECK-NEXT: Name: .data
|
||||
# CHECK-NEXT: ...
|
||||
|
|
|
@ -562,6 +562,16 @@ unsigned NameSection::numNamedGlobals() const {
|
|||
return numNames;
|
||||
}
|
||||
|
||||
unsigned NameSection::numNamedDataSegments() const {
|
||||
unsigned numNames = 0;
|
||||
|
||||
for (const OutputSegment *s : segments)
|
||||
if (!s->name.empty())
|
||||
++numNames;
|
||||
|
||||
return numNames;
|
||||
}
|
||||
|
||||
// Create the custom "name" section containing debug symbol names.
|
||||
void NameSection::writeBody() {
|
||||
unsigned count = numNamedFunctions();
|
||||
|
@ -619,6 +629,19 @@ void NameSection::writeBody() {
|
|||
|
||||
sub.writeTo(bodyOutputStream);
|
||||
}
|
||||
|
||||
count = numNamedDataSegments();
|
||||
if (count) {
|
||||
SubSection sub(WASM_NAMES_DATA_SEGMENT);
|
||||
writeUleb128(sub.os, count, "name count");
|
||||
|
||||
for (OutputSegment *s : segments) {
|
||||
writeUleb128(sub.os, s->index, "global index");
|
||||
writeStr(sub.os, s->name, "segment name");
|
||||
}
|
||||
|
||||
sub.writeTo(bodyOutputStream);
|
||||
}
|
||||
}
|
||||
|
||||
void ProducersSection::addInfo(const WasmProducerInfo &info) {
|
||||
|
|
|
@ -296,7 +296,9 @@ protected:
|
|||
// Create the custom "name" section containing debug symbol names.
|
||||
class NameSection : public SyntheticSection {
|
||||
public:
|
||||
NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {}
|
||||
NameSection(ArrayRef<OutputSegment *> segments)
|
||||
: SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name"),
|
||||
segments(segments) {}
|
||||
bool isNeeded() const override {
|
||||
return !config->stripDebug && !config->stripAll && numNames() > 0;
|
||||
}
|
||||
|
@ -304,6 +306,10 @@ public:
|
|||
unsigned numNames() const { return numNamedGlobals() + numNamedFunctions(); }
|
||||
unsigned numNamedGlobals() const;
|
||||
unsigned numNamedFunctions() const;
|
||||
unsigned numNamedDataSegments() const;
|
||||
|
||||
protected:
|
||||
ArrayRef<OutputSegment *> segments;
|
||||
};
|
||||
|
||||
class ProducersSection : public SyntheticSection {
|
||||
|
|
|
@ -1210,7 +1210,7 @@ void Writer::createSyntheticSections() {
|
|||
out.elemSec = make<ElemSection>();
|
||||
out.dataCountSec = make<DataCountSection>(segments);
|
||||
out.linkingSec = make<LinkingSection>(initFunctions, segments);
|
||||
out.nameSec = make<NameSection>();
|
||||
out.nameSec = make<NameSection>(segments);
|
||||
out.producersSec = make<ProducersSection>();
|
||||
out.targetFeaturesSec = make<TargetFeaturesSection>();
|
||||
}
|
||||
|
|
|
@ -202,7 +202,8 @@ struct WasmSymbolInfo {
|
|||
|
||||
enum class NameType {
|
||||
FUNCTION,
|
||||
GLOBAL
|
||||
GLOBAL,
|
||||
DATA_SEGMENT,
|
||||
};
|
||||
|
||||
struct WasmDebugName {
|
||||
|
@ -313,9 +314,10 @@ enum : uint8_t {
|
|||
|
||||
// Kind codes used in the custom "name" section
|
||||
enum : unsigned {
|
||||
WASM_NAMES_FUNCTION = 0x1,
|
||||
WASM_NAMES_LOCAL = 0x2,
|
||||
WASM_NAMES_GLOBAL = 0x7,
|
||||
WASM_NAMES_FUNCTION = 1,
|
||||
WASM_NAMES_LOCAL = 2,
|
||||
WASM_NAMES_GLOBAL = 7,
|
||||
WASM_NAMES_DATA_SEGMENT = 9,
|
||||
};
|
||||
|
||||
// Kind codes used in the custom "linking" section
|
||||
|
|
|
@ -222,6 +222,7 @@ struct NameSection : CustomSection {
|
|||
|
||||
std::vector<NameEntry> FunctionNames;
|
||||
std::vector<NameEntry> GlobalNames;
|
||||
std::vector<NameEntry> DataSegmentNames;
|
||||
};
|
||||
|
||||
struct LinkingSection : CustomSection {
|
||||
|
|
|
@ -357,6 +357,7 @@ Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
|
|||
Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
|
||||
llvm::DenseSet<uint64_t> SeenFunctions;
|
||||
llvm::DenseSet<uint64_t> SeenGlobals;
|
||||
llvm::DenseSet<uint64_t> SeenSegments;
|
||||
if (FunctionTypes.size() && !SeenCodeSection) {
|
||||
return make_error<GenericBinaryError>("Names must come after code section",
|
||||
object_error::parse_failed);
|
||||
|
@ -368,11 +369,13 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
|
|||
const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
|
||||
switch (Type) {
|
||||
case wasm::WASM_NAMES_FUNCTION:
|
||||
case wasm::WASM_NAMES_GLOBAL: {
|
||||
case wasm::WASM_NAMES_GLOBAL:
|
||||
case wasm::WASM_NAMES_DATA_SEGMENT: {
|
||||
uint32_t Count = readVaruint32(Ctx);
|
||||
while (Count--) {
|
||||
uint32_t Index = readVaruint32(Ctx);
|
||||
StringRef Name = readString(Ctx);
|
||||
wasm::NameType nameType = wasm::NameType::FUNCTION;
|
||||
if (Type == wasm::WASM_NAMES_FUNCTION) {
|
||||
if (!SeenFunctions.insert(Index).second)
|
||||
return make_error<GenericBinaryError>(
|
||||
|
@ -383,18 +386,24 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
|
|||
|
||||
if (isDefinedFunctionIndex(Index))
|
||||
getDefinedFunction(Index).DebugName = Name;
|
||||
} else {
|
||||
} else if (Type == wasm::WASM_NAMES_GLOBAL) {
|
||||
nameType = wasm::NameType::GLOBAL;
|
||||
if (!SeenGlobals.insert(Index).second)
|
||||
return make_error<GenericBinaryError>("Global named more than once",
|
||||
object_error::parse_failed);
|
||||
if (!isValidGlobalIndex(Index) || Name.empty())
|
||||
return make_error<GenericBinaryError>("Invalid name entry",
|
||||
object_error::parse_failed);
|
||||
} else {
|
||||
nameType = wasm::NameType::DATA_SEGMENT;
|
||||
if (!SeenSegments.insert(Index).second)
|
||||
return make_error<GenericBinaryError>(
|
||||
"Segment named more than once", object_error::parse_failed);
|
||||
if (Index > DataSegments.size())
|
||||
return make_error<GenericBinaryError>("Invalid named data segment",
|
||||
object_error::parse_failed);
|
||||
}
|
||||
wasm::NameType T = Type == wasm::WASM_NAMES_FUNCTION
|
||||
? wasm::NameType::FUNCTION
|
||||
: wasm::NameType::GLOBAL;
|
||||
DebugNames.push_back(wasm::WasmDebugName{T, Index, Name});
|
||||
DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -281,6 +281,19 @@ void WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||
writeStringRef(NameEntry.Name, SubSection.getStream());
|
||||
}
|
||||
|
||||
SubSection.done();
|
||||
}
|
||||
if (Section.DataSegmentNames.size()) {
|
||||
writeUint8(OS, wasm::WASM_NAMES_DATA_SEGMENT);
|
||||
|
||||
SubSectionWriter SubSection(OS);
|
||||
|
||||
encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());
|
||||
for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
|
||||
encodeULEB128(NameEntry.Index, SubSection.getStream());
|
||||
writeStringRef(NameEntry.Name, SubSection.getStream());
|
||||
}
|
||||
|
||||
SubSection.done();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
|
|||
IO.mapRequired("Name", Section.Name);
|
||||
IO.mapOptional("FunctionNames", Section.FunctionNames);
|
||||
IO.mapOptional("GlobalNames", Section.GlobalNames);
|
||||
IO.mapOptional("DataSegmentNames", Section.DataSegmentNames);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
|
||||
|
|
|
@ -70,9 +70,11 @@ WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
|
|||
NameEntry.Index = Name.Index;
|
||||
if (Name.Type == llvm::wasm::NameType::FUNCTION) {
|
||||
NameSec->FunctionNames.push_back(NameEntry);
|
||||
} else {
|
||||
assert(Name.Type == llvm::wasm::NameType::GLOBAL);
|
||||
} else if (Name.Type == llvm::wasm::NameType::GLOBAL) {
|
||||
NameSec->GlobalNames.push_back(NameEntry);
|
||||
} else {
|
||||
assert(Name.Type == llvm::wasm::NameType::DATA_SEGMENT);
|
||||
NameSec->DataSegmentNames.push_back(NameEntry);
|
||||
}
|
||||
}
|
||||
CustomSec = std::move(NameSec);
|
||||
|
|
Loading…
Reference in New Issue