Hi Alex, Hi Jeff, Hi Richard, Consider the following small test case:
% cat test1.c extern int g (void) __attribute__ ((visibility("protected"))); int f (void) { return g (); } % cat test2.c extern int g(void) __attribute__ ((visibility("protected"))); int i; int g (void) { return i; } % gcc -fPIC -c test1.c test2.c % gcc -shared -o libtest_protected.so test1.o test2.o When compiled with a MN10300 toolchain based on the current FSF GCC and binutils sources the final link will fail with: test1.o: In function `f': test1.c:(.text+0x7): warning: error: inappropriate relocation type for shared library (did you forget -fpic?) The problem here is that GCC has decided that since "g" is protected it does not need a PLT entry. But the linker has decided that since "g" is a function it does need a PLT entry (even though it is protected) so that function pointer comparison will work. (See the definition of SYMBOL_REFERENCES_LOCAL in bfd/elf-bfd.h for more information on this). I have a small patch that fixes this problem (see below), but I am not sure if this is the correct solution. As far as I can see, this is not an MN10300 specific problem however, so surely other targets ought to have similar problems ? (But other targets do not seem to use targetm.binds_local_p to decide if a symbol is global or local. cf/ mn10300_encode_section_info). Anyway any advice or comments on the situation would be appreciated. Cheers Nick Index: gcc/config/mn10300/mn10300.c =================================================================== --- gcc/config/mn10300/mn10300.c (revision 174069) +++ gcc/config/mn10300/mn10300.c (working copy) @@ -3315,8 +3315,30 @@ } } +static bool +mn10300_binds_local (const_tree exp) +{ + bool local = default_binds_local_p (exp); + + /* The default binds_local function will decide that protected functions + bind locally. Whilst technically this is true, in practice in PIC mode + protected functions still need a PLT entry so that function pointer + comparison will work. */ + if (local + && flag_pic + && DECL_P (exp) + && TREE_CODE (exp) == FUNCTION_DECL + && DECL_VISIBILITY (exp) == VISIBILITY_PROTECTED) + return false; + + return local; +} + /* Initialize the GCC target structure. */ +#undef TARGET_BINDS_LOCAL_P +#define TARGET_BINDS_LOCAL_P mn10300_binds_local + #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG mn10300_reorg