If we use '.set' directive to set a symbol as an alias of an IFunc, then the
symbol should also be IFunc. But it's evaluated to be the IFunc resolver at
this time. This patch tries to fix it.
Details
Diff Detail
Event Timeline
Suppose we have foo.s as follows:
.text .p2align 3 .globl foo_impl .type foo_impl,@function foo_impl: ret .globl foo_resolver .type foo_resolver,@function foo_resolver: mov $foo_impl, %rax ret .globl foo .type foo,@gnu_indirect_function .set foo,foo_resolver .globl foo2 .set foo2,foo
and assemble foo.s with GNU as, and check foo.o with nm:
$ as foo.s -o foo.o $ nm foo.o 0000000000000006 i foo 0000000000000006 i foo2 <- foo2 is an ifunc identical to foo 0000000000000000 T foo_impl 0000000000000006 T foo_resolver
and the 'foo2' is also an ifunc whose resolver is foo_resolver.
However, when assemble with llvm-mc, the 'foo2' becomes normal a function identical to 'foo_resolver':
$ llvm-mc foo.s -filetype obj -o foo.o $ nm foo.o 0000000000000006 i foo 0000000000000006 T foo2 <- foo2 is a strong symbol identical to foo_resolver 0000000000000000 T foo_impl 0000000000000006 T foo_resolver
The reason is as follows:
When we 'getBaseSymbol' from 'ELFwriter::writeSymbol' in lib/MC/ELFObjectWriter.cpp, it recursively evaluates the 'Value' of the 'Symbol', and the two direcives -- '.set foo,foo_resolver' and '.set foo2,foo' -- make foo2 is evaluated as 'foo_resolver', and the 'Type' we get below becomes function, while it should be ifunc.
llvm/lib/MC/ELFObjectWriter.cpp | ||
---|---|---|
539 | GNU as doesn't check the type of the alias .type foo2, @function .set foo2,foo # foo2 is a STT_GNU_IFUNC | |
llvm/test/MC/ELF/ifunc-alias.s | ||
4 | .globl directives and instructions are not significant. You can simplify the test: .type foo_resolver,@function foo_resolver: .type foo,@gnu_indirect_function .set foo,foo_resolver .set foo2,foo .set foo3,foo2 # add another alias to show it is necessary to resolve it recursively |
llvm/lib/MC/ELFObjectWriter.cpp | ||
---|---|---|
539 | I'm sorry, but do you mean that I need to remove the '.type' directive in the test or that the IFunc check I do here is wrong? :D |
llvm/lib/MC/ELFObjectWriter.cpp | ||
---|---|---|
514 | If you make the parameter a pointer, SymbolPtr can be deleted. |
With pleasure:) Sigh, I don't like this GNU extension but I have to learn more and more about it. Last time I committed a -z ifunc-noplt linker change for FreeBSD devs...
If you make the parameter a pointer, SymbolPtr can be deleted.