public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* gcc-nm behavior with -flto
@ 2020-02-04 20:58 Arvind Sankar
  2020-02-05  2:43 ` Xi Ruoyao
  2020-02-05 19:40 ` Arvind Sankar
  0 siblings, 2 replies; 3+ messages in thread
From: Arvind Sankar @ 2020-02-04 20:58 UTC (permalink / raw)
  To: gcc-help; +Cc: binutils

Hi, I get some odd symbol types when using gcc-nm on an lto file.

Given the source file
	void text(void) {}
	int data = 1;
	int bss = 0;
	int common;

gcc -c test.c && gcc-nm test.o:
0000000000000000 B bss
0000000000000004 C common
0000000000000000 D data
0000000000000000 T text

gcc -flto -c test.c && gcc-nm test.o:
00000000 T bss
00000000 C common
00000000 T data
00000000 T text

gcc -flto -fno-common -c test.c && gcc-nm test.o:
00000000 T bss
00000000 T common
00000000 T data
00000000 T text

i.e. with LTO, .bss and .data symbols are shown as text symbols instead
by gcc-nm. This causes issues with configure scripts that use libtool
when the CFLAGS contain both -flto and -fno-common. There's a section in
the configure script that tries to figure out how to parse nm's output.
It compiles a source file that contains a common symbol and a function,
then parses nm output to create a second .c file with those
declarations, and tries to check that everything is working by linking
them together. In the -flto -fno-common case, the second file ends up
with both symbols turning into functions which then gives a link-time
error.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: gcc-nm behavior with -flto
  2020-02-04 20:58 gcc-nm behavior with -flto Arvind Sankar
@ 2020-02-05  2:43 ` Xi Ruoyao
  2020-02-05 19:40 ` Arvind Sankar
  1 sibling, 0 replies; 3+ messages in thread
From: Xi Ruoyao @ 2020-02-05  2:43 UTC (permalink / raw)
  To: Arvind Sankar, gcc-help; +Cc: binutils

On 2020-02-04 15:58 -0500, Arvind Sankar wrote:
> Hi, I get some odd symbol types when using gcc-nm on an lto file.
> 
> Given the source file
> 	void text(void) {}
> 	int data = 1;
> 	int bss = 0;
> 	int common;
> 
> gcc -c test.c && gcc-nm test.o:
> 0000000000000000 B bss
> 0000000000000004 C common
> 0000000000000000 D data
> 0000000000000000 T text
> 
> gcc -flto -c test.c && gcc-nm test.o:
> 00000000 T bss
> 00000000 C common
> 00000000 T data
> 00000000 T text
> 
> gcc -flto -fno-common -c test.c && gcc-nm test.o:
> 00000000 T bss
> 00000000 T common
> 00000000 T data
> 00000000 T text
> 
> i.e. with LTO, .bss and .data symbols are shown as text symbols instead
> by gcc-nm. This causes issues with configure scripts that use libtool
> when the CFLAGS contain both -flto and -fno-common. There's a section in
> the configure script that tries to figure out how to parse nm's output.
> It compiles a source file that contains a common symbol and a function,
> then parses nm output to create a second .c file with those
> declarations, and tries to check that everything is working by linking
> them together. In the -flto -fno-common case, the second file ends up
> with both symbols turning into functions which then gives a link-time
> error.

I can't reproduce this.

$ cat test1.c
void text(void) {}
int data = 1;
int bss = 0;
int common;
$ cat test2.c
#include <assert.h>

extern void text(void);
extern int data;
extern int bss;
extern int common;

int main()
{
	assert(bss == 0 && data == 1);
	return 0;
}
$ cc test1.c test2.c -flto -fno-common
$ ./a.out 
$

Did you forgot the "extern" in test2.c for "int common;"?  "int common;" is a
tentative definition, equivalent to "int common = 0;", in ANSI C.  "-fcommon" is
a workaround enabled by default to resolve same tentative definitions in
multiple files.  With "-fno-common" there is no such a workaround so the linker
will complain.
-- 
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: gcc-nm behavior with -flto
  2020-02-04 20:58 gcc-nm behavior with -flto Arvind Sankar
  2020-02-05  2:43 ` Xi Ruoyao
@ 2020-02-05 19:40 ` Arvind Sankar
  1 sibling, 0 replies; 3+ messages in thread
From: Arvind Sankar @ 2020-02-05 19:40 UTC (permalink / raw)
  To: gcc-help, xry111; +Cc: binutils

On 2020-02-05 10:42 +0800, Xi Ruoyao wrote:
> I can't reproduce this.
> 
> $ cat test1.c
> void text(void) {}
> int data = 1;
> int bss = 0;
> int common;
> $ cat test2.c
> #include <assert.h>
> 
> extern void text(void);
> extern int data;
> extern int bss;
> extern int common;
> 
> int main()
> {
> 	assert(bss == 0 && data == 1);
> 	return 0;
> }
> $ cc test1.c test2.c -flto -fno-common
> $ ./a.out
> $
> 
> Did you forgot the "extern" in test2.c for "int common;"?  "int common;" is a
> tentative definition, equivalent to "int common = 0;", in ANSI C.  "-fcommon" is
> a workaround enabled by default to resolve same tentative definitions in
> multiple files.  With "-fno-common" there is no such a workaround so the linker
> will complain.

Hi Xi, no, that's not the issue. The actual files as used in configure
are shown below. Because of nm showing the variable as a "T" symbol,
conftest.c got generated with a function declaration for nm_test_var,
instead of the expected variable declaration.

This causes the configure test to fail with
conftest.cpp:6:12: error: variable 'nm_test_var' redeclared as function

Without -fno-common, nm_test_var shows up as a "C" symbol, so it gets it
right for the configure test, but it would be wrong if/when it's actually
used for .bss or .data symbols.

I found that there is a bugzilla entry for this
https://sourceware.org/bugzilla/show_bug.cgi?id=25355 already.

I also got to wondering why this doesn't break gcc-10 LTO bootstrap,
which also uses libtool, and it turns out its because
lt__PROGRAM_LTX_preloaded_symbols[] is declared as a file-scope
constant, which in C++ defaults to static linkage. We use xg++ as the
compiler for the configure test, and at -O1 and above, conftest.c gets
optimized into nothing (i.e. no symbol references remain) and so the
error doesn't trigger.

conftest.c:

	#ifdef __cplusplus
	extern "C" {
	#endif

	extern int nm_test_func();
	extern int nm_test_var(); /* This is incorrectly a function declaration */

	/* The mapping between symbol names and symbols.  */
	const struct {
	  const char *name;
	  void       *address;
	}
	lt__PROGRAM__LTX_preloaded_symbols[] =
	{
	  { "@PROGRAM@", (void *) 0 },
	  {"nm_test_func", (void *) &nm_test_func},
	  {"nm_test_var", (void *) &nm_test_var},
	  {0, (void *) 0}
	};

	/* This works around a problem in FreeBSD linker */
	#ifdef FREEBSD_WORKAROUND
	static const void *lt_preloaded_setup() {
	  return lt__PROGRAM__LTX_preloaded_symbols;
	}
	#endif

	#ifdef __cplusplus
	}
	#endif

conftstm.c:

	#ifdef __cplusplus
	extern "C" {
	#endif
	char nm_test_var;
	void nm_test_func(void);
	void nm_test_func(void){}
	#ifdef __cplusplus
	}
	#endif
	int main(){nm_test_var='a';nm_test_func();return(0);}

PS: I didn't receive your e-mail but saw it on gcc-help archive. Not
sure why.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-02-05 19:40 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-04 20:58 gcc-nm behavior with -flto Arvind Sankar
2020-02-05  2:43 ` Xi Ruoyao
2020-02-05 19:40 ` Arvind Sankar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).