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

2

7

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 )?
Allx answered 8/11, 2018 at 14:55 Comment(4)
Not the same description: one is relocatable, the other one is executable.Marceline
which one is relocable, and which one is executableAllx
It is there in the file output: ELF 32-bit LSB relocatable for the .o file.Marceline
Oh, thanks for the tip, I was blind :)Allx
H
11

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.

Hexamethylenetetramine answered 8/11, 2018 at 15:20 Comment(4)
As I asked above, can you help me/point me to some documentation for generating the .map files? More so what are the files with *.out extension?Allx
An ELF file doesn't necessarily have to be an executable program. We have a project that generates what is really just a linkable library, but the output file's format is ELF.Inculpate
I compiled quite a few programs into executable binaries, but have never seen the .elf suffix. I assume a final .elf is just filename sugar. A binary executable is really just an ELF when compiled under Linux, right?Fideicommissum
On today's Linux, all executables are elf files with few exceptions. And as you say, they don't have the file extension. They are also common for microcontroller code.Hexamethylenetetramine
R
1
  • What is the practical difference between both files, or in case I have multiple source file?

A .o file contains the compiled code from one source (compilation unit) but it is not ready to run: it can contain references to external symbols from libraries or other object files.

  • What is the correct file to run, and how to generate it?

That is the executable file (.exe in windows). It is generated by the linking stage (by the linker) which searches libraries and other object files to resolve external references from the .o files.

  • Do I need object files, or they are only intermediary files?

yes, you need them in order to link them, but they are intermediate 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 )?

Some flags "persist" in the sense that they detemine the .o files, but not all. -Wall only gives warnings during compilation, -Os specifies some type of optimization, which will result in a .o file with some optimization on the code performed.

Reclusion answered 8/11, 2018 at 15:5 Comment(6)
Unix does not use extensions to indicate executables (it uses permission bits). .a is the extension for an archive.Neodymium
Thanks for the quick answer, more so, can you tell me/point me to somewhere, on how to generate the .map file? I guess they are some auxiliary files at the linking stage( when using the linker, am I right? )Allx
No, I can't because i don't know gcc. But you can read the documentation.Reclusion
@Allx -Xlinker -Map=output.map for the linking stepGregale
they will list the symbolsGregale
For one last question. As stated above, some flags persists, can I find details about each flag and it's persistence?Allx

© 2022 - 2024 — McMap. All rights reserved.