Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC -flto changing symbol visibility

I have a large piece of code, which produces errors when compiled using -flto only on some versions of gcc. I will try to summarise below

in file1.h

extern char A [100];

in file1.c

#include "file1.h"
char A[100];

I also have some c++ code that uses the variable A. The C++ code is compiled to an .o file, and then the whole thing is compiled with something like

gcc file1.c cpp.o

Using the version of gcc on archlinux (5.2.0), there is no problem both with and without -flto. However using gcc on Ubuntu 14.04 (4.8.4), when the code is compiled with -flto, A becomes a local variable. I have verified this with nm:

These are the output from nm a.out for the variable in question

Ubuntu, no lto (arch similar, with a different number):

00000000006162e0 B A

Ubuntu, lto

00000000006092c0 b A.2722

My understanding is that the B is for a global variable, and b is not.

How can I ensure that A is maintained as a global variable even when I use -flto on Ubuntu?

like image 760
John Palmer Avatar asked Oct 30 '22 22:10

John Palmer


1 Answers

Looking at this and this, it most certainly appears to be a bug within the particular version of gcc that you are using (gcc 4.8.4 comes bundled with Ubuntu 14.04).

Using the code snippets from the question,
i was able to reproduce the behaviour on my machine running Ubuntu 14.04.

A simple workaround for this is to explicitly mark the symbol in question as used.

file1.c has char A[100];

file2.c has __attribute__((used)) char A[100];

gcc file1.c -o file1-default.o
nm file1-default.o | grep "A$"
0000000000601060 B A               <-- symbol is a global.

gcc file1.c -flto -o file1-flto.o
nm file1-flto.o | grep "A$"
0000000000601060 b A.2385          <-- symbol updated to a local.

gcc file2.c -flto -o file2.o
nm file2.o | grep "A$"
0000000000601060 B A               <-- symbol retained as global.
like image 81
TheCodeArtist Avatar answered Nov 15 '22 04:11

TheCodeArtist