Comando objdump de Linux explicado para principiantes (7 ejemplos)
Si le gusta programar en Linux y su trabajo gira en torno a los compiladores, hay un puñado de utilidades de línea de comandos que debe tener en cuenta. Una de esas herramientas es objdump. En este tutorial, discutiremos los conceptos básicos de este comando utilizando algunos ejemplos fáciles de entender.
Pero antes de hacerlo, vale la pena mencionar que todos los ejemplos aquí se probaron en una máquina con Ubuntu 20.04 LTS y en Debian 10.
Comando objdump de Linux
El comando objdump en Linux, como sugiere su nombre, muestra información de archivos de objetos. La siguiente es la sintaxis de la herramienta:
objdump OPTIONS objfile ...
Y esto es lo que dice la página del manual al respecto:
objdump displays information about one or more object files. The options control what particular information to display. This information is mostly useful to programmers who are working on the compilation tools, as opposed to programmers who just want their program to compile and work. objfile... are the object files to be examined. When you specify archives, objdump shows information on each of the member object files.
Los siguientes son algunos ejemplos de estilo de preguntas y respuestas que deberían darle una idea aún mejor de cómo funciona objdump.
Q1. ¿Cómo hacer que objdump muestre el contenido del encabezado del archivo?
Esto se puede hacer usando la opción de línea de comando -f.
Por ejemplo:
objdump -f /bin/ls
Y aquí está el resultado del comando anterior:
/bin/ls: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x00000000000067d0
Entonces puede ver que el contenido del encabezado de ‘ls’ se mostró en la salida.
Q2. ¿Cómo hacer que objdump muestre contenido de encabezado de archivo específico en formato de objeto?
Esto se puede hacer usando la opción de línea de comando -p. Por ejemplo, el siguiente comando:
objdump -p /bin/ls
Produjo la siguiente salida:
/bin/ls: file format elf64-x86-64 Program Header: PHDR off 0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3 filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r-x INTERP off 0x0000000000000238 vaddr 0x0000000000000238 paddr 0x0000000000000238 align 2**0 filesz 0x000000000000001c memsz 0x000000000000001c flags r-- LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21 filesz 0x000000000001e6e8 memsz 0x000000000001e6e8 flags r-x LOAD off 0x000000000001eff0 vaddr 0x000000000021eff0 paddr 0x000000000021eff0 align 2**21 filesz 0x0000000000001278 memsz 0x0000000000002570 flags rw- DYNAMIC off 0x000000000001fa38 vaddr 0x000000000021fa38 paddr 0x000000000021fa38 align 2**3 filesz 0x0000000000000200 memsz 0x0000000000000200 flags rw- NOTE off 0x0000000000000254 vaddr 0x0000000000000254 paddr 0x0000000000000254 align 2**2 filesz 0x0000000000000044 memsz 0x0000000000000044 flags r-- EH_FRAME off 0x000000000001b1a0 vaddr 0x000000000001b1a0 paddr 0x000000000001b1a0 align 2**2 filesz 0x0000000000000884 memsz 0x0000000000000884 flags r-- STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4 filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw- RELRO off 0x000000000001eff0 vaddr 0x000000000021eff0 paddr 0x000000000021eff0 align 2**0 filesz 0x0000000000001010 memsz 0x0000000000001010 flags r-- Dynamic Section: NEEDED libselinux.so.1 NEEDED libc.so.6 INIT 0x0000000000003758 FINI 0x000000000001636c INIT_ARRAY 0x000000000021eff0 INIT_ARRAYSZ 0x0000000000000008 FINI_ARRAY 0x000000000021eff8 FINI_ARRAYSZ 0x0000000000000008 GNU_HASH 0x0000000000000298 STRTAB 0x0000000000001180 SYMTAB 0x0000000000000388 STRSZ 0x0000000000000682 SYMENT 0x0000000000000018 DEBUG 0x0000000000000000 PLTGOT 0x000000000021fc38 PLTRELSZ 0x0000000000000a68 PLTREL 0x0000000000000007 JMPREL 0x0000000000002cf0 RELA 0x00000000000019a0 RELASZ 0x0000000000001350 RELAENT 0x0000000000000018 FLAGS 0x0000000000000008 FLAGS_1 0x0000000008000001 VERNEED 0x0000000000001930 VERNEEDNUM 0x0000000000000001 VERSYM 0x0000000000001802 RELACOUNT 0x00000000000000c1 Version References: required from libc.so.6: 0x06969194 0x00 07 GLIBC_2.14 0x0d696914 0x00 06 GLIBC_2.4 0x06969197 0x00 05 GLIBC_2.17 0x09691974 0x00 04 GLIBC_2.3.4 0x09691a75 0x00 03 GLIBC_2.2.5 0x0d696913 0x00 02 GLIBC_2.3
Q3. ¿Cómo hacer que objdump muestre el contenido de los encabezados de sección?
Esto se puede hacer usando la opción de línea de comando -h. Por ejemplo, el siguiente comando:
objdump -h /bin/ls
produjo el siguiente resultado en mi sistema:
/bin/ls: file format elf64-x86-64 Sections: Idx Name Size VMA LMA File off Algn 0 .interp 0000001c 0000000000000238 0000000000000238 00000238 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .note.ABI-tag 00000020 0000000000000254 0000000000000254 00000254 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .note.gnu.build-id 00000024 0000000000000274 0000000000000274 00000274 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .gnu.hash 000000ec 0000000000000298 0000000000000298 00000298 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .dynsym 00000df8 0000000000000388 0000000000000388 00000388 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .dynstr 00000682 0000000000001180 0000000000001180 00001180 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .gnu.version 0000012a 0000000000001802 0000000000001802 00001802 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .gnu.version_r 00000070 0000000000001930 0000000000001930 00001930 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 .rela.dyn 00001350 00000000000019a0 00000000000019a0 000019a0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 .rela.plt 00000a68 0000000000002cf0 0000000000002cf0 00002cf0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 10 .init 00000017 0000000000003758 0000000000003758 00003758 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 11 .plt 00000700 0000000000003770 0000000000003770 00003770 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 12 .plt.got 00000018 0000000000003e70 0000000000003e70 00003e70 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .text 000124d9 0000000000003e90 0000000000003e90 00003e90 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 14 .fini 00000009 000000000001636c 000000000001636c 0001636c 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 15 .rodata 00004e1d 0000000000016380 0000000000016380 00016380 2**5 CONTENTS, ALLOC, LOAD, READONLY, DATA 16 .eh_frame_hdr 00000884 000000000001b1a0 000000000001b1a0 0001b1a0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 17 .eh_frame 00002cc0 000000000001ba28 000000000001ba28 0001ba28 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 18 .init_array 00000008 000000000021eff0 000000000021eff0 0001eff0 2**3 CONTENTS, ALLOC, LOAD, DATA 19 .fini_array 00000008 000000000021eff8 000000000021eff8 0001eff8 2**3 CONTENTS, ALLOC, LOAD, DATA 20 .data.rel.ro 00000a38 000000000021f000 000000000021f000 0001f000 2**5 CONTENTS, ALLOC, LOAD, DATA 21 .dynamic 00000200 000000000021fa38 000000000021fa38 0001fa38 2**3 CONTENTS, ALLOC, LOAD, DATA 22 .got 000003c8 000000000021fc38 000000000021fc38 0001fc38 2**3 CONTENTS, ALLOC, LOAD, DATA 23 .data 00000268 0000000000220000 0000000000220000 00020000 2**5 CONTENTS, ALLOC, LOAD, DATA 24 .bss 000012e0 0000000000220280 0000000000220280 00020268 2**5 ALLOC 25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 00020268 2**2 CONTENTS, READONLY
Q4. ¿Cómo hacer que objdump muestre todos los encabezados?
Para hacer que objdump muestre todos los encabezados, use la opción de línea de comando -x.
objdump -x /bin/ls
El siguiente es el resultado que este comando produjo en mi sistema:
/bin/ls: file format elf64-x86-64 /bin/ls architecture: i386:x86-64, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x0000000000005850 Program Header: PHDR off 0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3 filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r-x INTERP off 0x0000000000000238 vaddr 0x0000000000000238 paddr 0x0000000000000238 align 2**0 filesz 0x000000000000001c memsz 0x000000000000001c flags r-- LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21 filesz 0x000000000001e6e8 memsz 0x000000000001e6e8 flags r-x LOAD off 0x000000000001eff0 vaddr 0x000000000021eff0 paddr 0x000000000021eff0 align 2**21 filesz 0x0000000000001278 memsz 0x0000000000002570 flags rw- DYNAMIC off 0x000000000001fa38 vaddr 0x000000000021fa38 paddr 0x000000000021fa38 align 2**3 filesz 0x0000000000000200 memsz 0x0000000000000200 flags rw- NOTE off 0x0000000000000254 vaddr 0x0000000000000254 paddr 0x0000000000000254 align 2**2 filesz 0x0000000000000044 memsz 0x0000000000000044 flags r-- EH_FRAME off 0x000000000001b1a0 vaddr 0x000000000001b1a0 paddr 0x000000000001b1a0 align 2**2 filesz 0x0000000000000884 memsz 0x0000000000000884 flags r-- STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4 filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw- RELRO off 0x000000000001eff0 vaddr 0x000000000021eff0 paddr 0x000000000021eff0 align 2**0 filesz 0x0000000000001010 memsz 0x0000000000001010 flags r-- Dynamic Section: NEEDED libselinux.so.1 NEEDED libc.so.6 INIT 0x0000000000003758 FINI 0x000000000001636c INIT_ARRAY 0x000000000021eff0 INIT_ARRAYSZ 0x0000000000000008 FINI_ARRAY 0x000000000021eff8 FINI_ARRAYSZ 0x0000000000000008 GNU_HASH 0x0000000000000298 STRTAB 0x0000000000001180 SYMTAB 0x0000000000000388 STRSZ 0x0000000000000682 SYMENT 0x0000000000000018 DEBUG 0x0000000000000000 PLTGOT 0x000000000021fc38 PLTRELSZ 0x0000000000000a68 PLTREL 0x0000000000000007 JMPREL 0x0000000000002cf0 RELA 0x00000000000019a0 RELASZ 0x0000000000001350 RELAENT 0x0000000000000018 FLAGS 0x0000000000000008 FLAGS_1 0x0000000008000001 VERNEED 0x0000000000001930 VERNEEDNUM 0x0000000000000001 VERSYM 0x0000000000001802 RELACOUNT 0x00000000000000c1 Version References: required from libc.so.6: 0x06969194 0x00 07 GLIBC_2.14 0x0d696914 0x00 06 GLIBC_2.4 0x06969197 0x00 05 GLIBC_2.17 0x09691974 0x00 04 GLIBC_2.3.4 0x09691a75 0x00 03 GLIBC_2.2.5 0x0d696913 0x00 02 GLIBC_2.3 Sections: Idx Name Size VMA LMA File off Algn 0 .interp 0000001c 0000000000000238 0000000000000238 00000238 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .note.ABI-tag 00000020 0000000000000254 0000000000000254 00000254 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .note.gnu.build-id 00000024 0000000000000274 0000000000000274 00000274 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .gnu.hash 000000ec 0000000000000298 0000000000000298 00000298 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .dynsym 00000df8 0000000000000388 0000000000000388 00000388 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .dynstr 00000682 0000000000001180 0000000000001180 00001180 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .gnu.version 0000012a 0000000000001802 0000000000001802 00001802 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .gnu.version_r 00000070 0000000000001930 0000000000001930 00001930 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 .rela.dyn 00001350 00000000000019a0 00000000000019a0 000019a0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 .rela.plt 00000a68 0000000000002cf0 0000000000002cf0 00002cf0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 10 .init 00000017 0000000000003758 0000000000003758 00003758 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 11 .plt 00000700 0000000000003770 0000000000003770 00003770 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 12 .plt.got 00000018 0000000000003e70 0000000000003e70 00003e70 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .text 000124d9 0000000000003e90 0000000000003e90 00003e90 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 14 .fini 00000009 000000000001636c 000000000001636c 0001636c 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 15 .rodata 00004e1d 0000000000016380 0000000000016380 00016380 2**5 CONTENTS, ALLOC, LOAD, READONLY, DATA 16 .eh_frame_hdr 00000884 000000000001b1a0 000000000001b1a0 0001b1a0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 17 .eh_frame 00002cc0 000000000001ba28 000000000001ba28 0001ba28 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 18 .init_array 00000008 000000000021eff0 000000000021eff0 0001eff0 2**3 CONTENTS, ALLOC, LOAD, DATA 19 .fini_array 00000008 000000000021eff8 000000000021eff8 0001eff8 2**3 CONTENTS, ALLOC, LOAD, DATA 20 .data.rel.ro 00000a38 000000000021f000 000000000021f000 0001f000 2**5 CONTENTS, ALLOC, LOAD, DATA 21 .dynamic 00000200 000000000021fa38 000000000021fa38 0001fa38 2**3 CONTENTS, ALLOC, LOAD, DATA 22 .got 000003c8 000000000021fc38 000000000021fc38 0001fc38 2**3 CONTENTS, ALLOC, LOAD, DATA 23 .data 00000268 0000000000220000 0000000000220000 00020000 2**5 CONTENTS, ALLOC, LOAD, DATA 24 .bss 000012e0 0000000000220280 0000000000220280 00020268 2**5 ALLOC 25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 00020268 2**2 CONTENTS, READONLY SYMBOL TABLE: no symbols
P5. ¿Cómo hacer que objdump muestre el contenido del ensamblador de las secciones ejecutables?
Para ello, utilice la opción de línea de comando -d. Aquí hay un ejemplo que muestra esta opción en acción:
objdump -d /bin/ls
Y aquí hay un extracto de la salida:
/bin/ls: file format elf64-x86-64 Disassembly of section .init: 0000000000003758 <[email protected]@Base>: 3758: 48 83 ec 08 sub $0x8,%rsp 375c: 48 8b 05 7d c8 21 00 mov 0x21c87d(%rip),%rax # 21ffe0 <__gmon_start__> 3763: 48 85 c0 test %rax,%rax 3766: 74 02 je 376a <[email protected]@Base+0x12> 3768: ff d0 callq *%rax 376a: 48 83 c4 08 add $0x8,%rsp 376e: c3 retq Disassembly of section .plt: 0000000000003770 <[email protected]>: 3770: ff 35 ca c4 21 00 pushq 0x21c4ca(%rip) # 21fc40 <[email protected]@Base+0x260> 3776: ff 25 cc c4 21 00 jmpq *0x21c4cc(%rip) # 21fc48 <[email protected]@Base+0x268> 377c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000003780 <[email protected]>: 3780: ff 25 ca c4 21 00 jmpq *0x21c4ca(%rip) # 21fc50 <[email protected]_2.3> 3786: 68 00 00 00 00 pushq $0x0 378b: e9 e0 ff ff ff jmpq 3770 <[email protected]@Base+0x18> 0000000000003790 <[email protected]>: 3790: ff 25 c2 c4 21 00 jmpq *0x21c4c2(%rip) # 21fc58 <[email protected]_2.2.5> 3796: 68 01 00 00 00 pushq $0x1 379b: e9 d0 ff ff ff jmpq 3770 <[email protected]@Base+0x18> 00000000000037a0 <[email protected]>: 37a0: ff 25 ba c4 21 00 jmpq *0x21c4ba(%rip) # 21fc60 <[email protected]_2.2.5> 37a6: 68 02 00 00 00 pushq $0x2
De manera similar, puede usar la opción de línea de comando -D para hacer que objdump muestre el contenido del ensamblador de todas las secciones, y la opción -S para asegurarse de que la herramienta mezcle el código fuente con el desensamblado.
P6. ¿Cómo hacer que objdump muestre información de depuración?
Esto puede hacerse posible usando la opción de línea de comandos -S.
objdump -g /bin/ls
El siguiente es un extracto de la salida producida por este comando:
Contents of the .eh_frame section (loaded from /bin/ls): 00000000 0000000000000014 00000000 CIE Version: 1 Augmentation: "zR" Code alignment factor: 1 Data alignment factor: -8 Return address column: 16 Augmentation data: 1b DW_CFA_def_cfa: r7 (rsp) ofs 8 DW_CFA_offset: r16 (rip) at cfa-8 DW_CFA_undefined: r16 (rip) 00000018 0000000000000014 0000001c FDE cie=00000000 pc=0000000000005850..000000000000587b DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop 00000030 0000000000000014 00000000 CIE Version: 1 Augmentation: "zR" Code alignment factor: 1 Data alignment factor: -8 Return address column: 16 Augmentation data: 1b DW_CFA_def_cfa: r7 (rsp) ofs 8 DW_CFA_offset: r16 (rip) at cfa-8
P7. ¿Cómo hacer que objdump muestre el contenido de la tabla de símbolos?
Esto se puede hacer usando la opción de línea de comando -t.
objdump -t /bin/ls
Conclusión
Acabamos de arañar la superficie aquí, ya que el comando objdump ofrece muchas opciones de línea de comandos. Una vez que haya terminado de practicar estos, puede obtener más información sobre la herramienta dirigiéndose a su página man.