A disassembler is very useful for debugging. This tutorial will provide information regards ELF file format and disassembler command. As an add-on Some hidden facts of the main function explained with examples.
Learn about the ELF file format.
What is EFL file format?
- EFL means “Executable and Linkable Format” (EFL, formerly named Extensible Linking Format).
- It is a common standard file format for executable files, object code, shared libraries, and core dumps.
More you can read about it here!
A disassembler is a computer code that translates machine language (binary code) into assembly language. In simple words it is an inverse operation to that of an assembler.
Hex Editors (Disassembler): Which converts binary code to assembly code
COMMAND: objdump (Object dump)
objdump is by default available in UNIX/Linux Disassembler. Which is mainly used to edit an object file (binary file) using Disassembler.
To learn about object file creation click here!
objdump command in Linux is used to get in detail information of an object file.
This command is mainly used by the compiler programmers, but still, it is a handy tool for normal programmers also for debugging of code.
$ objdump [options] <object file>...
$ objdump -D prog.o
This is how objdump gives output. It directly takes you to down is not user friendly way to go-through.
Problem means there is a solution.
Use “less” or “more” command if you want the output in page wise display.
Extra info- ” | “ is a pipe (we will learn in linux tutorial).
$ objdump -D prog.o | less
$ objdump -D prog.o | more
W = go one page up
D = one page down
S = one line down
Or you can use arrow keys of keyboard and page down and page up button.
Q = to quit the page view
When you disassemble object file you can see that program execution starts from startup function wherein startup function main function is called & main executed & returns to the startup function.
NOTE: main is called by startup function, main returns to startup function so that’s why we never call the main function, it only does by startup function.
Q) Why size of object file and executable files are different?
$ size prog.o
$ size prog
prog.o object file is nothing but an object code of our written main code. While the Executable file prog file is created by linker; the task of a linker is to link OS supported files and other object files to it.
That’s a reason for executable file size is larger than the object file.
Interesting main() function.
If the return type is not mentioned then default return type will be int but some compiler will throw warnings and warnings are annoying.
main( ) == int main( ) == main(void) == int main(void)
Always start with a good habits.
<return type> function name (arguments)
This is a prototype of a function and if we follow, in future it will very helpful.
Reason in the future we will see main is also having arguments and sometimes we forgot to write the arguments and makes the unnecessary debugging task. That’s a pro point.
main() is always a calling function i.e it is not a called function.
In simple terms we can not call main() in code.
Execution starts from main and ends with main.
But what if I not use main() in code?
Lets test this:
This is our test.c source code.
Our source code passed Preprocessor stage, means no error.
Our source code passed Translator stage, means no error.
Our source code passed Assembler stage, means no error.
Whoa! Linker has thrown an error. Error found because the linker does not found main( ) in startup function. Let’s break it out in small chunks.
Undefined symbols for architecture x86_64: "_main", referenced from: implicit entry/start for main executable ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
Undefined symbols for architecture x86_64: "_main", referenced from: implicit entry/start for main executable ld: symbol(s) not found for architecture x86_64
in x86 architecture _main is a implicit function. What is a meaning of implicit?
clang: error: linker command failed with exit code 1 (use -v to see invocation)
So as per definition main function should be there. that’s why linker exited with code 1.
Every linker starts execution with main( ).
To overcome linking error use the following command.
$ gcc -nostartfiles test.c
If you like this article. Comment your views. It will motivate us.