llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.4k stars 11.73k forks source link

assignments made before SECTIONS do not reflect final values after section parsing #42335

Closed kees closed 5 years ago

kees commented 5 years ago
Bugzilla Link 42990
Resolution FIXED
Resolved on Aug 26, 2019 10:01
Version unspecified
OS Linux
CC @MaskRay,@nickdesaulniers,@smithp35

Extended Description

The following poc.lds links differently between bfd and lld:

efistubend = _end; SECTIONS { . = 0xffff; . += ((_end >> 8) - 0xff ); _end = .; }

Linking with an empty .o file:

$ ld.lld -maarch64elf -shared -o vmlinux.lld -T poc.lds /tmp/test.o && readelf -Ws vmlinux.lld | egrep '\b(init_pg_size|(efistub_|)_end)\b' 2: 000000000000ffff 0 NOTYPE GLOBAL DEFAULT 1 _end 3: 000000000000ff00 0 NOTYPE GLOBAL DEFAULT 1 efistubend

i.e. efistubend is calculated before _end is known. Moving the efistubend assignment to after the SECTIONS {} works around this bug.

bfd produces the same results with either ordering:

$ aarch64-linux-gnu-ld.bfd -maarch64elf -shared -o vmlinux.bfd -T poc.lds /tmp/test.o && readelf -Ws vmlinux.bfd | egrep '\b(init_pg_size|(efistub_|)_end)\b' 2: 000000000000ffff 0 NOTYPE GLOBAL DEFAULT 1 _end 4: 000000000000ffff 0 NOTYPE GLOBAL DEFAULT ABS efistubend

nickdesaulniers commented 5 years ago

Fixed in https://reviews.llvm.org/rL369889.

MaskRay commented 5 years ago

Proposed patch: https://reviews.llvm.org/D66279

smithp35 commented 5 years ago

In this case, and I think llvm/llvm-project#41851 which is strongly related, LLD is evaluating the expression of symbol assignment too eagerly. In effect at the time efistubend = _end; is read in, it will be evaluated, losing any later changes made to the value of _end.

The best that I can find in the documentation about what is supposed to happen is: https://sourceware.org/binutils/docs/ld/Evaluation.html#Evaluation but it isn't explicit about this case.

In BFD ldlang.c there is a late run of just the symbol assignments after Section sizes have been fixed lang_do_assignments (lang_final_phase_enum). This would mean that _end would have its final value.

I think LLD will need something like a late pass through just the symbol assignements to update aliases. Ideally we'd be able to make something that would solve the outstanding symbol definition differences in one go.

kees commented 5 years ago

Actually, llvm/llvm-project#41851 appears to be solved with the same workaround as here. (Though they still may be different bugs.)

kees commented 5 years ago

Also, FWIW, this bug appears to be distinct from these seemingly related issues:

llvm/llvm-project#40514

llvm/llvm-project#41851

kees commented 5 years ago

This is from https://github.com/ClangBuiltLinux/linux/issues/634