From 4c2b8d663b4c75d56649d658556da7f4bc3f9bf9 Mon Sep 17 00:00:00 2001 From: Blau Araujo Date: Sat, 26 Apr 2025 11:16:54 -0300 Subject: [PATCH] =?UTF-8?q?nova=20=C3=A1rvore=20de=20trabalho?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/01/.gdb_history | 30 ++++ mods/01/README.org | 389 +++++++++++++++++++++++++++++++++++++++++++ mods/01/demo.c | 14 ++ 3 files changed, 433 insertions(+) create mode 100644 mods/01/.gdb_history create mode 100644 mods/01/README.org create mode 100644 mods/01/demo.c diff --git a/mods/01/.gdb_history b/mods/01/.gdb_history new file mode 100644 index 0000000..1246d26 --- /dev/null +++ b/mods/01/.gdb_history @@ -0,0 +1,30 @@ +help help +h +help apropos +q +q +q +b main +r +c +r +help watch +watch resultado +l +watch z +c +help watch +b soma +watch resultado +c +c +i breakpoints +r +c +w resultado +watch resultado +r +c +c +i breakpoints +q diff --git a/mods/01/README.org b/mods/01/README.org new file mode 100644 index 0000000..c01ab31 --- /dev/null +++ b/mods/01/README.org @@ -0,0 +1,389 @@ +#+title: Curso prático de introdução ao GDB +#+author: Blau Araujo +#+email: blau@debxp.org + +* 1. Primeiro contato guiado + +** Objetivos + +- Entender o que é o GDB; +- Conhecer o conceito de /depuração/; +- Demonstrar o GDB em ação. + +** O que é o GDB + +O GDB (/GNU Debugger/) é uma ferramenta de depuração de programas escritos em +diversas linguagens. Ele possibilita a inspeção da execução de um programa +em tempo real ou após uma falha, fornecendo recursos como: + +- Pontos de parada (/breakpoints/); +- Execução passo a passo (/step-by-step/); +- Visualização e modificação de variáveis; +- Análise de memória e registradores; +- Inspeção da pilha de chamadas (/backtrace/); +- Avaliação de expressões em tempo de execução; +- Depuração de múltiplas /threads/; +- Depuração remota (via =gdbserver=). + +Por operar em baixo nível, o GDB oferece uma visão detalhada do comportamento +interno do programa, sendo essencial tanto para o desenvolvimento quanto para +o diagnóstico de erros complexos. + +** O que é depurar (/debugar/) + +Depuração (ou _/debugging/_) é o processo de identificar, analisar e corrigir +erros (/bugs/) em um programa ou sistema. Durante a depuração, o programador +examina o comportamento do código para entender onde e por que ele não funciona +como esperado. O objetivo é encontrar a origem dos problemas e corrigi-los, +até que o software opere corretamente. + +Sem o auxílio de ferramentas especializadas, a depuração pode ser feita, por +exemplo: + +- Com uma revisão cuidadosa do que está escrito no código-fonte; +- Inserindo a exibição de mensagens em pontos suspeitos do código para avaliar + variáveis (/"o valor está correto neste ponto?"/) e o próprio fluxo de execução + (/"o programa chegou a este ponto?"/); +- Com a análise manual de algoritmos, seguindo a execução do programa no código + tendo em mente alguns exemplos de entrada. + +Mas existem ferramentas (como o GDB) que auxiliam o processo de depuração que, +sem alterar diretamente o código, oferecem formas de: + +- Definir pontos de parada (/breakpoints/); +- Monitorar a alteração de valores em variáveis (/whatchpoints/); +- Executar o programa passo a passo; +- Examinar dados em endereços específicos da memória através de /símbolos/; +- Examinar o conteúdo da pilha de chamadas de sistema; +- Explorar informações sobre o processo do programa na memória... + +Entre várias outras possibilidades. + +Também existem ferramentas especializadas em aspectos e métodos específicos da +depuração, como... + +- *Valgrind:* para examinar a memória e detectar vazamentos e acessos inválidos. +- *Linters e analisadores:* para analisar como o código-fonte foi escrito e apontar + erros de sintaxe, de estilo e violações de especificações e convenções da linguagem + em uso sem, sequer, compilar (se for o caso) e executar o código. + +*** Uma nota sobre depuração preventiva + +Alguns /ambientes integrados de desenvolvimento/ (IDE) e editores de código +oferecem meios para sinalizar erros de sintaxe (a falta de um =;= em C, por +exemplo) ou destaques coloridos para diferentes tipos de elementos da +linguagem. Muitos deles integram-se com /protocolos de servidores de linguagem/ +(LSP) para funcionarem como /linters/ e analisadores de código em tempo +real (ou seja, durante a digitação do código), o que antecipa e ajuda a +evitar potenciais causas de erros. + +** Uma pequena demonstração + +Considere o seguinte programa em C (=demo.c=): + +#+begin_src c +#include + +int soma(int a, int b) { + int resultado = a + b; + return resultado; +} + +int main() { + int x = 10; + int y = 20; + int z = soma(x, y); + printf("Resultado: %d\n", z); + return 0; +} +#+end_src + +Compilação com símbolos de depuração: + +#+begin_example +gcc -g -o demo demo.c +#+end_example + +#+begin_quote +Sem os símbolos de depuração, nós teríamos que descobrir quais seriam os +endereços de dados em variáveis e de outros elementos do código para inspecionar +seus valores e comportamentos. +#+end_quote + +*** Iniciando o GDB para depuração + +O GDB pode ser iniciado de várias formas para depurar programas. A mais comum, +porém, é através da passagem do caminho de um binário executável como argumento +na sua invocação na linha de comandos. + +No nosso exemplo: + +#+begin_example +gdb ./demo +#+end_example + +Sem a opção =-q= (/quiet/) ou sem configurações de início, o GDB exibe informações +de versão e /copyright/ antes das mensagens relativas à depuração, propriamente +dita, e do prompt de seu shell de comandos... + +#+begin_example +:~$ gdb ./demo +GNU gdb (Debian 16.3-1) 16.3 +Copyright (C) 2024 Free Software Foundation, Inc. +License GPLv3+: GNU GPL version 3 or later +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. +Type "show copying" and "show warranty" for details. +This GDB was configured as "x86_64-linux-gnu". +Type "show configuration" for configuration details. +For bug reporting instructions, please see: +. +Find the GDB manual and other documentation resources online at: + . + +For help, type "help". +Type "apropos word" to search for commands related to "word"... +Reading symbols from ./demo... +(gdb) +#+end_example + +Apesar da poluição visual, essa mensagem padrão pode ser útil para iniciantes, +especialmente este trecho sobre ajuda: + +#+begin_example +For help, type "help". +Type "apropos word" to search for commands related to "word"... +#+end_example + +Ou seja... + +- Com o comando =help= (ou apenas =h=), nós teremos uma lista dos tópicos de + ajuda (classes de comandos) e as instruções de uso do próprio comando + =help=; +- Com o comando =apropos PALAVRA=, nós podemos buscar comandos que casem com + =PALAVRA=, que é interpretada como uma expressão regular (REGEX). + +*** Terminando o GDB + +Para sair do GDB, nós podemos teclar =Ctrl+D= ou executar =quit= (ou apenas =q=) no +prompt do shell de comandos: + +#+begin_example +(gdb) quit +#+end_example + +*** Omitindo a mensagem de início + +A forma mais simples de omitir a mensagem de início é utilizando a opção =-q= +na invocação do GDB: + +#+begin_example +:~$ gdb ./demo +Reading symbols from ./demo... +(gdb) +#+end_example + +Desta forma, a primeira mensagem relevante para a depuração é a única a ser +exibida antes do prompt: + +#+begin_example +Reading symbols from ./demo... +#+end_example + +Ela diz que o nosso binário foi compilado com símbolos para depuração e que +esses símbolos foram lidos e registrados. Mas, vamos sair e compilar novamente +o programa para ver o que aconteceria... + +#+begin_example +(gdb) q +:~$ gcc -o demo demo.c +:~$ gdb ./demo +Reading symbols from ./demo... +(No debugging symbols found in ./demo) +(gdb) +#+end_example + +Desta vez, sem os símbolos de depuração, nós tivemos a mensagem: + +#+begin_example +Reading symbols from ./demo... +(No debugging symbols found in ./demo) +#+end_example + +*** Uma nota sobre compilação com símbolos de depuração + +Normalmente, os projetos são compilados para duas finalidades: desenvolvimento +e publicação (/release/). É na compilação em desenvolvimento que os símbolos de +depuração podem ser úteis. Embora isso não cause prejuízos de desempenho, +binários compilados e publicados com símbolos de depuração resultam em arquivos +maiores e, dependendo do caso, podem expor informações internas sensíveis. + +Isso não costuma ser relevante no contexto do Software Livre, já que o acesso +aos fontes deve ser garantido, mas existem casos de programas escritos para +uso interno em alguma cadeia de produção que vão requerer mais cuidados. + +#+begin_quote +É possível compilar o código com os símbolos de depuração e, depois, removê-los +do binário que será distribuído(=strip -g=), ou ainda, gerar e armazenar +cópias dos símbolos em arquivos separados (=objcopy --only-keep-debug=), mas isso +foge do nosso escopo de interesses. +#+end_quote + +Sendo assim, vamos sair e compilar novamente o nosso programa com os +símbolos de depuração. + +#+begin_example +(gdb) q +:~$ gcc -g -o demo demo.c +:~$ gdb ./demo +Reading symbols from ./demo... +(gdb) +#+end_example + +*** Listando o código-fonte + +No GDB, podemos listar o código-fonte com o comando =list=: + +#+begin_example +(gdb) list +3 int soma(int a, int b) { +4 int resultado = a + b; +5 return resultado; +6 } +7 +8 int main() { +9 int x = 10; +10 int y = 20; +11 int z = soma(x, y); +12 printf("Resultado: %d\n", z); +#+end_example + +Por padrão, somente 10 linhas são exibidas, mas podemos teclar =Enter= algumas vezes +até que todo o código seja listado. + +#+begin_example +(gdb) +13 return 0; +14 } +#+end_example + +Chagando ao final, podemos reiniciar a listagem com =list .=: + +#+begin_example +(gdb) list . +3 int soma(int a, int b) { +4 int resultado = a + b; +5 return resultado; +6 } +7 +8 int main() { +9 int x = 10; +10 int y = 20; +11 int z = soma(x, y); +12 printf("Resultado: %d\n", z); +#+end_example + +*** Ponto de parada e execução + +Nós podemos definir pontos de parada com o comando =break=: + +#+begin_example +(gdb) break main +Breakpoint 1 at 0x115b: file demo.c, line 9. +#+end_example + +Assim, quando o programa for executado (com o comando =run=), a execução será +pausada nos símbolos definidos como pontos de parada: + +#+begin_example +(gdb) run +Starting program: /home/blau/tmp/gdb/demo +[Thread debugging using libthread_db enabled] +Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". + +Breakpoint 1, main () at demo.c:9 +9 int x = 10; +#+end_example + +Neste exemplo, o ponto de parada é a função =main=, e nós vemos a próxima linha +a ser executada (linha =9=). Para avançar para as próximas linhas, nós podemos +executar o comando =next=: + +#+begin_example +(gdb) next +10 int y = 20; +#+end_example + +A linha =9= foi executada e a próxima será a linha =10=. Se quisermos continuar +executando o comando =next=, basta teclar =Enter= imediatamente em seguida: + +#+begin_example +(gdb) +11 int z = soma(x, y); +#+end_example + +Neste ponto, as variáveis =x= e =y= já foram carregadas e nós podemos conferir +seus valores com o comando =print=: + +#+begin_example +(gdb) print x +$1 = 10 +(gdb) print y +$2 = 20 +#+end_example + +#+begin_quote +O resultado de cada avaliação é armazenado no GDB em uma variável especial +numerada (=$n=) de acordo com a ordem da avaliação. +#+end_quote + +A próxima linha a ser executada será a linha =11=, onde temos a chamada da +função =soma=. Se executarmos =next= novamente, a função será executada e nós +iremos para a linha seguinte na função =main=. Mas nós também podemos entrar +na função =soma= e acompanhar a sua execução passo a passo com o comando +=step=: + +#+begin_example +(gdb) step +soma (a=10, b=20) at demo.c:4 +4 int resultado = a + b; +#+end_example + +Aqui, nós podemos inspecionar os valores de =a=, =b= e do valor inicial de =resultado=, +antes da linha =4= ser executada: + +#+begin_example +(gdb) print a +$3 = 10 +(gdb) print b +$4 = 20 +(gdb) print resultado +$5 = 0 +#+end_example + +Com o comando =next=, nós avançamos na função e já podemos exibir o novo valor +de =resultado=: + +#+begin_example +(gdb) next +5 return resultado; +(gdb) print resultado +$6 = 30 +#+end_example + +Se, a partir daqui, nós quisermos executar todo o restante do programa, +basta executar comando =continue=: + +#+begin_example +(gdb) continue +Continuing. +Resultado: 30 +[Inferior 1 (process 214693) exited normally] +#+end_example + +Para sair do GDB... + +#+begin_example +(gdb) quit +:~$ +#+end_example diff --git a/mods/01/demo.c b/mods/01/demo.c new file mode 100644 index 0000000..319acfc --- /dev/null +++ b/mods/01/demo.c @@ -0,0 +1,14 @@ +#include + +int soma(int a, int b) { + int resultado = a + b; + return resultado; +} + +int main() { + int x = 10; + int y = 20; + int z = soma(x, y); + printf("Resultado: %d\n", z); + return 0; +}