[WebAssembly] Add data size and alignement to linking section

The overal size of the data section (including BSS)
is otherwise not included in the wasm binary.

Differential Revision: https://reviews.llvm.org/D34657

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306459 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sam Clegg 2017-06-27 20:27:59 +00:00
parent f4a2d1d749
commit 49ab5d5992
13 changed files with 166 additions and 75 deletions

View File

@ -112,6 +112,11 @@ struct WasmRelocation {
int64_t Addend; // A value to add to the symbol.
};
struct WasmLinkingData {
uint32_t DataSize;
uint32_t DataAlignment;
};
enum : unsigned {
WASM_SEC_CUSTOM = 0, // Custom / User-defined section
WASM_SEC_TYPE = 1, // Function signature declarations
@ -175,8 +180,10 @@ enum class ValType {
// Linking metadata kinds.
enum : unsigned {
WASM_STACK_POINTER = 0x1,
WASM_SYMBOL_INFO = 0x2,
WASM_STACK_POINTER = 0x1,
WASM_SYMBOL_INFO = 0x2,
WASM_DATA_SIZE = 0x3,
WASM_DATA_ALIGNMENT = 0x4,
};
enum : unsigned {

View File

@ -100,6 +100,7 @@ public:
const std::vector<wasm::WasmLimits>& memories() const { return Memories; }
const std::vector<wasm::WasmGlobal>& globals() const { return Globals; }
const std::vector<wasm::WasmExport>& exports() const { return Exports; }
const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
uint32_t getNumberOfSymbols() const {
return Symbols.size();
@ -214,6 +215,7 @@ private:
std::vector<WasmSymbol> Symbols;
ArrayRef<uint8_t> CodeSection;
uint32_t StartFunction = -1;
wasm::WasmLinkingData LinkingData;
StringMap<uint32_t> SymbolMap;
};

View File

@ -154,6 +154,8 @@ struct LinkingSection : CustomSection {
}
std::vector<SymbolInfo> SymbolInfos;
uint32_t DataSize;
uint32_t DataAlignment;
};
struct TypeSection : Section {

View File

@ -265,7 +265,8 @@ private:
uint32_t NumFuncImports);
void writeCodeRelocSection();
void writeDataRelocSection(uint64_t DataSectionHeaderSize);
void writeLinkingMetaDataSection(ArrayRef<StringRef> WeakSymbols,
void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment,
ArrayRef<StringRef> WeakSymbols,
bool HasStackPointer,
uint32_t StackPointerGlobal);
@ -877,11 +878,8 @@ void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
}
void WasmObjectWriter::writeLinkingMetaDataSection(
ArrayRef<StringRef> WeakSymbols, bool HasStackPointer,
uint32_t StackPointerGlobal) {
if (!HasStackPointer && WeakSymbols.empty())
return;
uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
bool HasStackPointer, uint32_t StackPointerGlobal) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
SectionBookkeeping SubSection;
@ -902,6 +900,16 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
endSection(SubSection);
}
if (DataSize > 0) {
startSection(SubSection, wasm::WASM_DATA_SIZE);
encodeULEB128(DataSize, getStream());
endSection(SubSection);
startSection(SubSection, wasm::WASM_DATA_ALIGNMENT);
encodeULEB128(DataAlignment, getStream());
endSection(SubSection);
}
endSection(Section);
}
@ -923,6 +931,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
unsigned NumFuncImports = 0;
unsigned NumGlobalImports = 0;
SmallVector<char, 0> DataBytes;
uint32_t DataAlignment = 1;
uint32_t StackPointerGlobal = 0;
bool HasStackPointer = false;
@ -1157,6 +1166,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
report_fatal_error("data sections must contain at most one variable");
DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
DataSection.setSectionOffset(DataBytes.size());
@ -1272,7 +1282,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeNameSection(Functions, Imports, NumFuncImports);
writeCodeRelocSection();
writeDataRelocSection(DataSectionHeaderSize);
writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal);
writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal);
// TODO: Translate the .comment section to the output.
// TODO: Translate debug sections to the output.

View File

@ -193,6 +193,9 @@ static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
: ObjectFile(Binary::ID_Wasm, Buffer) {
LinkingData.DataAlignment = 0;
LinkingData.DataSize = 0;
ErrorAsOutParameter ErrAsOutParam(&Err);
Header.Magic = getData().substr(0, 4);
if (Header.Magic != StringRef("\0asm", 4)) {
@ -305,7 +308,7 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
auto iter = SymbolMap.find(Symbol);
if (iter == SymbolMap.end()) {
return make_error<GenericBinaryError>(
"Invalid symbol name in linking section",
"Invalid symbol name in linking section: " + Symbol,
object_error::parse_failed);
}
uint32_t SymIndex = iter->second;
@ -318,6 +321,12 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
}
break;
}
case wasm::WASM_DATA_SIZE:
LinkingData.DataSize = readVaruint32(Ptr);
break;
case wasm::WASM_DATA_ALIGNMENT:
LinkingData.DataAlignment = readVaruint32(Ptr);
break;
case wasm::WASM_STACK_POINTER:
default:
Ptr += Size;

View File

@ -56,6 +56,8 @@ static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
commonSectionMapping(IO, Section);
IO.mapRequired("Name", Section.Name);
IO.mapRequired("DataSize", Section.DataSize);
IO.mapRequired("DataAlignment", Section.DataAlignment);
IO.mapRequired("SymbolInfo", Section.SymbolInfos);
}

View File

@ -7,47 +7,53 @@
@b = global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), align 8
; CHECK: - Type: GLOBAL
; CHECK: Globals:
; CHECK: - Type: I32
; CHECK: Mutable: false
; CHECK: InitExpr:
; CHECK: Opcode: I32_CONST
; CHECK: Value: 0
; CHECK: - Type: I32
; CHECK: Mutable: false
; CHECK: InitExpr:
; CHECK: Opcode: I32_CONST
; CHECK: Value: 6
; CHECK: - Type: I32
; CHECK: Mutable: false
; CHECK: InitExpr:
; CHECK: Opcode: I32_CONST
; CHECK: Value: 16
; CHECK: - Type: I32
; CHECK: Mutable: false
; CHECK: InitExpr:
; CHECK: Opcode: I32_CONST
; CHECK: Value: 24
; CHECK: - Type: EXPORT
; CHECK: Exports:
; CHECK: - Name: a
; CHECK: Kind: GLOBAL
; CHECK: Index: 2
; CHECK: - Name: b
; CHECK: Kind: GLOBAL
; CHECK: Index: 3
; CHECK: - Type: DATA
; CHECK: Relocations:
; CHECK: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
; CHECK: Index: 0
; CHECK: Offset: 0x00000016
; CHECK: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
; CHECK: Index: 1
; CHECK: Offset: 0x0000001E
; CHECK: Segments:
; CHECK: - Index: 0
; CHECK: Offset:
; CHECK: Opcode: I32_CONST
; CHECK: Value: 0
; CHECK: Content: 68656C6C6F00776F726C640000000000000000000000000006000000
; CHECK: - Type: GLOBAL
; CHECK-NEXT: Globals:
; CHECK-NEXT: - Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 0
; CHECK-NEXT: - Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 6
; CHECK-NEXT: - Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 16
; CHECK-NEXT: - Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 24
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: a
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: b
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Relocations:
; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
; CHECK-NEXT: Index: 0
; CHECK-NEXT: Offset: 0x00000016
; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
; CHECK-NEXT: Index: 1
; CHECK-NEXT: Offset: 0x0000001E
; CHECK-NEXT: Segments:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 0
; CHECK-NEXT: Content: 68656C6C6F00776F726C640000000000000000000000000006000000
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 28
; CHECK-NEXT: DataAlignment: 8
; CHECK-NEXT: SymbolInfo:
; CHECK-NEXT: ...

View File

@ -27,6 +27,8 @@ entry:
; CHECK-NEXT: Name: foo
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 0
; CHECK-NEXT: DataAlignment: 0
; CHECK-NEXT: SymbolInfo:
; CHECK-NEXT: - Name: foo_alias
; CHECK-NEXT: Flags: 1

View File

@ -26,6 +26,8 @@ entry:
; CHECK-NEXT: Name: weak_function
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 0
; CHECK-NEXT: DataAlignment: 0
; CHECK-NEXT: SymbolInfo:
; CHECK-NEXT: - Name: weak_external_data
; CHECK-NEXT: Flags: 1

View File

@ -3,6 +3,19 @@
FileHeader:
Version: 0x00000001
Sections:
- Type: TYPE
Signatures:
- ReturnType: I32
ParamTypes:
- Type: FUNCTION
FunctionTypes: [ 0, 0 ]
- Type: GLOBAL
Globals:
- Type: I32
Mutable: false
InitExpr:
Opcode: I32_CONST
Value: 1
- Type: EXPORT
Exports:
- Name: function_export
@ -10,9 +23,11 @@ Sections:
Index: 1
- Name: global_export
Kind: GLOBAL
Index: 2
Index: 0
- Type: CUSTOM
Name: linking
DataSize: 10
DataAlignment: 2
SymbolInfo:
- Name: function_export
Flags: 1
@ -30,9 +45,11 @@ Sections:
# CHECK: Index: 1
# CHECK: - Name: global_export
# CHECK: Kind: GLOBAL
# CHECK: Index: 2
# CHECK: Index: 0
# CHECK: - Type: CUSTOM
# CHECK: Name: linking
# CHECK: DataSize: 10
# CHECK: DataAlignment: 2
# CHECK: SymbolInfo:
# CHECK: - Name: function_export
# CHECK: Flags: 1

View File

@ -33,6 +33,8 @@ Sections:
Index: 0x00000002
- Type: CUSTOM
Name: linking
DataSize: 0
DataAlignment: 2
SymbolInfo:
- Name: weak_global_func
Flags: 1

View File

@ -77,6 +77,8 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
LinkingSec->SymbolInfos.push_back(Info);
}
}
LinkingSec->DataSize = Obj.linkingData().DataSize;
LinkingSec->DataAlignment = Obj.linkingData().DataAlignment;
CustomSec = std::move(LinkingSec);
} else {
CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);

View File

@ -110,22 +110,52 @@ static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
return 0;
}
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
writeStringRef(Section.Name, OS);
if (Section.SymbolInfos.size()) {
encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
std::string OutString;
raw_string_ostream StringStream(OutString);
class SubSectionWriter {
raw_ostream &OS;
std::string OutString;
raw_string_ostream StringStream;
encodeULEB128(Section.SymbolInfos.size(), StringStream);
for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
writeStringRef(Info.Name, StringStream);
encodeULEB128(Info.Flags, StringStream);
}
public:
SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
void Done() {
StringStream.flush();
encodeULEB128(OutString.size(), OS);
OS << OutString;
OutString.clear();
}
raw_ostream& GetStream() {
return StringStream;
}
};
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
writeStringRef(Section.Name, OS);
SubSectionWriter SubSection(OS);
// DATA_SIZE subsection
encodeULEB128(wasm::WASM_DATA_SIZE, OS);
encodeULEB128(Section.DataSize, SubSection.GetStream());
SubSection.Done();
// DATA_ALIGNMENT subsection
encodeULEB128(wasm::WASM_DATA_ALIGNMENT, OS);
encodeULEB128(Section.DataAlignment, SubSection.GetStream());
SubSection.Done();
// SYMBOL_INFO subsection
if (Section.SymbolInfos.size()) {
encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
encodeULEB128(Section.SymbolInfos.size(), SubSection.GetStream());
for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
writeStringRef(Info.Name, SubSection.GetStream());
encodeULEB128(Info.Flags, SubSection.GetStream());
}
SubSection.Done();
}
return 0;
}
@ -134,18 +164,16 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Sect
writeStringRef(Section.Name, OS);
if (Section.FunctionNames.size()) {
encodeULEB128(wasm::WASM_NAMES_FUNCTION, OS);
std::string OutString;
raw_string_ostream StringStream(OutString);
encodeULEB128(Section.FunctionNames.size(), StringStream);
SubSectionWriter SubSection(OS);
encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
encodeULEB128(NameEntry.Index, StringStream);
writeStringRef(NameEntry.Name, StringStream);
encodeULEB128(NameEntry.Index, SubSection.GetStream());
writeStringRef(NameEntry.Name, SubSection.GetStream());
}
StringStream.flush();
encodeULEB128(OutString.size(), OS);
OS << OutString;
SubSection.Done();
}
return 0;
}