On Thu, Mar 6, 2025 at 7:05 PM Nelson Chu <nel...@rivosinc.com> wrote:
>
> Committed, thanks.
>
> Nelson
>
> On Mon, Mar 3, 2025 at 11:51 AM Nelson Chu <nel...@rivosinc.com> wrote:
>>
>> Looks like we could give it a try and see if it works and won't affect 
>> current projects.  I will commit it before this weekend if there are no 
>> objections.
>>
>> Thanks
>> Nelson
>>
>> On Tue, Feb 11, 2025 at 1:53 AM Palmer Dabbelt <pal...@rivosinc.com> wrote:
>>>
>>> On Sat, 08 Feb 2025 00:33:37 PST (-0800), Nelson Chu wrote:
>>> > I got an request about the undefined behaviors, considering the following 
>>> > case,
>>> >
>>> > $ cat test.c
>>> > void main ()
>>> > {
>>> >   foo();
>>> > }
>>> > $ cat lib.h
>>> > void foo(void);
>>> > $ riscv64-unknown-linux-gnu-gcc test.c
>>> > riscv64-unknown-linux-gnu/bin/ld: /tmp/ccRO8fJl.o: in function `main':
>>> > test.c:(.text+0x8): undefined reference to `foo'
>>> > collect2: error: ld returned 1 exit status
>>> > $ riscv64-unknown-linux-gnu-gcc test.c 
>>> > -Wl,--unresolved-symbols=ignore-in-object-files
>>> > $ qemu-riscv64 a.out
>>> > Segmentation fault (core dumped)
>>> >
>>> > Testing with x86 and aarch64, they won't get the segfault since they go 
>>> > plt
>>> > for the undefined foo symbol.  So, after applying this patch, I can get 
>>> > the
>>> > following too,
>>> >
>>> > $ qemu-riscv64 a.out
>>> > a.out: symbol lookup error: a.out: undefined symbol: foo
>>> >
>>> > The change of this patch should only affect the call behavior, which refer
>>> > to an undefined (weak) symbol, when building an dynamic executable.  I 
>>> > think
>>> > the pic/pie behavior won't be affected as usual.  I am not sure if the 
>>> > change
>>> > will cause trouble or not for other projects, so please feels free to cc 
>>> > people
>>> > that you think they will be affected, thanks.
>>>
>>> Thanks for doing this.  For some more context, there's a handful of Go
>>> plugins that seem to want `-Wl,--export-dynamic
>>> -Wl,--unresolved-symbols=ignore-in-object-files` to result in
>>> executables that have PLT-indirect calls to these undefined symbols,
>>> which they'll then later LD_PRELOAD or dlopen() to resolve.  Here's an
>>> example
>>> <https://github.com/NVIDIA/nvidia-container-toolkit/blob/b19f5d8f7d76f8ec05534aadfc0c3641bd281d55/internal/dxcore/dxcore.go#L20>.
>>>
>>> IMO that's pretty far into the realm of undefined behavior, and from
>>> poking around a bit it looks like that's the case even on x86 --
>>> basically if my symbol gets linked before something has triggered a PLT
>>> to be created, then I end up with a direct reference that isn't
>>> dynamically resolvable.
>>>
>>> It also looks like arm64 generates NOPs (rather than calls to absolute
>>> 0) on these undefined symbols, so it's possible some instances of these
>>> are just crashing lazily.  THere might be some context floating around
>>> in 7cd2917227 ("aarch64: Return an error on conditional branch to an
>>> undefined symbol"), it's a bit hard to follow so I'm not sure if that's
>>> an intentional side-effect or just the easiest arbitrary thing to
>>> generate for this flavor of undefined behavior.
>>>
>>> So I'm kind of split on what we should do here: in general I like to
>>> have undefined behavior crash eagerly, as otherwise we're just making
>>> these issues harder to debug.  That said, this has blown up internally
>>> and making it crash lazily will make the fire go out, and it'd be really
>>> nice to start a Monday morning with more fires going out than
>>> starting...
>>>
>>> Maybe there's some more context floating around in someone's brain about
>>> this?
>>>
>>> > ---
>>> >  bfd/elfnn-riscv.c | 84 +++++++++++++++++++++++++----------------------
>>> >  1 file changed, 44 insertions(+), 40 deletions(-)

I am intrigued by the problem but I have trouble understanding the
description. What behavior does this patch change?

> riscv64-unknown-linux-gnu-gcc test.c 
> -Wl,--unresolved-symbols=ignore-in-object-files

There is no -nostdlib, therefore I assume that this command creates a
dynamically linked executable (both -fpie -pie and -fno-pie -no-pie
are possible, depending on how users configure the GCC).

I've tested a few cases but do not observe a behavior difference (in
terms of whether `foo` is in .dynsym and whether there is a JUMP_SLOT
relocation).

ld-new --unresolved-symbols=ignore-in-object-files -o a a.o b.so
ld-new --unresolved-symbols=ignore-in-object-files -o a a.o

(lld has a quite simple model where undefined non-weak and undefined
weak symbols are handled in a unified way.
A symbol is preemptible if:

* -shared or at least one input file is DSO, and
* the symbol is undefined or exported (to .dynsym due to
--export-dynamic/--dynamic-list/referenced by DSO/etc), and
* other conditions that the symbol is preemptible

Then, a preemptible symbol might need a PLT and associated JUMP_SLOT
relocation.)
)

Reply via email to