[Bug lto/107708] New: LTO causes gnu::constructor functions to not be called with correct arguments if there is more than one constructor
cfsteefel at arista dot com
gcc-bugzilla@gcc.gnu.org
Tue Nov 15 19:14:23 GMT 2022
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107708
Bug ID: 107708
Summary: LTO causes gnu::constructor functions to not be called
with correct arguments if there is more than one
constructor
Product: gcc
Version: 11.3.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: lto
Assignee: unassigned at gcc dot gnu.org
Reporter: cfsteefel at arista dot com
CC: marxin at gcc dot gnu.org
Target Milestone: ---
When a function is marked with the constructor attribute, if there is more than
one function marked with the constructor attribute, the function's arguments
are not passed when LTO inlines the function into DT_INIT_ARRAY. If LTO is
disabled, the function will instead be passed argc, argv, and envp by glibc
(other libc implementation may or may not pass anything).
See the following code:
#include <iostream>
namespace {
int c;
char ** a;
[[ gnu::constructor ]]
void foo( int argc, char ** argv ) {
a = argv;
c = argc;
}
[[ gnu::constructor ]]
void bar( int argc, char ** argv ) {
asm( "" );
}
}
int main() {
std::cerr << "argc: " << c << std::endl;
std::cerr << std::hex << a << std::endl;
return 0;
}
When compiled and run as:
> g++ text.cpp -g -shared -o libMain.so -fPIC -O2 -flto -Wall -Wextra
> g++ libMain.so
> LD_LIBRARY_PATH=. ./a.out 4 1 2 4
A sample output is:
argc: -638171435
0x7f20366efdd0
(the use of cerr is only meaningful for actually seeing output, and is not
needed to reproduce the error)
Using a specific and unique priority for the `gnu::constructor` attribute will
lead to the arguments being passed correctly, and argc will end up correct.
If the function is instead not defined inside an anonymous namespace, as just:
int c;
char ** a;
[[ gnu::constructor ]]
void foo( int argc, char ** argv ) {
a = argv;
c = argc;
}
g++ instead reports the error (using -Wall -Wextra):
In function '_sub_I_65535_0':
text.cpp:8:6: warning: 'argv' is used uninitialized [-Wuninitialized]
8 | a = argv;
| ^
lto1: note: 'argv' was declared here
text.cpp:9:6: warning: 'argc' is used uninitialized [-Wuninitialized]
9 | c = argc;
| ^
lto1: note: 'argc' was declared here
Using a unique constructor priority again will disable that warning.
g++ (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2)
glibc 2.34
More information about the Gcc-bugs
mailing list