Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Executable and Linkable Format(.elf) and Object(.o) file

I was looking in the gcc manual on linux (man gcc), for the -c option (gcc -c infile) which states:

-c: Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o.

more so, while inspecting an ELF file and an object file( with file comand ) the output is the same:

file ./out/main.o: ELF 32-bit LSB relocatable, Atmel AVR 8-bit, version 1 (SYSV), not stripped
file ./out/main.elf: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped

So they both have same description. My questions are:

  • What is the practical difference between both files, or in case I have multiple source file?
  • What is the correct file to run, and how to generate it?
  • Do I need object files, or they are only intermediary files?
  • If I compile some source files with -c option and some flags( -Wall -g -std=c99 -Os ) and get the object files from them, does the flags persist on ELF file generation( can I skip the flags while generating ELF file if I used them on Object files )?
like image 568
Upgrade Avatar asked Jul 21 '26 15:07

Upgrade


1 Answers

Let's make a simple example. You have these three files:

cnt.h

void inc_counter();
void print_counter();

cnt.c

#include <stdio.h>
#include <cnt.h>

static int counter= 0;

void inc_counter() {
    couner++;
}

void print_counter() {
    printf("Counter: %d\n", counter);
}

main.c

#include <cnt.h>

int main(char** args) {
    inc_counter();
    print_counter();
    return 0;
}

You then compile cnt.c and main.c to create cnt.o and main.o.

  • cnt.o will contain the executable code for get_counter and inc_counter. For each one it has an entry point. But the code is not executable. The call of printf will not work as the address of printf is not yet know. So the file contains information that this will need to be fixed later.
  • main.o will contain the executable code for main and an entry point for it. Again, the references for inc_counter and print_counter will not work.

In the second step, the files cnt.o, main.o and the standard C library will be linked and an executable output file will be created (with the .elf or no extension). The linker will create the missing links between the call of inc_counter and the function inc_counter. And it will do the same for print_counter and printf, thereby including the code of printf from the standard libary.

So while both file types mainly consist of executable code, .o files only contain pieces of code and .elf files contain a full program.

Note: There are additional variations when you create or use dynamically linked libraries. But for the sake of simplicity, I've excluded them.

like image 168
Codo Avatar answered Jul 23 '26 03:07

Codo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!