125 lines · plain
1# A size-0 DATA *definition* -- a bare label (`.globl m` / `m:`, with no2# `.functype`/`.type`/`.size`) that MC commit 95803ba61 makes assemble as a3# size-0 DATA symbol in a synthesized empty data segment (wasm has no4# NOTYPE/untyped symbol kind) -- is typeless, like a NOTYPE symbol on ELF. It5# must (a) defer to a real FUNCTION *definition* of the same name (the typed6# definition wins) and (b) *satisfy* an undefined FUNCTION reference (a call)7# without being demoted or pulling a real implementation -- instead of being8# rejected with a spurious "symbol type mismatch".9#10# This is the LINK-stage sequel to 95803ba61: glibc's stock elf/Makefile emits11# exactly such bare labels for the rtld symbol map (rtld-stubbed-symbols:12# malloc/free/calloc/__syscall_cancel/...), into a throwaway object13# (librtld.mapT.o) whose symbol *definitions* are placeholders. Those stubs are14# *deliberately* defined so the relocatable link does NOT pull their real15# implementation out of libc_pic.a ("stubbed out during symbol discovery ...16# provided differently in rtld"); the link must resolve calls to malloc/free17# against the stub, not error.18#19# On ELF/GNU-as a bare label is NOTYPE and resolves against whatever defines or20# references it. The relaxation is tightly guarded (never-silent): only a21# *zero-size* DATA definition is typeless -- a real (non-zero) DATA object vs a22# FUNCTION of the same name, whether a definition or a call, still errors23# loudly, so two real, genuinely-conflicting definitions are never silently24# merged.25#26# Sibling of 12776b692 (which resolved an *undefined* DATA ref against a27# function); this resolves a *defined* DATA placeholder against, and as a stub28# for, a function.29 30# RUN: rm -rf %t && split-file %s %t31# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/bare.s -o %t/bare.o32# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/func.s -o %t/func.o33# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/realdata.s -o %t/realdata.o34# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/takeaddr.s -o %t/takeaddr.o35# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/call.s -o %t/call.o36 37## The bare label alone assembles to a defined, size-0 DATA symbol (95803ba61);38## verify that has not regressed.39# RUN: llvm-objdump --syms %t/bare.o | FileCheck %s --check-prefix=BARE40# BARE: 00000000 g O DATA 00000000 m41 42## GREEN (both-defined): a size-0 DATA-def placeholder and a FUNCTION-def of the43## same name resolve to the FUNCTION definition, in either object order.44# RUN: wasm-ld -r -o %t/r1.o %t/bare.o %t/func.o45# RUN: llvm-objdump --syms %t/r1.o | FileCheck %s --check-prefix=FUNC46# RUN: wasm-ld -r -o %t/r2.o %t/func.o %t/bare.o47# RUN: llvm-objdump --syms %t/r2.o | FileCheck %s --check-prefix=FUNC48 49## GREEN (stub semantics): an undefined FUNCTION reference (a call) is satisfied50## by the size-0 DATA-def placeholder, in either object order -- as glibc's rtld51## map relies on (calls to the stubbed malloc/free resolve to the stub, not a52## real implementation). The link succeeds.53# RUN: wasm-ld -r -o %t/r5.o %t/bare.o %t/call.o54# RUN: wasm-ld -r -o %t/r6.o %t/call.o %t/bare.o55 56## GREEN (both-defined wins over a call): with a real FUNCTION def also present,57## the call binds to the FUNCTION, in any order.58# RUN: wasm-ld -r -o %t/r7.o %t/bare.o %t/call.o %t/func.o59# RUN: llvm-objdump --syms %t/r7.o | FileCheck %s --check-prefix=FUNC60 61## NEVER-SILENT: a genuine non-zero-size DATA object def vs a FUNCTION def of the62## same name still errors loudly, in either object order.63# RUN: not wasm-ld -r -o %t/r3.o %t/realdata.o %t/func.o 2>&1 | FileCheck %s --check-prefix=CONFLICT64# RUN: not wasm-ld -r -o %t/r4.o %t/func.o %t/realdata.o 2>&1 | FileCheck %s --check-prefix=CONFLICT65 66## NEVER-SILENT: a real (non-zero) DATA object cannot be *called* as a function67## either -- it still errors, in either object order.68# RUN: not wasm-ld -r -o %t/r8.o %t/realdata.o %t/call.o 2>&1 | FileCheck %s --check-prefix=CONFLICT69# RUN: not wasm-ld -r -o %t/r9.o %t/call.o %t/realdata.o 2>&1 | FileCheck %s --check-prefix=CONFLICT70 71## ADDRESSABILITY (no regression of 95803ba61 / completion via 30ef57c80): an72## object that takes &m -- where m resolves to the FUNCTION -- links, and the73## function-pointer reference is re-emitted as a table-index relocation.74# RUN: wasm-ld -r -o %t/ra.o %t/bare.o %t/func.o %t/takeaddr.o75# RUN: llvm-objdump -r %t/ra.o | FileCheck %s --check-prefix=ADDR76 77# FUNC: F {{.*}}m78# CONFLICT: error: symbol type mismatch: m79# ADDR: R_WASM_TABLE_INDEX_I32 m80 81#--- bare.s82## A bare label: no .functype, no .type, no .size, nothing following. MC83## (95803ba61) emits it as a size-0 DATA definition in a synthesized empty data84## segment.85.globl m86m:87 88#--- func.s89## A real FUNCTION definition of the same name.90.globl m91m:92 .functype m (i32) -> (i32)93 local.get 094 end_function95 96#--- realdata.s97## A genuine, non-zero-size DATA object definition of the same name -- a real98## type that must still conflict with the function definition / call.99.globl m100.section .data.m,"",@101m:102 .int32 0103.size m, 4104 105#--- takeaddr.s106## Takes the address of m (which resolves to the FUNCTION): a data relocation107## against a function symbol, re-emitted as a table-index relocation.108.globl p109.section .data.p,"",@110p:111 .int32 m112.size p, 4113 114#--- call.s115## Calls m as a function (an undefined FUNCTION reference). glibc's rtld objects116## call the stubbed malloc/free in exactly this way; the call must be satisfied117## by the placeholder definition without pulling a real implementation.118.functype m (i32) -> (i32)119.globl caller120caller:121 .functype caller () -> (i32)122 i32.const 0123 call m124 end_function125