C++ Binary Internals

The idea for this post started out as an exploration of compiler optimizations in GCC. It turned into a static and dynamic C++ class exploration exercise. The piece of code we’ll look at:

// file: bin1.hpp
using namespace std;

class FirstClass
        FirstClass(int new_id) { id = new_id; };
        int get_id() const { return id; };
        int id;

// file: bin1.cpp
#include "bin1.hpp"

int main()
    FirstClass a(0x539);
    printf("%d\n", a.get_id());
    return 0;

It is best practice to declare constructors and member functions in the header file, then have the implementation in the cpp file. This class is extremely simple though so I’ve opted for a more concise class definition. bin1 initializes a new object of type FirstClass, with id of 0x539. Compile with g++ -o bin1 bin1.cpp then look at the resulting binary’s .text section with objdump -M intel –demangle=gnu-v3 –section=.text -S bin1. Nice! I’ll be focusing on the sections directly related to the FirstClass class.

.text section symbols

Entry point of binary.

GCC transactional memory table tear down.

GCC transactional memory table setup.

Run all global destructors on exit when .fini_array is unavailable.


Our defined int main() function.

Calls constructors of classes with static storage duration, 
and registers destructors of classes with static storage duration. 
This shouldn't be relevant to FirstClass class, but is relevant for iostream.

Wrapper function to the above function.

Our FirstClass constructor

FirstClass::get_id() const
Our FirstClass get_id() member function

Calls function that need to run before main().

Calls functions that need to run after main().

Now the disassembly of the FirstClass constructor:


push   rbp                     ; function prologue
mov    rbp,rsp
mov    QWORD PTR [rbp-0x8],rdi ; rdi is a pointer to the object, move to stack
mov    DWORD PTR [rbp-0xc],esi ; esi is the id we provided, 0x529, move to stack
mov    rax,QWORD PTR [rbp-0x8] ; move object pointer to rax
mov    edx,DWORD PTR [rbp-0xc] ; move object id to edx
mov    DWORD PTR [rax],edx     ; move object id to 0th position in object
pop    rbp

Immediately after we return from this call, the top of the stack will be our object. (Object starts at 0x7fffffffded4)

0000| 0x7fffffffded0 --> 0x539ffffdfc0

The 0x539 is the ID we care about, the following bytes are garbage left behind in memory from some previous operation. Now the disassembly of the FirstClass get_id() member function:

FirstClass::get_id() const:

push   rbp                     ; function prologue
mov    rbp,rsp 
mov    QWORD PTR [rbp-0x8],rdi ; rdi points to object on stack
mov    rax,QWORD PTR [rbp-0x8] ; move object addr into rax
mov    eax,DWORD PTR [rax]     ; dereference object pointer, get 32 bits of data (the id)
pop    rbp

This has been a simple exploration of C++ classes during runtime.


Leave a Reply