106 lines · plain
1# A memory-address (data) relocation may, after symbol resolution, take the2# address of a symbol that resolves to a FUNCTION: an undefined symbol that MC3# was forced to type WASM_SYMBOL_TYPE_DATA (e.g. the target of a GNU-as alias,4# as glibc's libc_hidden_builtin redirect emits) can bind to a real FUNCTION5# definition of the same name (lld commit 12776b692). Taking that symbol's6# address must compute the wasm function pointer -- its index in7# __indirect_function_table -- instead of crashing in8# ObjFile::calcNewValue/InputChunk::getVA on a symbol with no data layout, and9# the re-emitted relocation must be the table-index form (a memory-address10# relocation against a function symbol is invalid in the wasm object format).11#12# This is the direct completion of 12776b692 (which resolved the *type*; this13# resolves the *relocation that takes the address*).14 15# RUN: rm -rf %t && split-file %s %t16# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/ref.s -o %t/ref.o17# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/func.s -o %t/func.o18# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/refadd.s -o %t/refadd.o19# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/datadata.s -o %t/datadata.o20# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/code.s -o %t/code.o21 22## GREEN: a data relocation that takes the address of a symbol resolving to a23## FUNCTION links (no crash), in either object order, and is re-emitted as a24## table-index relocation against the function.25# RUN: wasm-ld -r -o %t/r1.o %t/ref.o %t/func.o26# RUN: llvm-objdump --syms %t/r1.o | FileCheck %s --check-prefix=SYMS27# RUN: llvm-objdump -r %t/r1.o | FileCheck %s --check-prefix=RELOC28# RUN: wasm-ld -r -o %t/r2.o %t/func.o %t/ref.o29# RUN: llvm-objdump -r %t/r2.o | FileCheck %s --check-prefix=RELOC30 31## The re-emitted relocatable object is itself valid and links again cleanly.32# RUN: wasm-ld -r -o %t/r1b.o %t/r1.o33 34## A code-section function-address reference (i32.const &func -> a SLEB35## memory-address relocation, as glibc's _nl_make_l10nflist emits taking36## &__GI_strcpy) is likewise re-emitted as a table-index relocation.37# RUN: wasm-ld -r -o %t/c.o %t/code.o %t/func.o38# RUN: llvm-objdump -r %t/c.o | FileCheck %s --check-prefix=CODE39# RUN: wasm-ld -r -o %t/cb.o %t/c.o40 41## A normal data-to-data relocation is unaffected: it stays a memory-address42## relocation.43# RUN: wasm-ld -r -o %t/dd.o %t/datadata.o44# RUN: llvm-objdump -r %t/dd.o | FileCheck %s --check-prefix=DATADATA45 46## NEVER-SILENT: a function address with a non-zero addend cannot be represented47## as a table index, so it diagnoses loudly instead of crashing or emitting a48## wrong value.49# RUN: not wasm-ld -r -o %t/bad.o %t/refadd.o %t/func.o 2>&1 | FileCheck %s --check-prefix=ADDEND50 51# SYMS-DAG: F {{.*}}__GI_memset52# SYMS-DAG: O DATA {{.*}}p53# RELOC: R_WASM_TABLE_INDEX_I32 __GI_memset54# CODE: R_WASM_TABLE_INDEX_SLEB __GI_memset55# DATADATA: R_WASM_MEMORY_ADDR_I32 data_target56# ADDEND: error: {{.*}}cannot take the address of function `__GI_memset`{{.*}}non-zero addend57 58#--- ref.s59## `p` holds the address of __GI_memset, which is undefined here and referenced60## only as a data address, so MC types it DATA. It resolves to the FUNCTION61## defined in func.s.62.globl p63.section .data.p,"",@64p:65 .int32 __GI_memset66.size p, 467 68#--- func.s69.globl __GI_memset70__GI_memset:71 .functype __GI_memset (i32, i32, i32) -> (i32)72 local.get 073 end_function74 75#--- refadd.s76## Same, but takes __GI_memset + 4: a function pointer is a table index, so a77## non-zero byte addend is not representable.78.globl q79.section .data.q,"",@80q:81 .int32 __GI_memset+482.size q, 483 84#--- code.s85## A function body that takes the address of __GI_memset (undefined data here,86## referenced as an i32.const operand -> R_WASM_MEMORY_ADDR_SLEB). It resolves87## to the FUNCTION in func.s.88.globl caller89caller:90 .functype caller () -> (i32)91 i32.const __GI_memset92 end_function93 94#--- datadata.s95## A plain data-to-data address relocation; must remain a memory-address reloc.96.globl data_target97.section .data.data_target,"",@98data_target:99 .int32 7100.size data_target, 4101.globl dp102.section .data.dp,"",@103dp:104 .int32 data_target105.size dp, 4106