[lld 11.0.0] ppc64 branch-to-fd

Hello,

[clang/lld version 11.0.0, built on 1Apr20 using source
downloaded from github.]

When compiling for ppc64 big-endian target, a branch-with-link
targets the function descriptor instead of the function entry.

Below is a sample:

/*1.c*/
int main();
int _start(){return main();}

/*2.c*/
int g_var=20;
int main(){return g_var;}

/* build */
clang -target ppc64 -O3 -c 1.c
clang -target ppc64 -O3 -c 2.c
ld.lld 1.o 2.o

The dissassembly shows that _start branches to the
FD(0x...230) instead of to the entry point (0x...1f8):

00000000100101c8 <.text>:
. . .
100101d4: 48 02 00 5d bl 0x10030230; <-- bl to FD?
. . .
100101f8: 3c 62 00 01 addis 3, 2, 1 <-- main entry pt.
100101fc: e8 63 80 3a lwa 3, -32712(3)
10010200: 4e 80 00 20 blr

SYMBOL TABLE:
0000000010030230 g F .opd 0000000000000018 main

FD of main:
00000230: 00 00 00 00 10 01 01 f8 00 00 00 00 10 02 82 10
00000240: 00 00 00 00 00 00 00 00

The compiler emits a relocation within the object 1.o:
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
000000000000000c R_PPC64_REL24 main

The relevant code seems to be the function
PPC64::relocate inside lld/ELF/Arch/PPC64.cpp
when it receives R_PPC64_REL24 as rel (with
val 0x2005c in this particular case).

GNU ld for ppc64 emits a correct bl instruction.

Is this a bug with lld, or did I simply miss giving
it a switch on its commandline?

Thank you,
amol

Missed adding the dev-list in the reply so resending.

I believe the bug is that Clang should be setting the e_flags field in the ELF header to 1 when producing an object file which uses the function-descriptor based ABI. LLD only supports the V2 ELF ABI for PowerPC64, which doesn’t use function descriptors. LLD will accept object files with e_flags equal to 2 (V2 ABI specific) or 0 (unspecified nature),and without the correct flags LLD unfortunately can’t detect the invalid input.

Regards
Sean

Thank you!

I did not know that lld does not support v1 abi.

Manually setting e_flags to 1, inside the ELF headers of
the object files, now allows lld to show the error:

ld.lld 1.o 2.o
ld.lld: error: 1.o: ABI version 1 is not supported
ld.lld: error: 2.o: ABI version 1 is not supported

-amol