On 2019-12-18 14:19 +0100, Jan Hubicka wrote: > > ICE here. > > > > lto1: internal compiler error: tree check: expected identifier_node, have > > function_decl in ultimate_transparent_alias_target, at varasm.c:1308 > > 0x6f9cfe tree_check_failed(tree_node const*, char const*, int, char const*, > > ...) > > ../../gcc/gcc/tree.c:9685 > > 0x714541 tree_check(tree_node*, char const*, int, char const*, tree_code) > > ../../gcc/gcc/tree.h:3273 > > 0x714541 ultimate_transparent_alias_target > > ../../gcc/gcc/varasm.c:1308 > > 0x714541 do_assemble_symver(tree_node*, tree_node*) > > ../../gcc/gcc/varasm.c:5971 > > Interesting that it works for me, but indeed we can remove that call > since there is no way to do weakref of symbol version. > > > #ifdef ASM_OUTPUT_SYMVER_DIRECTIVE > > > - ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file, > > > - IDENTIFIER_POINTER (target), > > > - IDENTIFIER_POINTER (id)); > > > + if (TREE_PUBLIC (target) && DECL_VISIBILITY (target) == > > > VISIBILITY_DEFAULT) > > > + ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file, > > > + IDENTIFIER_POINTER > > > + (DECL_ASSEMBLER_NAME (target)), > > > + IDENTIFIER_POINTER (id)); > > > + else > > > + { > > > + int nameend; > > > + for (nameend = 0; IDENTIFIER_POINTER (id)[nameend] != '@'; > > > nameend++) > > > + ; > > > + if (IDENTIFIER_POINTER (id)[nameend + 1] != '@' > > > + || IDENTIFIER_POINTER (id)[nameend + 2] == '@') > > > + { > > > + sorry_at (DECL_SOURCE_LOCATION (target), > > > + "can not produce %<symver%> of a symbol that is " > > > + "not exported with default visibility"); > > > + return; > > > > I think this does not make sense. Some library authors may export "foo@VER_ > > 1" > > but not "foo_v1" to ensure the programmers using the library upgrade their > > code > > to use new "correct" ABI, instead of an old one. This error makes it > > impossible. > > > > (Try to comment out "foo_v1" in version.map, in the testcase.) > > The problem here is that we lie to the compiler (by pretending that > foo_v2 is exported from DSO while it is not) and force user to do the > same. > > We support two ways to hide symbol - either at compile time via > attribute((visibility("hidden"))) or at link-time via map file. The > first produces better code because compiler can do more optimizations > knowing that the symbol can not be interposed. > > Generally we want users to use visiblity attribute or -fvisibility since > it leads to better code. However now we tell users to use > attribute((symver("..."))) to produce symbol version, but at the same > time not use attribute((visibility("hidden"))).
Could a symver symbol be interposed? I'll do some test to see. > > > + memcpy (buf, IDENTIFIER_POINTER (id), nameend + 2); > > > + buf[nameend + 2] = '@'; > > > + strcpy (buf + nameend + 3, IDENTIFIER_POINTER (id) + nameend + 2); > > > > We can't replace a single "@" with "@@@". So I think producing .LSYMVERx is > > not > > an option for "old" versions like "foo@VER_1". > > I wonder why gas implements the .symver this way at first place. Does > the linker really need the global symbol foo_v1 to produce the > version (in addition to foo@VER_1 that is in symbol table as well)? I don't think the global symbol foo_v1 is necessary. But I can't find a way telling gas to make foo@VER_1 global and foo_v1 local. > > > + /* Symbol versions are always used externally, but linker does not > > > + report that correctly. */ > > > + else if (snode->symver && *res == LDPR_PREVAILING_DEF_IRONLY) > > > + snode->resolution = LDPR_PREVAILING_DEF_IRONLY_EXP; > > > > This is absolutely correct. > > Good, I will go ahead with filling in binutils PR on the wrong LDPR > value and apply the hack. > > > else > > > snode->resolution = *res; > > > } > > > > I still believe we should consider symver targets to be externally visible > > in > > cgraph_externally_visible_p. There is a comment saying "if linker counts on > > us, > > we must preserve the function". That's true in our case. > > > > And, I think > > > > .globl .LSYMVER0 > > .set .LSYMVER0, foo_v2 > > .symver .LSYMVER0, foo@@VERS_2 > I produce > .symver .LSYMVER0, foo@@@VERS_2 > > > is exactly same as > > > > .globl foo_v2 > > .symver foo_v2, foo@@VERS_2 > > > > except there is an unnecessary ".LSYMVER0". Adding ".globl foo_v2" or > > ".globl > > foo_v1" won't cause them to be "global" in the final DSO because the linker > > will > > hide them according to the version script. > > The difference is that in first case compiler can fully control foo_v2 > symbol (with LTO it will turn it into static symbol, it will inline > calls to it and do other things), while in the second case we need to > treat foo_v2 specially. > > So if it's safe we can force a ".globl foo_v2" before ".symver foo_v2, > > foo@@VERS_2". But I can't prove it's safe so I think it's better to > > consider > > this case in cgraph_externally_visible_p. > > It sort of makes things work, but for example it will prevent gcc from > inlining calls to foo_v2. I think we will still need to do something > about -fvisibility=hidden. > > It is sad that we do not have way to produce symbol version without a > corresponding symbol of global visiblity. If we had we could support > multiple symver aliases from one symbol and avoid the need to explicitly > hide the unnecesary symbols in the map files... Explicitly hiding the unnecessary symbols in map files is now how we handle this [with __asm__(".symver foo_v2, foo@@VERS_2")]. We can continue to do in this way and leave it as an enhancement. -- Xi Ruoyao <xry...@mengyan1223.wang> School of Aerospace Science and Technology, Xidian University