3

I wrote a simple C++ program with which defined a class like below:

#include <iostream>

using namespace std;

class Computer
{
public:
  Computer();
  ~Computer();
};

Computer::Computer()
{
}

Computer::~Computer()
{
}

int main()
{
  Computer compute;  
    return 0;
}

When I use g++(Test is on x86 32bit Linux with g++ 4.6.3.) to produce the ctors and dtors, I get these definitions at the end of section .ctors.

    .globl  _ZN8ComputerC1Ev
    .set    _ZN8ComputerC1Ev,_ZN8ComputerC2Ev
    .globl  _ZN8ComputerD1Ev
    .set    _ZN8ComputerD1Ev,_ZN8ComputerD2Ev

After digging into the assembly code produced, I figured out that _ZN8ComputerC1Ev should be the function name which is used when class Computer is constructed, while _ZN8ComputerC2Ev is the name of class Computer's constructor. The same thing happens in Computer's destructor declaring and invoking.

It seems that a table is built, linking the constructor and its implementation.

So my questions are:

  1. What actually is this constructor/destructor information for?

  2. Where can I find them in ELF format?

I dumped related .ctors and .init_array section, but I just can not find the meta data that defined the relation between _ZN8ComputerC1Ev and _ZN8ComputerC2Ev...

Igor Skochinsky
  • 24,629
  • 2
  • 72
  • 109
lllllllllllll
  • 8,519
  • 9
  • 45
  • 80

1 Answers1

2

There is no table here. .globl and .set are so-called assembler directives or pseudo ops. They signal something to the assembler, but do not necessarily result in production of actual code or data. From the docs:

.global symbol, .globl symbol

.global makes the symbol visible to ld. If you define symbol in your partial program, its value is made available to other partial programs that are linked with it. Otherwise, symbol takes its attributes from a symbol of the same name from another file linked into the same program.

.set symbol, expression

Set the value of symbol to expression. This changes symbol's value and type to conform to expression.

So the fragment you quote just ensures that the constructor is available for linking in case it's referenced by other compile units. The only effect of it you normally see in the final ELF is the presence of those symbols in the symbol table (if it has not been stripped).

Now, you may be curious about why you have two different names for the constructor (e.g. _ZN8ComputerC1Ev and _ZN8ComputerC2Ev). The answer is somewhat complicated so I will refer you to another SO question which addresses it in some detail:

Dual emission of constructor symbols

Community
  • 1
  • 1
Igor Skochinsky
  • 24,629
  • 2
  • 72
  • 109