Skip to content

[WebAssembly] non-pie dynamic-linking executable seems broken (LLVM 19 regression) #107387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
yamt opened this issue Sep 5, 2024 · 5 comments · Fixed by #108146 or #109249
Closed

[WebAssembly] non-pie dynamic-linking executable seems broken (LLVM 19 regression) #107387

yamt opened this issue Sep 5, 2024 · 5 comments · Fixed by #108146 or #109249
Labels

Comments

@yamt
Copy link
Contributor

yamt commented Sep 5, 2024

build the following test code as a non-pie dynamically-linked executable.
llvm 19 produces non-working binary.
llvm 18 worked fine.
you can find the full test code and compiler/linker options in https://github.com/yamt/garbage/tree/master/c/shlib_2

void f(void);
void (*f_p)(void) = f;

void
_start(void)
{
                f_p();
}
spacetanuki% toywasm --dyld main
Error: [trap] uninitialized element (8): call_indirect (null funcref) 0
current pc 0000fd
frame[  0] funcpc 0000e2 (main:_start)
2024-09-05 20:43:42 (1725536622.157386000): [10fb06600] instance_execute_func failed with -1
2024-09-05 20:43:42 (1725536622.157883000): [10fb06600] invoke failed with -1
spacetanuki% 

note that llvm 19's __wasm_apply_data_relocs is empty.

llvm 19.1.0-rc4

(module $main
  (type (;0;) (func))
  (import "env" "f" (func $f (type 0)))
  (func $__wasm_apply_data_relocs (type 0))
  (func $_start (type 0)
    global.get $GOT.data.internal.__memory_base
    i32.const 1024
    i32.add
    i32.load
    call_indirect (type 0))
  (table (;0;) 1 funcref)
  (memory (;0;) 2)
  (global $__stack_pointer (mut i32) (i32.const 66576))
  (global $GOT.data.internal.__memory_base i32 (i32.const 0))
  (global (;2;) i32 (i32.const 66576))
  (global (;3;) i32 (i32.const 131072))
  (export "memory" (memory 0))
  (export "__stack_pointer" (global $__stack_pointer))
  (export "__wasm_apply_data_relocs" (func $__wasm_apply_data_relocs))
  (export "_start" (func $_start))
  (export "__indirect_function_table" (table 0))
  (export "__heap_base" (global 2))
  (export "__heap_end" (global 3))
  (data $.data (i32.const 1024) "\00\00\00\00"))

llvm 18.1.2

(module $main
  (type (;0;) (func))
  (import "env" "f" (func $f (type 0)))
  (import "GOT.func" "f" (global $f (mut i32)))
  (func $__wasm_apply_data_relocs (type 0)
    i32.const 1024
    global.get $f
    i32.store)
  (func $_start (type 0)
    global.get $GOT.data.internal.__memory_base
    i32.const 1024
    i32.add
    i32.load
    call_indirect (type 0))
  (table (;0;) 1 funcref)
  (memory (;0;) 2)
  (global $__stack_pointer (mut i32) (i32.const 66576))
  (global $GOT.data.internal.__memory_base i32 (i32.const 0))
  (global (;3;) i32 (i32.const 66576))
  (global (;4;) i32 (i32.const 131072))
  (export "memory" (memory 0))
  (export "__stack_pointer" (global $__stack_pointer))
  (export "__wasm_apply_data_relocs" (func $__wasm_apply_data_relocs))
  (export "_start" (func $_start))
  (export "__indirect_function_table" (table 0))
  (export "__heap_base" (global 3))
  (export "__heap_end" (global 4))
  (data $.data (i32.const 1024) "\00\00\00\00"))
@yamt
Copy link
Contributor Author

yamt commented Sep 5, 2024

i did a bisection.
this has been broken since 22b7b84.
@sbc100 any idea?

@llvmbot
Copy link
Member

llvmbot commented Sep 5, 2024

@llvm/issue-subscribers-lld-wasm

Author: YAMAMOTO Takashi (yamt)

build the following test code as a non-pie dynamically-linked executable. llvm 19 produces non-working binary. llvm 18 worked fine. you can find the full test code and compiler/linker options in https://github.com/yamt/garbage/tree/master/c/shlib_2
void f(void);
void (*f_p)(void) = f;

void
_start(void)
{
                f_p();
}
spacetanuki% toywasm --dyld main
Error: [trap] uninitialized element (8): call_indirect (null funcref) 0
current pc 0000fd
frame[  0] funcpc 0000e2 (main:_start)
2024-09-05 20:43:42 (1725536622.157386000): [10fb06600] instance_execute_func failed with -1
2024-09-05 20:43:42 (1725536622.157883000): [10fb06600] invoke failed with -1
spacetanuki% 

note that llvm 19's __wasm_apply_data_relocs is empty.

llvm 19.1.0-rc4

(module $main
  (type (;0;) (func))
  (import "env" "f" (func $f (type 0)))
  (func $__wasm_apply_data_relocs (type 0))
  (func $_start (type 0)
    global.get $GOT.data.internal.__memory_base
    i32.const 1024
    i32.add
    i32.load
    call_indirect (type 0))
  (table (;0;) 1 funcref)
  (memory (;0;) 2)
  (global $__stack_pointer (mut i32) (i32.const 66576))
  (global $GOT.data.internal.__memory_base i32 (i32.const 0))
  (global (;2;) i32 (i32.const 66576))
  (global (;3;) i32 (i32.const 131072))
  (export "memory" (memory 0))
  (export "__stack_pointer" (global $__stack_pointer))
  (export "__wasm_apply_data_relocs" (func $__wasm_apply_data_relocs))
  (export "_start" (func $_start))
  (export "__indirect_function_table" (table 0))
  (export "__heap_base" (global 2))
  (export "__heap_end" (global 3))
  (data $.data (i32.const 1024) "\00\00\00\00"))

llvm 18.1.2

(module $main
  (type (;0;) (func))
  (import "env" "f" (func $f (type 0)))
  (import "GOT.func" "f" (global $f (mut i32)))
  (func $__wasm_apply_data_relocs (type 0)
    i32.const 1024
    global.get $f
    i32.store)
  (func $_start (type 0)
    global.get $GOT.data.internal.__memory_base
    i32.const 1024
    i32.add
    i32.load
    call_indirect (type 0))
  (table (;0;) 1 funcref)
  (memory (;0;) 2)
  (global $__stack_pointer (mut i32) (i32.const 66576))
  (global $GOT.data.internal.__memory_base i32 (i32.const 0))
  (global (;3;) i32 (i32.const 66576))
  (global (;4;) i32 (i32.const 131072))
  (export "memory" (memory 0))
  (export "__stack_pointer" (global $__stack_pointer))
  (export "__wasm_apply_data_relocs" (func $__wasm_apply_data_relocs))
  (export "_start" (func $_start))
  (export "__indirect_function_table" (table 0))
  (export "__heap_base" (global 3))
  (export "__heap_end" (global 4))
  (data $.data (i32.const 1024) "\00\00\00\00"))

@sbc100
Copy link
Collaborator

sbc100 commented Sep 5, 2024

I wasn't aware that non-PIE dynamic executables were something that was working. I had hoped to get it working since emscripten could benefit from this I think, but its not something that emscripten currently uses, which is the biggest user of dynamic linking today (IIUC). So I guess I'm not surprised that this use case broke, but we should certainly fix it, and improve the tests in this area.

yamt added a commit to yamt/llvm-project that referenced this issue Sep 12, 2024
yamt added a commit to yamt/llvm-project that referenced this issue Sep 19, 2024
… phase

Instead of always generating __wasm_apply_data_relocs when
relevant options like -pie and -shared are specified,
generate it only when the relevant relocations are actually
necessary.

Note: omitting empty __wasm_apply_data_relocs is not a problem
because the export is optional in the spec (DynamicLinking.md)
and all runtime linker implementations I'm aware of implement
it that way.  (emscripten, toywasm, wasm-tools)

Motivations:

* This possibly reduces the module size

* This is also a preparation to fix
  llvm#107387,
  for which it isn't obvious if we need these relocations at the
  time of createSyntheticSymbols. (unless we introduce a new explicit
  option like --non-pie-dynamic-link.)
yamt added a commit to yamt/llvm-project that referenced this issue Sep 20, 2024
…ction

Instead of always generating __wasm_apply_data_relocs when
relevant options like -pie and -shared are specified,
generate it only when the relevant relocations are actually
necessary.

Note: omitting empty __wasm_apply_data_relocs is not a problem
because the export is optional in the spec (DynamicLinking.md)
and all runtime linker implementations I'm aware of implement
it that way.  (emscripten, toywasm, wasm-tools)

Motivations:

* This possibly reduces the module size

* This is also a preparation to fix
  llvm#107387,
  for which it isn't obvious if we need these relocations at the
  time of createSyntheticSymbols. (unless we introduce a new explicit
  option like --non-pie-dynamic-link.)
@yamt
Copy link
Contributor Author

yamt commented Oct 1, 2024

this has not been fixed yet. can you reopen?

@sbc100 sbc100 reopened this Oct 1, 2024
yamt added a commit to yamt/llvm-project that referenced this issue Oct 1, 2024
The commit 22b7b84
made the symbols provided by shared libraries "defined",
and thus effectively made it impossible to generate non-pie
dynamically linked executables using --unresolved-symbols=import-dynamic.

This commit, based on llvm#109249,
fixes it by checking sym->isShared() explictly.
(as a bonus, you don't need to rely on --unresolved-symbols=import-dynamic
anymore.)

Fixes llvm#107387
puja2196 pushed a commit to puja2196/LLVM-tutorial that referenced this issue Oct 2, 2024
…tion (#109249)

Instead of always generating __wasm_apply_data_relocs when relevant
options like -pie and -shared are specified, generate it only when the
relevant relocations are actually necessary.

Note: omitting empty __wasm_apply_data_relocs is not a problem because
the export is optional in the spec (DynamicLinking.md) and all runtime
linker implementations I'm aware of implement it that way. (emscripten,
toywasm, wasm-tools)

Motivations:

* This possibly reduces the module size

* This is also a preparation to fix
llvm/llvm-project#107387, for which it isn't
obvious if we need these relocations at the time of
createSyntheticSymbols. (unless we introduce a new explicit option like
--non-pie-dynamic-link.)
Sterling-Augustine pushed a commit to Sterling-Augustine/llvm-project that referenced this issue Oct 3, 2024
…tion (llvm#109249)

Instead of always generating __wasm_apply_data_relocs when relevant
options like -pie and -shared are specified, generate it only when the
relevant relocations are actually necessary.

Note: omitting empty __wasm_apply_data_relocs is not a problem because
the export is optional in the spec (DynamicLinking.md) and all runtime
linker implementations I'm aware of implement it that way. (emscripten,
toywasm, wasm-tools)

Motivations:

* This possibly reduces the module size

* This is also a preparation to fix
llvm#107387, for which it isn't
obvious if we need these relocations at the time of
createSyntheticSymbols. (unless we introduce a new explicit option like
--non-pie-dynamic-link.)
@topperc topperc closed this as completed Oct 30, 2024
@yamt
Copy link
Contributor Author

yamt commented Oct 31, 2024

@topperc this has not been fixed yet. can you reopen?
a proposed fix is #108146

sbc100 pushed a commit that referenced this issue Jan 3, 2025
The commit 22b7b84
made the symbols provided by shared libraries "defined",
and thus effectively made it impossible to generate non-pie
dynamically linked executables using
--unresolved-symbols=import-dynamic.

This commit, based on #109249,
fixes it by checking sym->isShared() explictly.
(as a bonus, you don't need to rely on
--unresolved-symbols=import-dynamic
anymore.)

Fixes #107387
github-actions bot pushed a commit to arm/arm-toolchain that referenced this issue Jan 10, 2025
…(#108146)

The commit 22b7b84
made the symbols provided by shared libraries "defined",
and thus effectively made it impossible to generate non-pie
dynamically linked executables using
--unresolved-symbols=import-dynamic.

This commit, based on llvm/llvm-project#109249,
fixes it by checking sym->isShared() explictly.
(as a bonus, you don't need to rely on
--unresolved-symbols=import-dynamic
anymore.)

Fixes llvm/llvm-project#107387
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants