Search code examples
c++g++elfreadelf

Why is my simple `main` program's ELF header say it's a `DYN (Shared object file)` instead of an executable?


Here's a very simple C++ program:

// main.cpp
int main() {}

My Makefile generates the following command to compile the program.

❯ make
g++ -O0 -fverbose-asm  -o main main.cpp

I check with the command file to see it's an ELF executable:

❯ file main
main: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=921d352e49a0e4262aece7e72418290189520782, for GNU/Linux 3.2.0, not stripped

Everything seems fine until I try to inspect the ELF header:

❯ readelf -e main
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
...
  Type:                              DYN (Shared object file)

From wikipedia here, it appears that there are different types of files such as EXEC. Why does it say my simple main program is a shared object and not an executable on the ELF header?

From the limited scope of knowledge I have on .so's, I thought they were libraries that is linked but not loaded until runtime. How does that make sense in this context?

Extra information:

❯ g++ --version
g++ (Arch Linux 9.3.0-1) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.

❯ readelf --version
GNU readelf (GNU Binutils) 2.34
Copyright (C) 2020 Free Software Foundation, Inc.

❯ lsb_release -a
LSB Version:    1.4
Distributor ID: Arch
Description:    Arch Linux
Release:    rolling
Codename:   n/a

Solution

  • Executables that are as compiled as "position independent executables" (with -pie/-fPIE) should be relocated to a random address at runtime. To achieve this, they use the DYN type.

    Your version of g++ was configured with --enable-default-pie, so it sets -pie and -fPIE by default. You can disable this, and generate a normal executable, by linking with -no-pie.