[WebAssembly] Support multiple .init_array fragments when writing Wasm objects (#111008)
This commit is contained in:
@@ -1853,49 +1853,54 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
||||
if (EmptyFrag.getKind() != MCFragment::FT_Data)
|
||||
report_fatal_error(".init_array section should be aligned");
|
||||
|
||||
const MCFragment &AlignFrag = *EmptyFrag.getNext();
|
||||
if (AlignFrag.getKind() != MCFragment::FT_Align)
|
||||
report_fatal_error(".init_array section should be aligned");
|
||||
if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
|
||||
Align(is64Bit() ? 8 : 4))
|
||||
report_fatal_error(".init_array section should be aligned for pointers");
|
||||
|
||||
const MCFragment &Frag = *AlignFrag.getNext();
|
||||
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
|
||||
report_fatal_error("only data supported in .init_array section");
|
||||
|
||||
uint16_t Priority = UINT16_MAX;
|
||||
unsigned PrefixLength = strlen(".init_array");
|
||||
if (WS.getName().size() > PrefixLength) {
|
||||
if (WS.getName()[PrefixLength] != '.')
|
||||
const MCFragment *nextFrag = EmptyFrag.getNext();
|
||||
while (nextFrag != nullptr) {
|
||||
const MCFragment &AlignFrag = *nextFrag;
|
||||
if (AlignFrag.getKind() != MCFragment::FT_Align)
|
||||
report_fatal_error(".init_array section should be aligned");
|
||||
if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
|
||||
Align(is64Bit() ? 8 : 4))
|
||||
report_fatal_error(
|
||||
".init_array section priority should start with '.'");
|
||||
if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
|
||||
report_fatal_error("invalid .init_array section priority");
|
||||
}
|
||||
const auto &DataFrag = cast<MCDataFragment>(Frag);
|
||||
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
||||
for (const uint8_t *
|
||||
P = (const uint8_t *)Contents.data(),
|
||||
*End = (const uint8_t *)Contents.data() + Contents.size();
|
||||
P != End; ++P) {
|
||||
if (*P != 0)
|
||||
report_fatal_error("non-symbolic data in .init_array section");
|
||||
}
|
||||
for (const MCFixup &Fixup : DataFrag.getFixups()) {
|
||||
assert(Fixup.getKind() ==
|
||||
MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
|
||||
const MCExpr *Expr = Fixup.getValue();
|
||||
auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||
if (!SymRef)
|
||||
report_fatal_error("fixups in .init_array should be symbol references");
|
||||
const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
|
||||
if (TargetSym.getIndex() == InvalidIndex)
|
||||
report_fatal_error("symbols in .init_array should exist in symtab");
|
||||
if (!TargetSym.isFunction())
|
||||
report_fatal_error("symbols in .init_array should be for functions");
|
||||
InitFuncs.push_back(
|
||||
std::make_pair(Priority, TargetSym.getIndex()));
|
||||
".init_array section should be aligned for pointers");
|
||||
|
||||
const MCFragment &Frag = *AlignFrag.getNext();
|
||||
nextFrag = Frag.getNext();
|
||||
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
|
||||
report_fatal_error("only data supported in .init_array section");
|
||||
|
||||
uint16_t Priority = UINT16_MAX;
|
||||
unsigned PrefixLength = strlen(".init_array");
|
||||
if (WS.getName().size() > PrefixLength) {
|
||||
if (WS.getName()[PrefixLength] != '.')
|
||||
report_fatal_error(
|
||||
".init_array section priority should start with '.'");
|
||||
if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
|
||||
report_fatal_error("invalid .init_array section priority");
|
||||
}
|
||||
const auto &DataFrag = cast<MCDataFragment>(Frag);
|
||||
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
||||
for (const uint8_t *
|
||||
P = (const uint8_t *)Contents.data(),
|
||||
*End = (const uint8_t *)Contents.data() + Contents.size();
|
||||
P != End; ++P) {
|
||||
if (*P != 0)
|
||||
report_fatal_error("non-symbolic data in .init_array section");
|
||||
}
|
||||
for (const MCFixup &Fixup : DataFrag.getFixups()) {
|
||||
assert(Fixup.getKind() ==
|
||||
MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
|
||||
const MCExpr *Expr = Fixup.getValue();
|
||||
auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||
if (!SymRef)
|
||||
report_fatal_error(
|
||||
"fixups in .init_array should be symbol references");
|
||||
const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
|
||||
if (TargetSym.getIndex() == InvalidIndex)
|
||||
report_fatal_error("symbols in .init_array should exist in symtab");
|
||||
if (!TargetSym.isFunction())
|
||||
report_fatal_error("symbols in .init_array should be for functions");
|
||||
InitFuncs.push_back(std::make_pair(Priority, TargetSym.getIndex()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
49
llvm/test/MC/WebAssembly/init-array.s
Normal file
49
llvm/test/MC/WebAssembly/init-array.s
Normal file
@@ -0,0 +1,49 @@
|
||||
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck %s
|
||||
|
||||
init1:
|
||||
.functype init1 () -> ()
|
||||
end_function
|
||||
|
||||
init2:
|
||||
.functype init2 () -> ()
|
||||
end_function
|
||||
|
||||
.section .init_array,"",@
|
||||
.p2align 2, 0
|
||||
.int32 init1
|
||||
|
||||
.section .init_array,"",@
|
||||
.p2align 2
|
||||
.int32 init2
|
||||
|
||||
# CHECK: - Type: FUNCTION
|
||||
# CHECK-NEXT: FunctionTypes: [ 0, 0 ]
|
||||
# CHECK-NEXT: - Type: CODE
|
||||
# CHECK-NEXT: Functions:
|
||||
# CHECK-NEXT: - Index: 0
|
||||
# CHECK-NEXT: Locals: []
|
||||
# CHECK-NEXT: Body: 0B
|
||||
# CHECK-NEXT: - Index: 1
|
||||
# CHECK-NEXT: Locals: []
|
||||
# CHECK-NEXT: Body: 0B
|
||||
# CHECK-NEXT: - Type: CUSTOM
|
||||
# CHECK-NEXT: Name: linking
|
||||
# CHECK-NEXT: Version: 2
|
||||
# CHECK-NEXT: SymbolTable:
|
||||
# CHECK-NEXT: - Index: 0
|
||||
# CHECK-NEXT: Kind: FUNCTION
|
||||
# CHECK-NEXT: Name: init1
|
||||
# CHECK-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
# CHECK-NEXT: Function: 0
|
||||
# CHECK-NEXT: - Index: 1
|
||||
# CHECK-NEXT: Kind: FUNCTION
|
||||
# CHECK-NEXT: Name: init2
|
||||
# CHECK-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
# CHECK-NEXT: Function: 1
|
||||
# CHECK-NEXT: InitFunctions:
|
||||
# CHECK-NEXT: - Priority: 65535
|
||||
# CHECK-NEXT: Symbol: 0
|
||||
# CHECK-NEXT: - Priority: 65535
|
||||
# CHECK-NEXT: Symbol: 1
|
||||
# CHECK-NEXT: ...
|
||||
#
|
||||
Reference in New Issue
Block a user