1

I understand that name mangling happens. What I don't understand is this:

class MyClass{
public:
  int doStuff(int a){
    return a+1;
  }
};

int main(){
  MyClass myclass;
  myclass.doStuff(2);

  return 0;
}
 > g++ -c  -O0 blah.cpp && objdump -h blah.o 

blah.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .group        00000008  0000000000000000  0000000000000000  00000040  2**2
                  CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD
  1 .text         00000043  0000000000000000  0000000000000000  00000048  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  2 .data         00000000  0000000000000000  0000000000000000  0000008b  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  3 .bss          00000000  0000000000000000  0000000000000000  0000008b  2**0
                  ALLOC
  4 .text._ZN7MyClass7doStuffEi 00000013  0000000000000000  0000000000000000  0000008c  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  5 .comment      00000036  0000000000000000  0000000000000000  0000009f  2**0
                  CONTENTS, READONLY
  6 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000d5  2**0
                  CONTENTS, READONLY
  7 .eh_frame     00000058  0000000000000000  0000000000000000  000000d8  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

Why is MyClass.doStuff in its own section, the section name being the mangled symbol for that member function?

I think this is not necessary for the linking to work, since it is the symbols that match when linking, not sections. ie. if everything was in .text it should work.

Is there a way to make this not happen?

PizzaBeer
  • 183
  • 14
  • 2
    blah.o is not an executable. Each externally linked symbol is placed in own section in an object file, so linker can remove it later if it is not used or place into .text of a result executable. In other words each such section is a function body. – 273K May 19 '20 at 15:56
  • Thanks for the info, but that's not true according to the simple test above. If you add to the above code a declaration and call to some function, it is put into "RELOCATION RECORDS FOR [.text]". So it seems all externally linked symbols go into 1 place, don't know what to call it but it is not a section. Moreover, the member function in the test code is not external. – PizzaBeer May 19 '20 at 16:27
  • @S.M. if you were referring to "public" functions ie. non-static functions, I tried, and the function body is in .text. It did not get its own section. It seems only the member function gets its own section. – PizzaBeer May 19 '20 at 16:52
  • My comment is more correct for inline functions. – 273K May 19 '20 at 17:50
  • 1
    You can use `-ffunction-sections` to give every function its own section anyway. (And `-fdata-sections`). Combined with a linker option. this helps to reduce the size of the executable because the linker can discard unused functions – M.M May 19 '20 at 20:28

1 Answers1

3

Not quite a duplicate but see my answer to this related question for deeper detail.

g++ (or clang++) compiles the inline definition of a class member function such as int MyClass::doStuff(int) as the inline definition of a weakly global symbol, e.g._ZN7MyClass7doStuffEi1 in the object file whenever the translation unit references the function, and places this definition in its own function section.

This is done because:-

An inline function definition must exist in every translation unit in which the function is referenced. But there may then be multiple object files in a linkage which contain identical definitions of _ZN7MyClass7doStuffEi.

So _ZN7MyClass7doStuffEi must be weak and global. Weak so that the linker will be at liberty to pick any one definition and discard the rest, as demanded by the One Definition Rule. Global so that whichever one of the identical definitions is selected for linkage can be referenced from the other object files in the linkage that do reference it.

Finally each definition of _ZN7MyClass7doStuffEi is placed in its own function section in each object file to ensure that the linker can discard this function definition. If other global symbols referenced by the program could be defined in the same section with _ZN7MyClass7doStuffEi then it might be impossible to discard all but one definition, forcing a multiple-definition error.


[1] Your comment "the member function in the test code is not external" is not correct. You don't and can't declare the member function extern but a (weak or strong) global symbol has external linkage.
Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
  • 1
    @PizzaBeer If "this topic" is the innards of GCC/GNU binutils compilation and linkage, I've learned most of what I know - which isn't very much - by experimentation with the tools, sleuthing in forum posts, mailing lists, bug-trackers, studying the tool sources as a last resort, that sort of stuff. I guess https://gcc.gnu.org/onlinedocs/gccint/ + https://stackoverflow.com/q/81656/1362568 + https://en.cppreference.com/w/ + https://www.amazon.co.uk/Linkers-Kaufmann-Software-Engineering-Programming/dp/1558604960 are ways into many things you might be curious about – Mike Kinghan May 20 '20 at 11:27