18

This question arose in the context of this question: Find unexecuted lines of c++ code

When searching for this problem most people tried to add code and variables into the same section - but this is definitely not the problem here. Here is a minimal working example:

unsigned cover() { return 0; }

#define COV() do { static unsigned cov[2] __attribute__((section("cov"))) = { __LINE__, cover() }; } while(0)

inline void foo() {
        COV();
}

int main(int argc, char* argv[])
{
        COV();

        if (argc > 1)
                COV();

        if (argc > 2)
                foo();

        return 0;
}

which results with g++ -std=c++11 test.cpp (g++ (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)) in the following error:

test.cpp:6:23: error: cov causes a section type conflict with cov
  COV();
                       ^
test.cpp:11:30: note: ‘cov’ was declared here
         COV();
                              ^

The error is not very helpful though, as it does not state why this is supposed to be a conflict. Both the .ii and .s temporary files give no hint as to what might be the problem. In fact there is only one section definition in the .s file

        .section        cov,"aw",@progbits

and I don't see why the next definition should conflict with this ("aw",@progbits is correct...).

Is there any way to get more information on this? See what the precise conflict is? Or is this just a bug...?

Community
  • 1
  • 1
example
  • 3,349
  • 1
  • 20
  • 29
  • Also see [Compile error "X causes a section type conflict with Y" should provide more information](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82209) in the GCC Issue Tracker. – jww Sep 14 '17 at 07:34
  • 4
    This question is an exact duplicate of [Inline static data causes a section type conflict](https://stackoverflow.com/q/35091862/1362568), of which I wrote the accepted answer with a detailed explanation and for which [the OP's own subsequent solution](https://stackoverflow.com/a/36361512/1362568) is nicer. The use of `__attribute__` as in the problem is unsupported by GCC. – Mike Kinghan Sep 14 '17 at 09:33
  • @MikeKinghan suggestion: 1/ make a summary of your excellent answer from the duplicate. 2/ earn bounty. 3/ close question as duplicate. – YSC Sep 19 '17 at 09:25
  • 1
    @YSC Tempted, but I feel it would be unseemly of me to have lifted 295 rep for my former answer and then to lift another 100 or so by summarizing it - when I only have the opportunity due to having not noticed this dupe in time to close-vote it before it was bountied! – Mike Kinghan Sep 19 '17 at 19:09
  • @Mike - The best I can tell, the analysis in your other answer is correct. However, this question is concerned with ***identifying*** the problem sections. That's why: ***"This bounty attempts to obtain a canonical answer for troubleshooting the conflict by pinpointing the offenders"***. (We have the same problem. We have almost 200 object files, and we have no idea which symbols are causing the failure. There's no realistic way we can manually inspect 10's of thousands of symbols from hundreds of object files) – jww Sep 22 '17 at 04:51
  • @jww Hi. For the type of section conflict I discussed, a problem section is one that, in the same translation unit, is *unsupportedly* attributed to *local static* variables, at least one in the scope of an *inlined* function and at least one not. If your type of section conflict is the same it should not be hard to find the culprit attributions by scripting to trawl the preprocessed (`.ii`) translation units. Essentially you only need to find section attributions not at global scope - the unsupported ones. – Mike Kinghan Sep 22 '17 at 07:56
  • Possible duplicate of [Inline static data causes a section type conflict](https://stackoverflow.com/questions/35091862/inline-static-data-causes-a-section-type-conflict) – Mike Kinghan Sep 22 '17 at 09:52

1 Answers1

1

The message is indeed very bad, but it isn't a bug. The problem here occurs with inline function foo() and occurs because Inline functions must be defined in each translation context where they used. In this link we can read about section attribute:
"..uninitialized variables tentatively go in the common (or bss) section and can be multiply ‘defined’. Using the section attribute changes what section the variable goes into and may cause the linker to issue an error if an uninitialized variable has multiple definitions...".

Thus, when the foo function needs to be 'defined' in function main, the linker finds cov variable previously defined in inline function foo and issues the error.

Let’s make the pre-processor's work and expand COV() define to help to clarify the problem:

inline  void foo()
{
    do { static unsigned cov[2] __attribute__((section("cov"))) = { 40, cover() }; } while(0);
}

int main(int argc, char *argv[]) {
    do { static unsigned cov[2] __attribute__((section("cov"))) = { 44, cover() }; } while(0);

    if (argc > 1)
        do { static unsigned cov[2] __attribute__((section("cov"))) = { 47, cover() }; } while(0);

    if (argc > 2)
             foo();

To facilitate reasoning, let’s alter the section attribute of definition in foo inline function to cov.2 just to compile the code. Now we haven’t the error, so we can examine the object (.o) with objdump:

objdump -C -t -j cov ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o

./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    d  cov    0000000000000000 cov
0000000000000000 l     O cov    0000000000000008 main::cov
0000000000000008 l     O cov    0000000000000008 main::cov

objdump -C -t -j cov.2 ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o 

./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    d  cov.2  0000000000000000 cov.2
0000000000000000 u     O cov.2  0000000000000008 foo()::cov

We can see that compiler makes foo::cov, in section cov.2 GLOBAL (signed by ‘u’ letter). When we use the same section name (cov), the compiler, trying to ‘define’ foo in main block encounters a previous globally defined cov and the issues the error.

If you make inline foo static (inline static void foo() . . .), which avoids compiler to emit code for inline function and just copies it at expansion time, you’ll see the error disappears, because there isn't a global foo::cov.

  • I think this is a restatement of Mike's answer in the cited question. However, this question is concerned with ***identifying*** the problem sections. That's why: ***"This bounty attempts to obtain a canonical answer for troubleshooting the conflict by pinpointing the offenders"***. (We have the same problem. We have almost 200 object files, and we have no idea which symbols are causing the failure. There's no realistic way we can manually inspect 10's of thousands of symbols from hundreds of object files) – jww Sep 22 '17 at 04:54