public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Multiple symbols defined in object files that should not be there.
@ 2023-04-06  4:03 Steve Thompson
  2023-04-06  9:08 ` Jonathan Wakely
  0 siblings, 1 reply; 3+ messages in thread
From: Steve Thompson @ 2023-04-06  4:03 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 5588 bytes --]

I have a perplexing problem in compiling source files:

make[1]: Leaving directory '/home/stevet/stuff/src/projects/olock-beta/arch'
ar cr libolock.a anon_pages.o aobm.o apool.o asm_ops.o bool.o debugging.o
microsecond_time.o nanosecond_time.o obm.o olock.o os_linux.o platform.o
posix_mmap.o posix_threads.o statistics.o
ranlib libolock.a
make -C test
make[1]: Entering directory
'/home/stevet/stuff/src/projects/olock-beta/test'
gcc10.4  -D _DEFAULT_SOURCE -DARCH_64 -DOLOCK_192 -DLINUX -I./ -I../
-pthread -m64 -std=c99 -Wall -Wextra -Werror -fdiagnostics-color=never -O
-ggdb  -DUSE_OBM -o otest otest.c ../libolock.a
/usr/bin/ld: ../libolock.a(debugging.o): in function `apool_init_freelist':
/home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
definition of `apool_init_freelist';
/tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
first defined here
/usr/bin/ld: ../libolock.a(olock.o): in function `apool_init_freelist':
/home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
definition of `apool_init_freelist';
/tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
first defined here
/usr/bin/ld: ../libolock.a(platform.o): in function `apool_init_freelist':
/home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
definition of `apool_init_freelist';
/tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
first defined here
/usr/bin/ld: ../libolock.a(posix_threads.o): in function
`apool_init_freelist':
/home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
definition of `apool_init_freelist';
/tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
first defined here
/usr/bin/ld: ../libolock.a(anon_pages.o): in function `apool_init_freelist':
/home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
definition of `apool_init_freelist';
/tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
first defined here
/usr/bin/ld: ../libolock.a(os_linux.o): in function `apool_init_freelist':
/home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
definition of `apool_init_freelist';
/tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
first defined here
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:31: otest] Error 1
make[1]: Leaving directory '/home/stevet/stuff/src/projects/olock-beta/test'
make: *** [Makefile:36: test] Error 2

Actually there are two problems, and I had to do something stupid to get
this error, so that one first.

All of the .h files are referenced in a particular sequence in platform.h
and each source module compiled above only includes the consolidated header.

In microsecond_time.h  there are several definitions, one of which is
"typedef s64 T64;".  Now the T64 type is used all over the place and is
defined correctly _except_ for microsecond_time.h.   When
microsecond_time.c is compiled the typedef is missing from the --save-temps
file, whereas it is present in all of the other compilation units.  To
fudge it I modified microsecond_time.c to include only the necessary
headers and added a redundant "typedef s64 T64" line in microsecond_time.c
-- and it compiles!

The second problem is shaped as follows:  apool_init_freelist() is defined
in apool.h as __inline__ and is referenced by two more __inline__ macros,
like this:

__inline__ void apool_init_freelist(apool * a) {
   a->free_list = 1;
   apool_fl_nr_cells(a, 1) = a->pool.nr_cells - 1;  // macro
   apool_fl_next(a, 1) = 0;                                    // macro
   a->nr_free = a->pool.nr_cells - 1;
}

...
__inline__ void init_apool_struct(apool * p)
{
   p->nr_free = p->pool.nr_cells - 1;
   p->pool.offset = sizeof(apool);
   apool_init_freelist(p);
}

These functions aren't used anywhere yet so no code whatsoever should be
generated for apool_init_freelist().   And yet, as you can see in the
linker errors, several modules that do not reference those functions at all
have a symbol and code for the "inline" function.

In comp.lang.c (and in 2018) there is a thread that discusses an eerily
similar problem but in that case it seems to be triggered by a "#define
__attribute__(x)" before inclusion of normal libc headers (affecting atoi)
:   (damn google)

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwiP--P5qpT-AhVjADQIHSMZBmQQFnoECAkQAQ&url=https%3A%2F%2Fgroups.google.com%2Fg%2Fcomp.lang.c%2Fc%2F0fqzRqf--ds&usg=AOvVaw3gu9TODPn58URUag7Y6B5d

The followups do not reveal a cause; the original poster found a workaround
that doesn't apply to my situation.  I could in theory work around this
problem by changing all the __inline__ (in .h files) functions to macros,
or by moving all the inline functions to the .c files, but the whole point
of the "apool" abstraction is that it is a very thin layer and should be
inline.   If I change all the header inline functions to macros it begs the
reason for having __inline__ at all.

At any rate both of these problems are entirely mysterious to me.  I can't
see a reason gcc would produce static copies of a function that is never
used in some but not all source modules where it is defined.  And second, I
should be getting an error for a redefined typedef as things stand with
microsecond time.c.

One last thing, if I compile with -O0 a whole slew of functions declared
"inline" are silently deleted and show up as missing symbols in the static
library link.

I am at a loss.  Suggestions for what to look for would be appreciated.

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

* Re: Multiple symbols defined in object files that should not be there.
  2023-04-06  4:03 Multiple symbols defined in object files that should not be there Steve Thompson
@ 2023-04-06  9:08 ` Jonathan Wakely
       [not found]   ` <CAA0MYJXVX7wue=03DJan21M-wwhkZUuaCQ2BqKmRkyj+yO5f9Q@mail.gmail.com>
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2023-04-06  9:08 UTC (permalink / raw)
  To: Steve Thompson; +Cc: gcc-help

On Thu, 6 Apr 2023 at 05:04, Steve Thompson via Gcc-help
<gcc-help@gcc.gnu.org> wrote:
>
> I have a perplexing problem in compiling source files:
>
> make[1]: Leaving directory '/home/stevet/stuff/src/projects/olock-beta/arch'
> ar cr libolock.a anon_pages.o aobm.o apool.o asm_ops.o bool.o debugging.o
> microsecond_time.o nanosecond_time.o obm.o olock.o os_linux.o platform.o
> posix_mmap.o posix_threads.o statistics.o
> ranlib libolock.a
> make -C test
> make[1]: Entering directory
> '/home/stevet/stuff/src/projects/olock-beta/test'
> gcc10.4  -D _DEFAULT_SOURCE -DARCH_64 -DOLOCK_192 -DLINUX -I./ -I../
> -pthread -m64 -std=c99 -Wall -Wextra -Werror -fdiagnostics-color=never -O
> -ggdb  -DUSE_OBM -o otest otest.c ../libolock.a
> /usr/bin/ld: ../libolock.a(debugging.o): in function `apool_init_freelist':
> /home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
> definition of `apool_init_freelist';
> /tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
> first defined here
> /usr/bin/ld: ../libolock.a(olock.o): in function `apool_init_freelist':
> /home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
> definition of `apool_init_freelist';
> /tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
> first defined here
> /usr/bin/ld: ../libolock.a(platform.o): in function `apool_init_freelist':
> /home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
> definition of `apool_init_freelist';
> /tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
> first defined here
> /usr/bin/ld: ../libolock.a(posix_threads.o): in function
> `apool_init_freelist':
> /home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
> definition of `apool_init_freelist';
> /tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
> first defined here
> /usr/bin/ld: ../libolock.a(anon_pages.o): in function `apool_init_freelist':
> /home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
> definition of `apool_init_freelist';
> /tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
> first defined here
> /usr/bin/ld: ../libolock.a(os_linux.o): in function `apool_init_freelist':
> /home/stevet/stuff/src/projects/olock-beta/./apool.h:92: multiple
> definition of `apool_init_freelist';
> /tmp/ccZflz99.o:/home/stevet/stuff/src/projects/olock-beta/test/../apool.h:92:
> first defined here
> collect2: error: ld returned 1 exit status
> make[1]: *** [Makefile:31: otest] Error 1
> make[1]: Leaving directory '/home/stevet/stuff/src/projects/olock-beta/test'
> make: *** [Makefile:36: test] Error 2
>
> Actually there are two problems, and I had to do something stupid to get
> this error, so that one first.
>
> All of the .h files are referenced in a particular sequence in platform.h
> and each source module compiled above only includes the consolidated header.
>
> In microsecond_time.h  there are several definitions, one of which is
> "typedef s64 T64;".  Now the T64 type is used all over the place and is
> defined correctly _except_ for microsecond_time.h.   When
> microsecond_time.c is compiled the typedef is missing from the --save-temps
> file, whereas it is present in all of the other compilation units.  To

That suggests either the typedef is guarded by some #if check, or that
compilation unit defines either s64 or T64 as a macro.

But nobody can tell you what you've done wrong when only you can see
the code. If you're looking at the save-temps output you should be
able to figure it out - everything you need to know is shown there, or
in the output of gcc -E -dD which shows all the macro definitions as
well.

> fudge it I modified microsecond_time.c to include only the necessary
> headers and added a redundant "typedef s64 T64" line in microsecond_time.c
> -- and it compiles!
>
> The second problem is shaped as follows:  apool_init_freelist() is defined
> in apool.h as __inline__ and is referenced by two more __inline__ macros,
> like this:

You haven't said what the __inline__ macro is defined as, or why
you're using it instead of the standard C99 inline keyword.

Maybe https://gcc.gnu.org/gcc-5/porting_to.html#inline is relevant for you.

>
> __inline__ void apool_init_freelist(apool * a) {
>    a->free_list = 1;
>    apool_fl_nr_cells(a, 1) = a->pool.nr_cells - 1;  // macro
>    apool_fl_next(a, 1) = 0;                                    // macro
>    a->nr_free = a->pool.nr_cells - 1;
> }
>
> ...
> __inline__ void init_apool_struct(apool * p)
> {
>    p->nr_free = p->pool.nr_cells - 1;
>    p->pool.offset = sizeof(apool);
>    apool_init_freelist(p);
> }
>
> These functions aren't used anywhere yet so no code whatsoever should be
> generated for apool_init_freelist().   And yet, as you can see in the
> linker errors, several modules that do not reference those functions at all
> have a symbol and code for the "inline" function.
>
> In comp.lang.c (and in 2018) there is a thread that discusses an eerily
> similar problem but in that case it seems to be triggered by a "#define
> __attribute__(x)" before inclusion of normal libc headers (affecting atoi)
> :   (damn google)
>
> https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwiP--P5qpT-AhVjADQIHSMZBmQQFnoECAkQAQ&url=https%3A%2F%2Fgroups.google.com%2Fg%2Fcomp.lang.c%2Fc%2F0fqzRqf--ds&usg=AOvVaw3gu9TODPn58URUag7Y6B5d
>
> The followups do not reveal a cause; the original poster found a workaround
> that doesn't apply to my situation.  I could in theory work around this
> problem by changing all the __inline__ (in .h files) functions to macros,
> or by moving all the inline functions to the .c files, but the whole point
> of the "apool" abstraction is that it is a very thin layer and should be
> inline.   If I change all the header inline functions to macros it begs the
> reason for having __inline__ at all.
>
> At any rate both of these problems are entirely mysterious to me.  I can't
> see a reason gcc would produce static copies of a function that is never
> used in some but not all source modules where it is defined.  And second, I
> should be getting an error for a redefined typedef as things stand with
> microsecond time.c.
>
> One last thing, if I compile with -O0 a whole slew of functions declared
> "inline" are silently deleted and show up as missing symbols in the static
> library link.
>
> I am at a loss.  Suggestions for what to look for would be appreciated.

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

* Fwd: Multiple symbols defined in object files that should not be there.
       [not found]     ` <CAH6eHdQLHvbjDyRCn-o7cAWLfsfZnuShc9erFonqfDU3nsznqA@mail.gmail.com>
@ 2023-04-07 19:38       ` Steve Thompson
  0 siblings, 0 replies; 3+ messages in thread
From: Steve Thompson @ 2023-04-07 19:38 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 2061 bytes --]

---------- Forwarded message ---------
From: Jonathan Wakely <jwakely.gcc@gmail.com>
Date: Fri, Apr 7, 2023 at 1:54 AM
Subject: Re: Multiple symbols defined in object files that should not be
there.
To: Steve Thompson <susurrus.of.qualia@gmail.com>


Please reply to the list, not just to me.

The preprocessor is dumb, it doesn't do anything complicated. If platform.h
doesn't include microsecond_time.h there must be an include guard stopping
it.

If #undef MICROSECOND_TIME_H doesn't change anything, maybe that's not the
name of the include guard.

None of those is a gcc problem, it's just your code not working how you
want it to.

--------------------------------------------------

Your suggestion to use "-E and -dD" was what I needed to find the
embarassing mistake that caused it all.  FTR I had guard clauses in the
microsecond_time.c file as well as the .h file for some odd reason.  Not a
recent change it seems and my brain was fooled and mostly eliminated those
clauses from my perception, possibly because they are present about half
the time I'm editing any given file and are more-or-less invisible.

I still have the problem that the compiler is generating code in some
object modules for an inline function that is not referenced in the
individual .c files.  Only 7 of 15 source files.  Some of the affected
source files are trivial while others are reasonably complex.

I defined the offending function as "static inline" and tried adding
-fno-keep-inline-functions, but there was no change.  Fooling aroung with
related options had no effect.

From my understanding, GCC simply shouldn't be marking an inline function
for inclusion in an object file unless it is referenced in the source file
it is compiling.  There simply no instances where apool_init_freelist() is
written in any of the .c files; it is only defined in the one .h file.  So
what on Earth is going on?

For the moment I'm going to hope that space aliens beam inspiration
directly into my brain before it melts completely.

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

end of thread, other threads:[~2023-04-07 19:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-06  4:03 Multiple symbols defined in object files that should not be there Steve Thompson
2023-04-06  9:08 ` Jonathan Wakely
     [not found]   ` <CAA0MYJXVX7wue=03DJan21M-wwhkZUuaCQ2BqKmRkyj+yO5f9Q@mail.gmail.com>
     [not found]     ` <CAH6eHdQLHvbjDyRCn-o7cAWLfsfZnuShc9erFonqfDU3nsznqA@mail.gmail.com>
2023-04-07 19:38       ` Fwd: " Steve Thompson

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).