Search code examples
c++g++gnuelf

Where does C++ keep it's class variables in the resulting ELF file?


This question relates specifically to the x86 architecture, g++ compiler and c++ code.

So, I have the following code:

#include <iostream>

int second;

class First {
private:
        int hello;
public:
        First(int number)
        {
            hello = number;
        }

        void printStuff()
        {
            std::cout<<this->hello<<'\n';
        }
};

int main(int argc, char** argv)
{
    First *first = new First(argc);
    first->printStuff();
    second = argc;
    return 0;
}

After compiling it like so:

g++ -O0 -g class.cpp -o class

I get the output class binary.

Now, I want to know where hello is stored, so I do readelf -s ./class and the output is:

[ishaypeled@escorpio tmp14]$ readelf -s --wide ./class

Symbol table '.dynsym' contains 13 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSolsEi@GLIBCXX_3.4 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (3)
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@GLIBC_2.2.5 (3)
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c@GLIBCXX_3.4 (2)
     8: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
     9: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    10: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _Znwm@GLIBCXX_3.4 (2)
    11: 00000000004006c0     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4 (2)
    12: 0000000000600dc0   272 OBJECT  GLOBAL DEFAULT   26 _ZSt4cout@GLIBCXX_3.4 (2)

Symbol table '.symtab' contains 88 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1 
     2: 000000000040021c     0 SECTION LOCAL  DEFAULT    2 
     3: 000000000040023c     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000400260     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000400288     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000004003c0     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000400502     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000400520     0 SECTION LOCAL  DEFAULT    8 
     9: 0000000000400560     0 SECTION LOCAL  DEFAULT    9 
    10: 0000000000400590     0 SECTION LOCAL  DEFAULT   10 
    11: 0000000000400638     0 SECTION LOCAL  DEFAULT   11 
    12: 0000000000400660     0 SECTION LOCAL  DEFAULT   12 
    13: 00000000004006e0     0 SECTION LOCAL  DEFAULT   13 
    14: 00000000004006f0     0 SECTION LOCAL  DEFAULT   14 
    15: 0000000000400944     0 SECTION LOCAL  DEFAULT   15 
    16: 0000000000400950     0 SECTION LOCAL  DEFAULT   16 
    17: 0000000000400958     0 SECTION LOCAL  DEFAULT   17 
    18: 00000000004009b0     0 SECTION LOCAL  DEFAULT   18 
    19: 0000000000600b30     0 SECTION LOCAL  DEFAULT   19 
    20: 0000000000600b40     0 SECTION LOCAL  DEFAULT   20 
    21: 0000000000600b48     0 SECTION LOCAL  DEFAULT   21 
    22: 0000000000600b50     0 SECTION LOCAL  DEFAULT   22 
    23: 0000000000600d50     0 SECTION LOCAL  DEFAULT   23 
    24: 0000000000600d58     0 SECTION LOCAL  DEFAULT   24 
    25: 0000000000600da8     0 SECTION LOCAL  DEFAULT   25 
    26: 0000000000600dc0     0 SECTION LOCAL  DEFAULT   26 
    27: 0000000000000000     0 SECTION LOCAL  DEFAULT   27 
    28: 0000000000000000     0 SECTION LOCAL  DEFAULT   28 
    29: 0000000000000000     0 SECTION LOCAL  DEFAULT   29 
    30: 0000000000000000     0 SECTION LOCAL  DEFAULT   30 
    31: 0000000000000000     0 SECTION LOCAL  DEFAULT   31 
    32: 0000000000000000     0 SECTION LOCAL  DEFAULT   32 
    33: 0000000000000000     0 SECTION LOCAL  DEFAULT   33 
    34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS init.c
    35: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    36: 0000000000600b48     0 OBJECT  LOCAL  DEFAULT   21 __JCR_LIST__
    37: 0000000000400720     0 FUNC    LOCAL  DEFAULT   14 deregister_tm_clones
    38: 0000000000400760     0 FUNC    LOCAL  DEFAULT   14 register_tm_clones
    39: 00000000004007a0     0 FUNC    LOCAL  DEFAULT   14 __do_global_dtors_aux
    40: 0000000000600ed0     1 OBJECT  LOCAL  DEFAULT   26 completed.6938
    41: 0000000000600b40     0 OBJECT  LOCAL  DEFAULT   20 __do_global_dtors_aux_fini_array_entry
    42: 00000000004007c0     0 FUNC    LOCAL  DEFAULT   14 frame_dummy
    43: 0000000000600b30     0 OBJECT  LOCAL  DEFAULT   19 __frame_dummy_init_array_entry
    44: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS class.cpp
    45: 0000000000400954     1 OBJECT  LOCAL  DEFAULT   16 _ZStL19piecewise_construct
    46: 0000000000600ed8     1 OBJECT  LOCAL  DEFAULT   26 _ZStL8__ioinit
    47: 0000000000400835    62 FUNC    LOCAL  DEFAULT   14 _Z41__static_initialization_and_destruction_0ii
    48: 0000000000400873    21 FUNC    LOCAL  DEFAULT   14 _GLOBAL__sub_I_second
    49: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    50: 0000000000400b28     0 OBJECT  LOCAL  DEFAULT   18 __FRAME_END__
    51: 0000000000600b48     0 OBJECT  LOCAL  DEFAULT   21 __JCR_END__
    52: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
    53: 0000000000400958     0 NOTYPE  LOCAL  DEFAULT   17 __GNU_EH_FRAME_HDR
    54: 0000000000600d58     0 OBJECT  LOCAL  DEFAULT   24 _GLOBAL_OFFSET_TABLE_
    55: 0000000000600b40     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_end
    56: 0000000000600b30     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_start
    57: 0000000000600b50     0 OBJECT  LOCAL  DEFAULT   22 _DYNAMIC
    58: 0000000000600da8     0 NOTYPE  WEAK   DEFAULT   25 data_start
    59: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSolsEi@@GLIBCXX_3.4
    60: 0000000000400940     2 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini
    61: 0000000000600ed4     4 OBJECT  GLOBAL DEFAULT   26 second
    62: 00000000004006f0    42 FUNC    GLOBAL DEFAULT   14 _start
    63: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    64: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    65: 0000000000400944     0 FUNC    GLOBAL DEFAULT   15 _fini
    66: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
    67: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_2.2.5
    68: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@@GLIBC_2.2.5
    69: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c@@GLIBCXX_3.4
    70: 00000000004006c0     0 FUNC    GLOBAL DEFAULT  UND _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
    71: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
    72: 0000000000400950     4 OBJECT  GLOBAL DEFAULT   16 _IO_stdin_used
    73: 0000000000400888    23 FUNC    WEAK   DEFAULT   14 _ZN5FirstC1Ei
    74: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    75: 0000000000600da8     0 NOTYPE  GLOBAL DEFAULT   25 __data_start
    76: 00000000004008a0    46 FUNC    WEAK   DEFAULT   14 _ZN5First10printStuffEv
    77: 0000000000400888    23 FUNC    WEAK   DEFAULT   14 _ZN5FirstC2Ei
    78: 0000000000600db8     0 OBJECT  GLOBAL HIDDEN    25 __TMC_END__
    79: 0000000000600dc0   272 OBJECT  GLOBAL DEFAULT   26 _ZSt4cout@@GLIBCXX_3.4
    80: 0000000000600db0     0 OBJECT  GLOBAL HIDDEN    25 __dso_handle
    81: 00000000004008d0   101 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
    82: 0000000000600db8     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start
    83: 0000000000600ee0     0 NOTYPE  GLOBAL DEFAULT   26 _end
    84: 0000000000600db8     0 NOTYPE  GLOBAL DEFAULT   25 _edata
    85: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _Znwm@@GLIBCXX_3.4
    86: 00000000004007e6    79 FUNC    GLOBAL DEFAULT   14 main
    87: 0000000000400638     0 FUNC    GLOBAL DEFAULT   11 _init

For better readability, I also ran this command:

[ishaypeled@escorpio tmp14]$ readelf -s --wide ./class | c++filt

Symbol table '.dynsym' contains 13 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)@GLIBCXX_3.4 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::ios_base::Init::Init()@GLIBCXX_3.4 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (3)
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@GLIBC_2.2.5 (3)
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)@GLIBCXX_3.4 (2)
     8: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
     9: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    10: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND operator new(unsigned long)@GLIBCXX_3.4 (2)
    11: 00000000004006c0     0 FUNC    GLOBAL DEFAULT  UND std::ios_base::Init::~Init()@GLIBCXX_3.4 (2)
    12: 0000000000600dc0   272 OBJECT  GLOBAL DEFAULT   26 std::cout@GLIBCXX_3.4 (2)

Symbol table '.symtab' contains 88 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1 
     2: 000000000040021c     0 SECTION LOCAL  DEFAULT    2 
     3: 000000000040023c     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000400260     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000400288     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000004003c0     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000400502     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000400520     0 SECTION LOCAL  DEFAULT    8 
     9: 0000000000400560     0 SECTION LOCAL  DEFAULT    9 
    10: 0000000000400590     0 SECTION LOCAL  DEFAULT   10 
    11: 0000000000400638     0 SECTION LOCAL  DEFAULT   11 
    12: 0000000000400660     0 SECTION LOCAL  DEFAULT   12 
    13: 00000000004006e0     0 SECTION LOCAL  DEFAULT   13 
    14: 00000000004006f0     0 SECTION LOCAL  DEFAULT   14 
    15: 0000000000400944     0 SECTION LOCAL  DEFAULT   15 
    16: 0000000000400950     0 SECTION LOCAL  DEFAULT   16 
    17: 0000000000400958     0 SECTION LOCAL  DEFAULT   17 
    18: 00000000004009b0     0 SECTION LOCAL  DEFAULT   18 
    19: 0000000000600b30     0 SECTION LOCAL  DEFAULT   19 
    20: 0000000000600b40     0 SECTION LOCAL  DEFAULT   20 
    21: 0000000000600b48     0 SECTION LOCAL  DEFAULT   21 
    22: 0000000000600b50     0 SECTION LOCAL  DEFAULT   22 
    23: 0000000000600d50     0 SECTION LOCAL  DEFAULT   23 
    24: 0000000000600d58     0 SECTION LOCAL  DEFAULT   24 
    25: 0000000000600da8     0 SECTION LOCAL  DEFAULT   25 
    26: 0000000000600dc0     0 SECTION LOCAL  DEFAULT   26 
    27: 0000000000000000     0 SECTION LOCAL  DEFAULT   27 
    28: 0000000000000000     0 SECTION LOCAL  DEFAULT   28 
    29: 0000000000000000     0 SECTION LOCAL  DEFAULT   29 
    30: 0000000000000000     0 SECTION LOCAL  DEFAULT   30 
    31: 0000000000000000     0 SECTION LOCAL  DEFAULT   31 
    32: 0000000000000000     0 SECTION LOCAL  DEFAULT   32 
    33: 0000000000000000     0 SECTION LOCAL  DEFAULT   33 
    34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS init.c
    35: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    36: 0000000000600b48     0 OBJECT  LOCAL  DEFAULT   21 __JCR_LIST__
    37: 0000000000400720     0 FUNC    LOCAL  DEFAULT   14 deregister_tm_clones
    38: 0000000000400760     0 FUNC    LOCAL  DEFAULT   14 register_tm_clones
    39: 00000000004007a0     0 FUNC    LOCAL  DEFAULT   14 __do_global_dtors_aux
    40: 0000000000600ed0     1 OBJECT  LOCAL  DEFAULT   26 completed.6938
    41: 0000000000600b40     0 OBJECT  LOCAL  DEFAULT   20 __do_global_dtors_aux_fini_array_entry
    42: 00000000004007c0     0 FUNC    LOCAL  DEFAULT   14 frame_dummy
    43: 0000000000600b30     0 OBJECT  LOCAL  DEFAULT   19 __frame_dummy_init_array_entry
    44: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS class.cpp
    45: 0000000000400954     1 OBJECT  LOCAL  DEFAULT   16 std::piecewise_construct
    46: 0000000000600ed8     1 OBJECT  LOCAL  DEFAULT   26 std::__ioinit
    47: 0000000000400835    62 FUNC    LOCAL  DEFAULT   14 __static_initialization_and_destruction_0(int, int)
    48: 0000000000400873    21 FUNC    LOCAL  DEFAULT   14 _GLOBAL__sub_I_second
    49: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    50: 0000000000400b28     0 OBJECT  LOCAL  DEFAULT   18 __FRAME_END__
    51: 0000000000600b48     0 OBJECT  LOCAL  DEFAULT   21 __JCR_END__
    52: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
    53: 0000000000400958     0 NOTYPE  LOCAL  DEFAULT   17 __GNU_EH_FRAME_HDR
    54: 0000000000600d58     0 OBJECT  LOCAL  DEFAULT   24 _GLOBAL_OFFSET_TABLE_
    55: 0000000000600b40     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_end
    56: 0000000000600b30     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_start
    57: 0000000000600b50     0 OBJECT  LOCAL  DEFAULT   22 _DYNAMIC
    58: 0000000000600da8     0 NOTYPE  WEAK   DEFAULT   25 data_start
    59: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)@@GLIBCXX_3.4
    60: 0000000000400940     2 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini
    61: 0000000000600ed4     4 OBJECT  GLOBAL DEFAULT   26 second
    62: 00000000004006f0    42 FUNC    GLOBAL DEFAULT   14 _start
    63: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    64: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    65: 0000000000400944     0 FUNC    GLOBAL DEFAULT   15 _fini
    66: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::ios_base::Init::Init()@@GLIBCXX_3.4
    67: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_2.2.5
    68: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@@GLIBC_2.2.5
    69: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)@@GLIBCXX_3.4
    70: 00000000004006c0     0 FUNC    GLOBAL DEFAULT  UND std::ios_base::Init::~Init()@@GLIBCXX_3.4
    71: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
    72: 0000000000400950     4 OBJECT  GLOBAL DEFAULT   16 _IO_stdin_used
    73: 0000000000400888    23 FUNC    WEAK   DEFAULT   14 First::First(int)
    74: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    75: 0000000000600da8     0 NOTYPE  GLOBAL DEFAULT   25 __data_start
    76: 00000000004008a0    46 FUNC    WEAK   DEFAULT   14 First::printStuff()
    77: 0000000000400888    23 FUNC    WEAK   DEFAULT   14 First::First(int)
    78: 0000000000600db8     0 OBJECT  GLOBAL HIDDEN    25 __TMC_END__
    79: 0000000000600dc0   272 OBJECT  GLOBAL DEFAULT   26 std::cout@@GLIBCXX_3.4
    80: 0000000000600db0     0 OBJECT  GLOBAL HIDDEN    25 __dso_handle
    81: 00000000004008d0   101 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
    82: 0000000000600db8     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start
    83: 0000000000600ee0     0 NOTYPE  GLOBAL DEFAULT   26 _end
    84: 0000000000600db8     0 NOTYPE  GLOBAL DEFAULT   25 _edata
    85: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND operator new(unsigned long)@@GLIBCXX_3.4
    86: 00000000004007e6    79 FUNC    GLOBAL DEFAULT   14 main
    87: 0000000000400638     0 FUNC    GLOBAL DEFAULT   11 _init

My question is, where is the variable first? I don't see this object in the dump! Note that second is there as symbol 61. I expected mangling of first, but not for it to disappear altogether...

Anyone?


Solution

  • example.cpp:

    class Clazz {
        int x;              // will live wherever the instance of Clazz is created
    public:
        Clazz(const std::initializer_list<int> & data) {}
        Clazz() : x(13) {}  // "13" is either in constructor code, or .rodata
    };
    
    // these will end in .data section
    // except the list parameter {1, 2, 3}, which is const and lands in .rodata
    static int localInt;    // local symbol, will be in .o file only in debug info
    int globalInt;          // global symbol
        // btw, both are initialized to 0, as they are defined in .data
    static Clazz *classPtr = nullptr;
    Clazz classInstance( {1, 2, 3} );
    
    // all global symbols from .data/.rodata/.bss/.text (.code) sections
    // will be visible in symbol table of executable (including the "foo" below)
    
    // everything else defined below (except foo) is runtime allocated,
    // and can't have any fixed address in symbol table, so it will not show there.
    
    void foo(int param) {   // param is either on stack or in register (ABI specific)
        Clazz localVar;     // localVar instance is living on the stack space
        classPtr = new Clazz({});
        // Instance of Clazz pointed at by classPtr lives in global heap memory
        // If not released by explicit "delete classPtr;" during runtime,
        // it will cause memory leak (avoid using naked pointers like this).
        int localInt;       // localInt lives on stack too, uninitialized = undefined value!
        // On the contrary to *classPtr the localVar is released upon exiting it's scope
    }
    

    Neither stack or heap instances are in ELF file, in ELF file is only code capable to manipulate the instance, and to create the instance (either on stack or on heap, either by instancing it as global/local variable, or by new).

    So unless you instantiate some type into .data/.bss sections (ie. defining it outside of function, as a global/local of that .cpp file), you can't figure out the where the variable will be kept by looking at symbol table of executable.