Readelf VS. Objdump: Why Are Both Needed

readelf vs. objdump: why are both needed

from binutils/readelf.c:

 /* The difference between readelf and objdump:

Both programs are capabale of displaying the contents of ELF format files,
so why does the binutils project have two file dumpers ?

The reason is that objdump sees an ELF file through a BFD filter of the
world; if BFD has a bug where, say, it disagrees about a machine constant
in e_flags, then the odds are good that it will remain internally
consistent. The linker sees it the BFD way, objdump sees it the BFD way,
GAS sees it the BFD way. There was need for a tool to go find out what
the file actually says.

This is why the readelf program does not link against the BFD library - it
exists as an independent program to help verify the correct working of BFD.

There is also the case that readelf can provide more information about an
ELF file than is provided by objdump. In particular it can display DWARF
debugging information which (at the moment) objdump cannot. */

Integer within C binary: viewing it using readelf, objdump or similar

In computing, endianness refers to the order of bytes (or sometimes bits) within a binary representation of a number.

In little endian representation the most significant bytes are stored last whereas least significant bytes are stored first. So in little endian, 0xDEADBEEF will be stored as 0xef 0xbe 0xad 0xde.

whereas,

In big endian the the most significant bytes are stored first whereas least significant bytes are stored last. In big endian, 0xDEADBEEF will be stored as 0xde 0xad 0xbe 0xef.


Program instructions are stored in .text section.

Global, static data are stored in .data section of the executable.

Global, static constant data are stored in .rodata (read-only data) section of the executable.

Local constant data are also stored in .text section.

For

//#include <stdio.h>
const char* p = "Hello world";

int main()
{
const long nn = 0xDEADBEEF;
//printf("%s %ld", p, nn);
return -1;
}

When compiled with

gcc hello.c -o hello -nostdlib -e main

(used -nostdlib to reduce the size of the executable)

The hello has following contents:

Contents of section .interp:
0238 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux-
0248 7838362d 36342e73 6f2e3200 x86-64.so.2.
Contents of section .note.gnu.build-id:
0254 04000000 14000000 03000000 474e5500 ............GNU.
0264 45c5b659 336be965 5721226a 788a4906 E..Y3k.eW!"jx.I.
0274 d7528479 .R.y
Contents of section .gnu.hash:
0278 01000000 01000000 01000000 00000000 ................
0288 00000000 00000000 00000000 ............
Contents of section .dynsym:
0298 00000000 00000000 00000000 00000000 ................
02a8 00000000 00000000 ........
Contents of section .dynstr:
02b0 00 .
Contents of section .rela.dyn:
02b8 00102000 00000000 08000000 00000000 .. .............
02c8 e4020000 00000000 ........
Contents of section .text:
02d0 554889e5 b8efbead de488945 f8b8ffff UH.......H.E....
02e0 ffff5dc3 ..].
Contents of section .rodata:
02e4 48656c6c 6f20776f 726c6400 Hello world.
Contents of section .eh_frame_hdr:
02f0 011b033b 14000000 01000000 e0ffffff ...;............
0300 30000000 0...
Contents of section .eh_frame:
0308 14000000 00000000 017a5200 01781001 .........zR..x..
0318 1b0c0708 90010000 1c000000 1c000000 ................
0328 a8ffffff 14000000 00410e10 8602430d .........A....C.
0338 064f0c07 08000000 .O......
Contents of section .dynamic:
200ef0 f5feff6f 00000000 78020000 00000000 ...o....x.......
200f00 05000000 00000000 b0020000 00000000 ................
200f10 06000000 00000000 98020000 00000000 ................
200f20 0a000000 00000000 01000000 00000000 ................
200f30 0b000000 00000000 18000000 00000000 ................
200f40 15000000 00000000 00000000 00000000 ................
200f50 07000000 00000000 b8020000 00000000 ................
200f60 08000000 00000000 18000000 00000000 ................
200f70 09000000 00000000 18000000 00000000 ................
200f80 1e000000 00000000 08000000 00000000 ................
200f90 fbffff6f 00000000 01000008 00000000 ...o............
200fa0 f9ffff6f 00000000 01000000 00000000 ...o............
200fb0 00000000 00000000 00000000 00000000 ................
200fc0 00000000 00000000 00000000 00000000 ................
200fd0 00000000 00000000 00000000 00000000 ................
200fe0 00000000 00000000 00000000 00000000 ................
200ff0 00000000 00000000 00000000 00000000 ................
Contents of section .data:
201000 e4020000 00000000 ........
Contents of section .comment:
0000 4743433a 20285562 756e7475 20372e34 GCC: (Ubuntu 7.4
0010 2e302d31 7562756e 7475317e 31382e30 .0-1ubuntu1~18.0
0020 342e3129 20372e34 2e3000 4.1) 7.4.0.

There you can see the deadbeef in little endian starting at offset 02d5 of the .text section.

Read more,

[1]Endianness: https://en.wikipedia.org/wiki/Endianness

Difference between nm and objdump

They have no similar parameters.
nm lists file symbols, while objdump can show a lot of different information about files. objdump can shows symbols too, and it is explicitly noted in the manpage that "This is similar to the information provided by the nm program, although the display format is different."

What is the difference between ldd and objdump?

You can see the difference in the output.

objdump is simply dumping what the object itself lists as libraries containing unresolved symbols.

ldd is listing which libraries ld.so would actually load. And it follows the graph backward, so that you can see what would be loaded by those libraries. Which is how libpthread.so.0 winds up in the ldd output, despite not being in the objdump output.

So ldd is going to give a much, much better picture of what really needs to be available at runtime. But, when resolving compile/link-time problems, objdump is pretty helpful.



Related Topics



Leave a reply



Submit