[WebAssembly] Write out undefined symbol addresses as zero

The addresses of undefined symbols that make it into the final
executable (i.e. weak references to non-existent symbols) should
resolve to zero.

Also, make sure to not include function in the indirect function
table if they are not included in the output.

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

llvm-svn: 322045
This commit is contained in:
Sam Clegg 2018-01-08 23:39:11 +00:00
parent 0f03c79b6d
commit 87e61923a4
7 changed files with 26 additions and 35 deletions

View File

@ -159,7 +159,7 @@ declare i32 @foo_import() local_unnamed_addr
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 16
; CHECK-NEXT: Content: FFFFFFFF
; CHECK-NEXT: Content: '00000000'
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 20

View File

@ -40,8 +40,8 @@ entry:
; CHECK-NEXT: - ElemType: ANYFUNC
; CHECK-NEXT: Limits:
; CHECK-NEXT: Flags: [ HAS_MAX ]
; CHECK-NEXT: Initial: 0x00000002
; CHECK-NEXT: Maximum: 0x00000002
; CHECK-NEXT: Initial: 0x00000001
; CHECK-NEXT: Maximum: 0x00000001
; CHECK-NEXT: - Type: MEMORY
; CHECK-NEXT: Memories:
; CHECK-NEXT: - Initial: 0x00000002
@ -66,20 +66,14 @@ entry:
; CHECK-NEXT: - Name: get_address_of_global_var
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Type: ELEM
; CHECK-NEXT: Segments:
; CHECK-NEXT: - Offset:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 1
; CHECK-NEXT: Functions: [ 0 ]
; CHECK-NEXT: - Type: CODE
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Locals:
; CHECK-NEXT: Body: 4181808080000B
; CHECK-NEXT: Body: 4180808080000B
; CHECK-NEXT: - Locals:
; CHECK-NEXT: Body: 41FFFFFFFF7F0B
; CHECK-NEXT: Body: 4180808080000B
; CHECK-NEXT: - Locals:
; CHECK-NEXT: Body: 41002802FFFFFFFF0F0B
; CHECK-NEXT: Body: 4100280280808080000B
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 0

View File

@ -83,7 +83,7 @@ uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
Symbol *Sym = getTableSymbol(Original);
uint32_t Index = Sym->getTableIndex();
uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
<< " -> " << Index << "\n");
return Index;
@ -91,7 +91,7 @@ uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
Symbol *Sym = getGlobalSymbol(Original);
uint32_t Index = Sym->getOutputIndex();
uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0;
DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
<< " -> " << Index << "\n");
return Index;

View File

@ -157,16 +157,12 @@ static void calcRelocations(const ObjFile &File,
if (Config->EmitRelocs)
NewReloc.NewIndex = calcNewIndex(File, Reloc);
else
NewReloc.NewIndex = UINT32_MAX;
switch (Reloc.Type) {
case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
case R_WEBASSEMBLY_MEMORY_ADDR_I32:
case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
NewReloc.Value = File.getRelocatedAddress(Reloc.Index);
if (NewReloc.Value != UINT32_MAX)
NewReloc.Value += Reloc.Addend;
NewReloc.Value = File.getRelocatedAddress(Reloc.Index) + Reloc.Addend;
break;
default:
NewReloc.Value = calcNewIndex(File, Reloc);

View File

@ -40,7 +40,7 @@ uint32_t Symbol::getVirtualAddress() const {
assert(isGlobal());
DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
if (isUndefined())
return UINT32_MAX;
return 0;
if (VirtualAddress.hasValue())
return VirtualAddress.getValue();
@ -53,12 +53,6 @@ uint32_t Symbol::getVirtualAddress() const {
return Segment->translateVA(Global.InitExpr.Value.Int32);
}
uint32_t Symbol::getOutputIndex() const {
if (isUndefined() && isWeak())
return 0;
return OutputIndex.getValue();
}
void Symbol::setVirtualAddress(uint32_t Value) {
DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
assert(!VirtualAddress.hasValue());

View File

@ -71,23 +71,28 @@ public:
bool hasFunctionType() const { return FunctionType != nullptr; }
const WasmSignature &getFunctionType() const;
uint32_t getOutputIndex() const;
uint32_t getTableIndex() const { return TableIndex.getValue(); }
// Returns the virtual address of a defined global.
// Only works for globals, not functions.
uint32_t getVirtualAddress() const;
uint32_t getOutputIndex() const { return OutputIndex.getValue(); }
// Returns true if an output index has been set for this symbol
bool hasOutputIndex() const { return OutputIndex.hasValue(); }
// Set the output index of the symbol (in the function or global index
// space of the output object.
void setOutputIndex(uint32_t Index);
uint32_t getTableIndex() const { return TableIndex.getValue(); }
// Returns true if a table index has been set for this symbol
bool hasTableIndex() const { return TableIndex.hasValue(); }
// Set the table index of the symbol
void setTableIndex(uint32_t Index);
// Returns the virtual address of a defined global.
// Only works for globals, not functions.
uint32_t getVirtualAddress() const;
void setVirtualAddress(uint32_t VA);
void update(Kind K, InputFile *F = nullptr, const WasmSymbol *Sym = nullptr,

View File

@ -629,12 +629,14 @@ void Writer::assignSymbolIndexes() {
Sym->setOutputIndex(GlobalIndex++);
}
}
}
for (ObjFile *File : Symtab->ObjectFiles) {
for (Symbol *Sym : File->getTableSymbols()) {
if (!Sym->hasTableIndex()) {
Sym->setTableIndex(TableIndex++);
IndirectFunctions.emplace_back(Sym);
}
if (Sym->hasTableIndex() || !Sym->hasOutputIndex())
continue;
Sym->setTableIndex(TableIndex++);
IndirectFunctions.emplace_back(Sym);
}
}
}