forked from OSchip/llvm-project
[WebAssembly] Don't allow functions to be named more than once
Even though a function can have multiple names in the linking standards (i.e. due to aliases), there can only be one name for a given function in the NAME section. Differential Revision: https://reviews.llvm.org/D41975 llvm-svn: 322383
This commit is contained in:
parent
ffbfc0f827
commit
408064ef1e
|
@ -0,0 +1,66 @@
|
|||
; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s
|
||||
; RUN: lld -flavor wasm %t.o -o %t.wasm
|
||||
; RUN: obj2yaml %t.wasm | FileCheck %s
|
||||
|
||||
@start_alias = alias i32 (), i32 ()* @_start
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define i32 @_start() local_unnamed_addr #1 {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; CHECK: --- !WASM
|
||||
; CHECK-NEXT: FileHeader:
|
||||
; CHECK-NEXT: Version: 0x00000001
|
||||
; CHECK-NEXT: Sections:
|
||||
; CHECK-NEXT: - Type: TYPE
|
||||
; CHECK-NEXT: Signatures:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ReturnType: I32
|
||||
; CHECK-NEXT: ParamTypes:
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - ElemType: ANYFUNC
|
||||
; CHECK-NEXT: Limits:
|
||||
; CHECK-NEXT: Flags: [ HAS_MAX ]
|
||||
; CHECK-NEXT: Initial: 0x00000001
|
||||
; CHECK-NEXT: Maximum: 0x00000001
|
||||
; CHECK-NEXT: - Type: MEMORY
|
||||
; CHECK-NEXT: Memories:
|
||||
; CHECK-NEXT: - Initial: 0x00000002
|
||||
; CHECK-NEXT: - Type: GLOBAL
|
||||
; CHECK-NEXT: Globals:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Type: I32
|
||||
; CHECK-NEXT: Mutable: true
|
||||
; CHECK-NEXT: InitExpr:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 66560
|
||||
; CHECK-NEXT: - Type: EXPORT
|
||||
; CHECK-NEXT: Exports:
|
||||
; CHECK-NEXT: - Name: memory
|
||||
; CHECK-NEXT: Kind: MEMORY
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: - Name: _start
|
||||
; CHECK-NEXT: Kind: FUNCTION
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: - Name: start_alias
|
||||
; CHECK-NEXT: Kind: FUNCTION
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: - Type: CODE
|
||||
; CHECK-NEXT: Functions:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Locals:
|
||||
; CHECK-NEXT: Body: 41000B
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: name
|
||||
; CHECK-NEXT: FunctionNames:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Name: start_alias
|
||||
; CHECK-NEXT: ...
|
|
@ -110,7 +110,7 @@ class InputFunction : public InputChunk {
|
|||
public:
|
||||
InputFunction(const WasmSignature &S, const WasmFunction &Func,
|
||||
const ObjFile &F)
|
||||
: InputChunk(F), Signature(S), Function(Func) {}
|
||||
: InputChunk(F), Signature(S), WrittenToNameSec(false), Function(Func) {}
|
||||
|
||||
uint32_t getSize() const override { return Function.Size; }
|
||||
const uint8_t *getData() const override {
|
||||
|
@ -126,6 +126,8 @@ public:
|
|||
|
||||
const WasmSignature &Signature;
|
||||
|
||||
unsigned WrittenToNameSec : 1;
|
||||
|
||||
protected:
|
||||
uint32_t getInputSectionOffset() const override {
|
||||
return Function.CodeSectionOffset;
|
||||
|
|
|
@ -74,7 +74,7 @@ void Symbol::setTableIndex(uint32_t Index) {
|
|||
}
|
||||
|
||||
void Symbol::update(Kind K, InputFile *F, uint32_t Flags_,
|
||||
const InputSegment *Seg, const InputFunction *Func,
|
||||
const InputSegment *Seg, InputFunction *Func,
|
||||
uint32_t Address) {
|
||||
SymbolKind = K;
|
||||
File = F;
|
||||
|
|
|
@ -93,11 +93,11 @@ public:
|
|||
|
||||
void update(Kind K, InputFile *F = nullptr, uint32_t Flags = 0,
|
||||
const InputSegment *Segment = nullptr,
|
||||
const InputFunction *Function = nullptr,
|
||||
uint32_t Address = UINT32_MAX);
|
||||
InputFunction *Function = nullptr, uint32_t Address = UINT32_MAX);
|
||||
|
||||
void setArchiveSymbol(const Archive::Symbol &Sym) { ArchiveSymbol = Sym; }
|
||||
const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; }
|
||||
InputFunction *getFunction() { return Function; }
|
||||
|
||||
// This bit is used by Writer::writeNameSection() to prevent
|
||||
// symbols from being written to the symbol table more than once.
|
||||
|
@ -113,7 +113,7 @@ protected:
|
|||
Kind SymbolKind = InvalidKind;
|
||||
InputFile *File = nullptr;
|
||||
const InputSegment *Segment = nullptr;
|
||||
const InputFunction *Function = nullptr;
|
||||
InputFunction *Function = nullptr;
|
||||
llvm::Optional<uint32_t> OutputIndex;
|
||||
llvm::Optional<uint32_t> TableIndex;
|
||||
const WasmSignature *FunctionType = nullptr;
|
||||
|
|
|
@ -442,6 +442,15 @@ void Writer::createNameSection() {
|
|||
for (Symbol *S : File->getSymbols()) {
|
||||
if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec)
|
||||
continue;
|
||||
// We also need to guard against two different symbols (two different
|
||||
// names) for the same wasm function. While this is possible (aliases)
|
||||
// it is not legal in the "name" section.
|
||||
InputFunction *Function = S->getFunction();
|
||||
if (Function) {
|
||||
if (Function->WrittenToNameSec)
|
||||
continue;
|
||||
Function->WrittenToNameSec = true;
|
||||
}
|
||||
S->WrittenToNameSec = true;
|
||||
Names.emplace_back(S);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue