gdb-pratico/mods/03/README.org

110 lines
3.6 KiB
Org Mode
Raw Normal View History

2025-04-26 11:45:42 -03:00
#+title: Curso prático de introdução ao GDB
#+author: Blau Araujo
#+email: blau@debxp.org
* 3. Formato ELF
Todo arquivo executável pelo sistema é construído em um binário segundo um
formato padrão. No GNU/Linux, esse formato é o *ELF* (/Executable and Linkable Format/),
que inclui no binário:
- O código de máquina do programa;
- Dados de variáveis globais e estáticas;
- Dados constantes;
- Tabelas de símbolos;
- Informações de depuração (se incluídas).
Os primeiros bytes de um arquivo ELF contém um cabeçalho com diversas
informações sobre o binário, o que nós podemos listar com o utilitário
=readelf=:
#+begin_example
:~$ readelf -h demo
Cabeçalho ELF:
Magia: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Classe: ELF64
Dados: complemento 2, little endian
Versão: 1 (actual)
OS/ABI: UNIX - System V
Versão ABI: 0
Tipo: DYN (Position-Independent Executable file)
Máquina: Advanced Micro Devices X86-64
Versão: 0x1
Endereço do ponto de entrada: 0x1050
Início dos cabeçalhos do programa: 64 (bytes no ficheiro)
Start of section headers: 14944 (bytes no ficheiro)
Bandeiras: 0x0
Tamanho deste cabeçalho: 64 (bytes)
Tamanho dos cabeçalhos do programa:56 (bytes)
Nº de cabeçalhos do programa: 14
Tamanho dos cabeçalhos de secção: 64 (bytes)
Nº dos cabeçalhos de secção: 37
Índice de tabela de cadeias da secção: 36
#+end_example
2025-04-26 11:48:30 -03:00
** Símbolos no binário
2025-04-26 11:45:42 -03:00
Símbolos são nomes associados a elementos do programa, como funções e
variáveis. Quando os símbolos de depuração são incluídos no binário
(compilando com =-g=, por exemplo), o GDB é capaz de:
- Exibir nomes legíveis, em vez de endereços de memória;
- Acompanhar o fluxo do programa com o código-fonte;
- Receber definições de /breakpoints/ por nomes de funções;
- Fazer a associação de códigos binários com as linhas do código-fonte;
- Acessar nomes de variáveis, tipos, estruturas, etc.
Nós podemos verificar se o programa foi compilado com os símbolos de
depuração com o utilitário =file=...
Sem a opção =-g=:
#+begin_example
:~$ gcc -o demo demo.c
:~$ file demo
demo: ELF 64-bit LSB pie executable [...] not stripped
#+end_example
Com a opção =-g=:
#+begin_example
:~$ gcc -g -o demo demo.c
:~$ file demo
demo: ELF 64-bit LSB pie executable [...] with debug_info, not stripped
#+end_example
Repare que, desta vez, nós temos a informação =with debug_info= no final
da linha.
Nós também podemos verificar se há símbolos de depuração a partir das
informações no formato ELF:
#+begin_example
:~$ readelf -S demo | grep debug
[28] .debug_aranges PROGBITS 0000000000000000 00003037
[29] .debug_info PROGBITS 0000000000000000 00003067
[30] .debug_abbrev PROGBITS 0000000000000000 00003180
[31] .debug_line PROGBITS 0000000000000000 0000324a
[32] .debug_str PROGBITS 0000000000000000 000032ba
[33] .debug_line_str PROGBITS 0000000000000000 00003367
#+end_example
Mas o próprio GDB informa se há símbolos de depuração ao iniciar...
Sem a opção =-g=:
#+begin_example
:~$ gcc -o demo demo.c
:~$ gdb demo
Reading symbols from demo...
(No debugging symbols found in demo)
#+end_example
Com a opção =-g=:
#+begin_example
:~$ gcc -g -o demo demo.c
:~$ gdb demo
Reading symbols from demo...
#+end_example