Skip to content

Commit 8069ce6

Browse files
georgestaggtru
authored andcommitted
[WebAssembly] Support multiple .init_array fragments when writing Wasm objects (#111008)
(cherry picked from commit ac5dd45)
1 parent 2384a06 commit 8069ce6

File tree

2 files changed

+96
-42
lines changed

2 files changed

+96
-42
lines changed

llvm/lib/MC/WasmObjectWriter.cpp

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,49 +1853,54 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
18531853
if (EmptyFrag.getKind() != MCFragment::FT_Data)
18541854
report_fatal_error(".init_array section should be aligned");
18551855

1856-
const MCFragment &AlignFrag = *EmptyFrag.getNext();
1857-
if (AlignFrag.getKind() != MCFragment::FT_Align)
1858-
report_fatal_error(".init_array section should be aligned");
1859-
if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1860-
Align(is64Bit() ? 8 : 4))
1861-
report_fatal_error(".init_array section should be aligned for pointers");
1862-
1863-
const MCFragment &Frag = *AlignFrag.getNext();
1864-
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1865-
report_fatal_error("only data supported in .init_array section");
1866-
1867-
uint16_t Priority = UINT16_MAX;
1868-
unsigned PrefixLength = strlen(".init_array");
1869-
if (WS.getName().size() > PrefixLength) {
1870-
if (WS.getName()[PrefixLength] != '.')
1856+
const MCFragment *nextFrag = EmptyFrag.getNext();
1857+
while (nextFrag != nullptr) {
1858+
const MCFragment &AlignFrag = *nextFrag;
1859+
if (AlignFrag.getKind() != MCFragment::FT_Align)
1860+
report_fatal_error(".init_array section should be aligned");
1861+
if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1862+
Align(is64Bit() ? 8 : 4))
18711863
report_fatal_error(
1872-
".init_array section priority should start with '.'");
1873-
if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1874-
report_fatal_error("invalid .init_array section priority");
1875-
}
1876-
const auto &DataFrag = cast<MCDataFragment>(Frag);
1877-
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1878-
for (const uint8_t *
1879-
P = (const uint8_t *)Contents.data(),
1880-
*End = (const uint8_t *)Contents.data() + Contents.size();
1881-
P != End; ++P) {
1882-
if (*P != 0)
1883-
report_fatal_error("non-symbolic data in .init_array section");
1884-
}
1885-
for (const MCFixup &Fixup : DataFrag.getFixups()) {
1886-
assert(Fixup.getKind() ==
1887-
MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
1888-
const MCExpr *Expr = Fixup.getValue();
1889-
auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1890-
if (!SymRef)
1891-
report_fatal_error("fixups in .init_array should be symbol references");
1892-
const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1893-
if (TargetSym.getIndex() == InvalidIndex)
1894-
report_fatal_error("symbols in .init_array should exist in symtab");
1895-
if (!TargetSym.isFunction())
1896-
report_fatal_error("symbols in .init_array should be for functions");
1897-
InitFuncs.push_back(
1898-
std::make_pair(Priority, TargetSym.getIndex()));
1864+
".init_array section should be aligned for pointers");
1865+
1866+
const MCFragment &Frag = *AlignFrag.getNext();
1867+
nextFrag = Frag.getNext();
1868+
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1869+
report_fatal_error("only data supported in .init_array section");
1870+
1871+
uint16_t Priority = UINT16_MAX;
1872+
unsigned PrefixLength = strlen(".init_array");
1873+
if (WS.getName().size() > PrefixLength) {
1874+
if (WS.getName()[PrefixLength] != '.')
1875+
report_fatal_error(
1876+
".init_array section priority should start with '.'");
1877+
if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1878+
report_fatal_error("invalid .init_array section priority");
1879+
}
1880+
const auto &DataFrag = cast<MCDataFragment>(Frag);
1881+
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1882+
for (const uint8_t *
1883+
P = (const uint8_t *)Contents.data(),
1884+
*End = (const uint8_t *)Contents.data() + Contents.size();
1885+
P != End; ++P) {
1886+
if (*P != 0)
1887+
report_fatal_error("non-symbolic data in .init_array section");
1888+
}
1889+
for (const MCFixup &Fixup : DataFrag.getFixups()) {
1890+
assert(Fixup.getKind() ==
1891+
MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
1892+
const MCExpr *Expr = Fixup.getValue();
1893+
auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1894+
if (!SymRef)
1895+
report_fatal_error(
1896+
"fixups in .init_array should be symbol references");
1897+
const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1898+
if (TargetSym.getIndex() == InvalidIndex)
1899+
report_fatal_error("symbols in .init_array should exist in symtab");
1900+
if (!TargetSym.isFunction())
1901+
report_fatal_error("symbols in .init_array should be for functions");
1902+
InitFuncs.push_back(std::make_pair(Priority, TargetSym.getIndex()));
1903+
}
18991904
}
19001905
}
19011906

llvm/test/MC/WebAssembly/init-array.s

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck %s
2+
3+
init1:
4+
.functype init1 () -> ()
5+
end_function
6+
7+
init2:
8+
.functype init2 () -> ()
9+
end_function
10+
11+
.section .init_array,"",@
12+
.p2align 2, 0
13+
.int32 init1
14+
15+
.section .init_array,"",@
16+
.p2align 2
17+
.int32 init2
18+
19+
# CHECK: - Type: FUNCTION
20+
# CHECK-NEXT: FunctionTypes: [ 0, 0 ]
21+
# CHECK-NEXT: - Type: CODE
22+
# CHECK-NEXT: Functions:
23+
# CHECK-NEXT: - Index: 0
24+
# CHECK-NEXT: Locals: []
25+
# CHECK-NEXT: Body: 0B
26+
# CHECK-NEXT: - Index: 1
27+
# CHECK-NEXT: Locals: []
28+
# CHECK-NEXT: Body: 0B
29+
# CHECK-NEXT: - Type: CUSTOM
30+
# CHECK-NEXT: Name: linking
31+
# CHECK-NEXT: Version: 2
32+
# CHECK-NEXT: SymbolTable:
33+
# CHECK-NEXT: - Index: 0
34+
# CHECK-NEXT: Kind: FUNCTION
35+
# CHECK-NEXT: Name: init1
36+
# CHECK-NEXT: Flags: [ BINDING_LOCAL ]
37+
# CHECK-NEXT: Function: 0
38+
# CHECK-NEXT: - Index: 1
39+
# CHECK-NEXT: Kind: FUNCTION
40+
# CHECK-NEXT: Name: init2
41+
# CHECK-NEXT: Flags: [ BINDING_LOCAL ]
42+
# CHECK-NEXT: Function: 1
43+
# CHECK-NEXT: InitFunctions:
44+
# CHECK-NEXT: - Priority: 65535
45+
# CHECK-NEXT: Symbol: 0
46+
# CHECK-NEXT: - Priority: 65535
47+
# CHECK-NEXT: Symbol: 1
48+
# CHECK-NEXT: ...
49+
#

0 commit comments

Comments
 (0)