Index: include/llvm/Object/Wasm.h =================================================================== --- include/llvm/Object/Wasm.h +++ include/llvm/Object/Wasm.h @@ -208,6 +208,10 @@ const WasmSection &getWasmSection(DataRefImpl Ref) const; const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; + const wasm::WasmDataSegment &getWasmDataSegment(DataRefImpl Ref) const; + + const ArrayRef &getDataRefContent(DataRefImpl Ref) const; + WasmSection* findCustomSectionByName(StringRef Name); WasmSection* findSectionByType(uint32_t Type); Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -846,7 +846,14 @@ write8(wasm::WASM_OPCODE_I32_CONST); encodeSLEB128(Segment.Offset, getStream()); // offset write8(wasm::WASM_OPCODE_END); - encodeULEB128(Segment.Data.size(), getStream()); // size + + raw_null_ostream NullStream; + unsigned SizeLen = encodeULEB128(Segment.Data.size(), NullStream); + uint64_t Padding = OffsetToAlignment(getStream().tell() + SizeLen, Segment.Alignment); + unsigned ActualSizeLen = encodeULEB128(Segment.Data.size(), getStream(), SizeLen + Padding); // size + assert((SizeLen +Padding) == ActualSizeLen); + + assert(OffsetToAlignment(getStream().tell(), Segment.Alignment) == 0 && "DataSegments is not aligned"); Segment.Section->setSectionOffset(getStream().tell() - Section.ContentsOffset); writeBytes(Segment.Data); // data } Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -982,7 +982,14 @@ return section_iterator(SectionRef(Ref, this)); } -void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } +void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { + if (isSectionData(Sec) && (Sec.d.b < (DataSegments.size()-1))) { + Sec.d.b++; + } else { + Sec.d.a++; + Sec.d.b = 0; + } +} std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, StringRef &Res) const { @@ -1002,7 +1009,11 @@ ECase(START); ECase(ELEM); ECase(CODE); - ECase(DATA); + case wasm::WASM_SEC_DATA: { + const WasmSegment &Seg = DataSegments[Sec.d.b]; + Res = Seg.Data.Name; + break; + } case wasm::WASM_SEC_CUSTOM: Res = S.Name; break; @@ -1020,22 +1031,41 @@ } uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { - const WasmSection &S = Sections[Sec.d.a]; - return S.Content.size(); + return getDataRefContent(Sec).size(); } std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { - const WasmSection &S = Sections[Sec.d.a]; - // This will never fail since wasm sections can never be empty (user-sections - // must have a name and non-user sections each have a defined structure). - Res = StringRef(reinterpret_cast(S.Content.data()), - S.Content.size()); + + const ArrayRef &Content = getDataRefContent(Sec); + + Res = StringRef(reinterpret_cast(Content.data()), + Content.size()); return std::error_code(); } uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { - return 1; + if (isSectionData(Sec)) { + const wasm::WasmDataSegment &Data = getWasmDataSegment(Sec); + return Data.Alignment; + } + + return 1; +} + +const wasm::WasmDataSegment &WasmObjectFile::getWasmDataSegment(DataRefImpl Sec) const { + assert(isSectionData(Sec) && "Section should be Data"); + assert(Sec.d.b < DataSegments.size()); + return DataSegments[Sec.d.b].Data; +} + +const ArrayRef &WasmObjectFile::getDataRefContent(DataRefImpl Sec) const { + if (isSectionData(Sec)) + return getWasmDataSegment(Sec).Content; + + // This will never fail since wasm sections can never be empty (user-sections + // must have a name and non-user sections each have a defined structure). + return getWasmSection(Sec).Content; } bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { Index: test/MC/WebAssembly/bss.ll =================================================================== --- test/MC/WebAssembly/bss.ll +++ test/MC/WebAssembly/bss.ll @@ -55,19 +55,19 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '00000000' -; CHECK-NEXT: - SectionOffset: 15 +; CHECK-NEXT: - SectionOffset: 18 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 4 ; CHECK-NEXT: Content: '00000000' -; CHECK-NEXT: - SectionOffset: 24 +; CHECK-NEXT: - SectionOffset: 27 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '00' -; CHECK-NEXT: - SectionOffset: 30 +; CHECK-NEXT: - SectionOffset: 33 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST Index: test/MC/WebAssembly/explicit-sections.ll =================================================================== --- test/MC/WebAssembly/explicit-sections.ll +++ test/MC/WebAssembly/explicit-sections.ll @@ -49,19 +49,19 @@ ; CHECK-NEXT: Index: 3 ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: -; CHECK-NEXT: - SectionOffset: 6 +; CHECK-NEXT: - SectionOffset: 8 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '08000000' -; CHECK-NEXT: - SectionOffset: 15 +; CHECK-NEXT: - SectionOffset: 24 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '01000000030000000700000000000000' -; CHECK-NEXT: - SectionOffset: 36 +; CHECK-NEXT: - SectionOffset: 48 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST Index: test/MC/WebAssembly/external-data.ll =================================================================== --- test/MC/WebAssembly/external-data.ll +++ test/MC/WebAssembly/external-data.ll @@ -11,7 +11,7 @@ ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: Offset: 0x00000013 +; CHECK-NEXT: Offset: 0x00000016 ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 ; CHECK-NEXT: MemoryIndex: 0 @@ -19,7 +19,7 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '0700000000000000' -; CHECK-NEXT: - SectionOffset: 19 +; CHECK-NEXT: - SectionOffset: 22 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST Index: test/MC/WebAssembly/global-ctor-dtor.ll =================================================================== --- test/MC/WebAssembly/global-ctor-dtor.ll +++ test/MC/WebAssembly/global-ctor-dtor.ll @@ -130,7 +130,7 @@ ; CHECK-NEXT: Body: 024041828080800041004180808080001081808080000D000F0B00000B ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: -; CHECK-NEXT: - SectionOffset: 6 +; CHECK-NEXT: - SectionOffset: 13 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST Index: test/MC/WebAssembly/reloc-data.ll =================================================================== --- test/MC/WebAssembly/reloc-data.ll +++ test/MC/WebAssembly/reloc-data.ll @@ -6,38 +6,38 @@ @bar = global i64 7, align 4 @a = global i32* getelementptr (i32, i32* @foo, i32 2), align 8 @b = global i64* getelementptr (i64, i64* @bar, i64 -2), align 8 -@c = global [3 x i32*] [i32* @foo, i32* @foo, i32* @foo], align 16 +@c = global [3 x i32*] [i32* @foo, i32* @foo, i32* @foo], align 8 ; CHECK: Format: WASM ; CHECK: Relocations [ ; CHECK-NEXT: Section (4) DATA { ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x13 +; CHECK-NEXT: Offset: 0x1B ; CHECK-NEXT: Index: 0x0 ; CHECK-NEXT: Addend: 8 ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x1C +; CHECK-NEXT: Offset: 0x2B ; CHECK-NEXT: Index: 0x1 ; CHECK-NEXT: Addend: -16 ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x25 +; CHECK-NEXT: Offset: 0x3B ; CHECK-NEXT: Index: 0x0 ; CHECK-NEXT: Addend: 0 ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x29 +; CHECK-NEXT: Offset: 0x3F ; CHECK-NEXT: Index: 0x0 ; CHECK-NEXT: Addend: 0 ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x2D +; CHECK-NEXT: Offset: 0x43 ; CHECK-NEXT: Index: 0x0 ; CHECK-NEXT: Addend: 0 ; CHECK-NEXT: } Index: test/MC/WebAssembly/unnamed-data.ll =================================================================== --- test/MC/WebAssembly/unnamed-data.ll +++ test/MC/WebAssembly/unnamed-data.ll @@ -54,7 +54,7 @@ ; CHECK-NEXT: Offset: 0x0000001C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Offset: 0x00000025 +; CHECK-NEXT: Offset: 0x0000002C ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 ; CHECK-NEXT: MemoryIndex: 0 @@ -74,7 +74,7 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 16 ; CHECK-NEXT: Content: '00000000' -; CHECK-NEXT: - SectionOffset: 37 +; CHECK-NEXT: - SectionOffset: 44 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST Index: test/MC/WebAssembly/weak-alias.ll =================================================================== --- test/MC/WebAssembly/weak-alias.ll +++ test/MC/WebAssembly/weak-alias.ll @@ -172,18 +172,18 @@ ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Offset: 0x0000000F +; CHECK-NEXT: Offset: 0x00000018 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 2 -; CHECK-NEXT: Offset: 0x00000018 +; CHECK-NEXT: Offset: 0x00000028 ; CHECK-NEXT: Segments: -; CHECK-NEXT: - SectionOffset: 6 +; CHECK-NEXT: - SectionOffset: 8 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '07000000' -; CHECK-NEXT: - SectionOffset: 15 +; CHECK-NEXT: - SectionOffset: 24 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST Index: test/tools/llvm-objdump/WebAssembly/relocations.test =================================================================== --- test/tools/llvm-objdump/WebAssembly/relocations.test +++ test/tools/llvm-objdump/WebAssembly/relocations.test @@ -4,5 +4,11 @@ @foo2 = hidden global i32 1, align 4 @bar = hidden global i32* @foo2, align 4 -; CHECK: RELOCATION RECORDS FOR [DATA]: -; CHECK-NEXT: 00000018 R_WEBASSEMBLY_MEMORY_ADDR_I32 1+0 +; CHECK: RELOCATION RECORDS FOR [.data.foo1]: +; CHECK-NEXT: 00000021 R_WEBASSEMBLY_MEMORY_ADDR_I32 1+0 + +; CHECK: RELOCATION RECORDS FOR [.data.foo2]: +; CHECK-NEXT: 00000021 R_WEBASSEMBLY_MEMORY_ADDR_I32 1+0 + +; CHECK: RELOCATION RECORDS FOR [.data.bar]: +; CHECK-NEXT: 00000021 R_WEBASSEMBLY_MEMORY_ADDR_I32 1+0 Index: test/tools/llvm-objdump/wasm.txt =================================================================== --- test/tools/llvm-objdump/wasm.txt +++ test/tools/llvm-objdump/wasm.txt @@ -10,7 +10,7 @@ # CHECK-NEXT: 5 GLOBAL 0000000b 0000000000000000 # CHECK-NEXT: 6 EXPORT 0000000e 0000000000000000 # CHECK-NEXT: 7 CODE 00000019 0000000000000000 TEXT -# CHECK-NEXT: 8 DATA 0000001a 0000000000000000 DATA +# CHECK-NEXT: 8 00000014 0000000000000000 DATA # CHECK-NEXT: 9 name 0000002b 0000000000000000 # CHECK-NEXT: 10 reloc.CODE 00000017 0000000000000000 # CHECK-NEXT: 11 linking 00000016 0000000000000000 Index: tools/llvm-readobj/WasmDumper.cpp =================================================================== --- tools/llvm-readobj/WasmDumper.cpp +++ tools/llvm-readobj/WasmDumper.cpp @@ -110,13 +110,23 @@ void WasmDumper::printRelocations() { ListScope D(W, "Relocations"); + int FirstDataSection = true; int SectionNumber = 0; for (const SectionRef &Section : Obj->sections()) { bool PrintedGroup = false; StringRef Name; error(Section.getName(Name)); - ++SectionNumber; + const WasmSection &Sec = Obj->getWasmSection(Section); + if (Sec.Type == wasm::WASM_SEC_DATA) { + if (! FirstDataSection) + continue; + + Name = "DATA"; + FirstDataSection = false; + } + + ++SectionNumber; for (const RelocationRef &Reloc : Section.relocations()) { if (!PrintedGroup) { W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; @@ -143,8 +153,12 @@ void WasmDumper::printSections() { ListScope Group(W, "Sections"); + bool FirstDataSection = true; for (const SectionRef &Section : Obj->sections()) { const WasmSection &WasmSec = Obj->getWasmSection(Section); + if (WasmSec.Type == wasm::WASM_SEC_DATA && !FirstDataSection) + continue; + DictScope SectionD(W, "Section"); W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes)); W.printNumber("Size", static_cast(WasmSec.Content.size())); @@ -164,6 +178,7 @@ } break; case wasm::WASM_SEC_DATA: { + FirstDataSection = false; ListScope Group(W, "Segments"); for (const WasmSegment &Segment : Obj->dataSegments()) { const wasm::WasmDataSegment& Seg = Segment.Data; Index: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- tools/obj2yaml/wasm2yaml.cpp +++ tools/obj2yaml/wasm2yaml.cpp @@ -116,6 +116,7 @@ // Dump header Y->Header.Version = Obj.getHeader().Version; + bool FirstDataSection = true; // Dump sections for (const auto &Sec : Obj.sections()) { @@ -259,6 +260,9 @@ break; } case wasm::WASM_SEC_DATA: { + if (!FirstDataSection) + continue; + FirstDataSection = false; auto DataSec = make_unique(); for (const object::WasmSegment &Segment : Obj.dataSegments()) { WasmYAML::DataSegment Seg;