Como usar ltrace para rastrear chamadas de biblioteca
Interessante em consertar aqueles erros de biblioteca e bugs que você observa ao instalar um novo programa legal no Linux? Confira este artigo que mostra como usar o ltrace, munindo você com a ferramenta necessária para depurar chamadas de biblioteca.
O que é uma biblioteca?
A maioria das pessoas está familiarizada com os arquivos . dll / . DLL (Dynamic Link Libraries) no Windows. O equivalente do Linux é um arquivo . so, um objeto compartilhado, geralmente referido apenas como biblioteca.
Uma biblioteca pode ser usada por um aplicativo, permitindo que esse programa utilize funcionalidades externas ao código do programa. Por exemplo, um servidor da web pode querer usar uma biblioteca de E / S de disco escrita pelo fornecedor do sistema operacional ou outro terceiro. É uma forma de compartilhar bens e interesses comuns na maioria dos sistemas operacionais, senão em todos.
As bibliotecas podem ser carregadas dinamicamente no tempo de execução (quando o programa de chamada está sendo iniciado, por exemplo) ou podem ser compiladas em um aplicativo / binário de destino. Eles serão, portanto, sempre carregados (usados ou não), como parte de e sempre que o aplicativo que os possui compilados / integrados for iniciado.
Para aprender mais sobre bibliotecas, suas dependências e a ferramenta ldd, você pode gostar de ler sobre como trabalhar com dependências de objetos compartilhados no Linux. A ferramenta ldd é outra ferramenta útil para ter em qualquer caixa de ferramentas de usuário Linux mais avançada.
o que é ltrace?
Existem vários utilitários de rastreamento no Linux, como o strace para rastrear chamadas e sinais do sistema e o traceroute para rastrear o roteamento da rede. O utilitário / ferramenta ltrace rastreia todas as chamadas de biblioteca.
Publicidade
Se você leu nosso trabalho com dependências de objetos compartilhados (biblioteca) no artigo do Linux (link acima), você já deve ter visto como pode descobrir a quais bibliotecas um binário específico está vinculado usando a ferramenta ldd. A finalidade e a funcionalidade do ltrace são um pouco diferentes; muito em linha com strace, o comando ltrace rastreia todas as chamadas de biblioteca que um programa específico está fazendo durante a execução.
Assim como strace, podemos iniciar um programa sob (pense nisso como uma hierarquia) ltrace. Simplesmente especificamos o programa que o ltrace deve iniciar como a primeira opção para o ltrace, e o ltrace iniciará esse programa para nós e começará imediatamente (em um nível superior) a rastrear todas as chamadas para qualquer biblioteca (sistema operacional ou instalado por terceiros).
Ele faz isso interceptando e gravando as chamadas dinâmicas da biblioteca feitas pelo programa em execução. Ele também rastreará quaisquer sinais enviados para o programa sendo executado, muito semelhante ao strace (e, se desejado, esta funcionalidade pode ser desabilitada especificando-se a opção -b ou equivalente --no-signs para ltrace).
Observe que o termo dinâmica é de grande importância aqui; O ltrace rastreará chamadas para bibliotecas externas (sob a forma de arquivos . so ou .a), ou seja, bibliotecas não compiladas diretamente em um programa; bibliotecas dinâmicas. Portanto, se você tiver um binário com bibliotecas estaticamente (compiladas), o ltrace não será capaz de ver / rastrear tais chamadas internas.
Instalando o ltrace
Para instalar o ltrace em sua distribuição Linux baseada em Debian / Apt (como Ubuntu e Mint), execute o seguinte comando em seu terminal:
sudo apt install ltrace
Publicidade
Para instalar o ltrace em sua distribuição Linux baseada em RedHat / Yum (como RHEL, Centos e Fedora), execute o seguinte comando em seu terminal:
sudo yum install ltrace
Usando ltrace
Vamos configurar um pequeno ambiente de teste:
sudo apt install tar xz-utils mkdir ~ / workspace & & cd ~ / espaço de trabalho toque a b c
Aqui nós instalamos tar e xz instalando xz-utils (você pode usar sudo yum install tar xz se estiver usando Centos / RHEL / Fedora). Em seguida, criamos um diretório ~ / workspace e entramos nele. Em seguida, criamos três arquivos vazios usando o comando touch, ou seja, os arquivos a, bec.
Vamos começar compactando nossos três arquivos em um arquivo (combinado com tar e compactado em xz) archive. tar. xz, enquanto executamos o mesmo no ltrace e observando a saída do ltrace:
ltrace tar -hcf --xz archive. tar. xz *
Vemos apenas uma pequena quantidade de saída. Podemos ver que nosso programa foi encerrado com sucesso (o arquivo foi criado), ou seja, status 0: um código de saída 0 sempre significa sucesso no Linux (embora o programa precise ter os códigos de saída implementados corretamente).
Isso não é muito útil até agora. Raciocinar por alguns segundos sobre como o tar funcionará aqui irá revelar rapidamente nossa próxima abordagem. O leitor ávido também pode ter entendido que o comando tar internamente chamaria o comando xz. A opção --xz passada para nossa linha de comando tar garantirá que o programa xz seja usado para compactação.
O processo secundário (ou o terceiro na hierarquia geral), a saber, xz (hierarquia: ltrace > tar > xz) será iniciado por tar quando necessário. Como tal, precisamos rastrear os processos filhos do programa em execução no ltrace, ou seja, tar. Podemos fazer isso especificando a opção follow (-f) para ltrace:
ltrace -f tar -hcf --xz archive. tar. xz *
Publicidade
Observe que é importante especificar a opção -f diretamente atrás do ltrace e não posteriormente na linha de comando após o tar, por exemplo. A razão é que queremos especificar esta opção para ltrace e não para o comando tar. Todas as opções após o comando tar são opções específicas do tar, enquanto -f é uma opção específica do ltrace.
A saída é um pouco mais interessante. Não observamos nenhuma chamada de biblioteca (de qualquer forma) ainda, mas pelo menos vemos que dois subprocessos são bifurcados (note exec ()) e que ambos os subprocessos terminam com status 0. Prático e bom.
Então, onde estão as chamadas da nossa biblioteca? Verificando tar e xz (os dois programas que serão usados pelo comando para criar o arquivo compactado) com ldd, percebemos rapidamente que a maioria das bibliotecas que ambos os programas usam são bibliotecas do sistema:
whereis tar whereis xz ldd / bin / tar ldd / usr / bin / xz
Devemos, portanto, dar um passo adiante e habilitar o rastreamento das chamadas da biblioteca do sistema especificando a opção -S para ltrace. Esta opção é desabilitada / desligada por padrão, pois a saída ficaria um pouco prolixa e é provável que as bibliotecas do sistema sejam geralmente muito mais estáveis e, como tal, não precisam ser rastreadas para começar. Vamos dar uma olhada.
ltrace -fS tar -hcf --xz archive. tar. xz *
Ou, para fins de teste:
ltrace -fS tar -hcf --xz archive. tar. xz * 2 > & 1 | head -n10 ltrace -fS tar -hcf --xz archive. tar. xz * 2 > & 1 | tail -n10
Como a saída foi substancial, tivemos que capturar a primeira e as últimas dez linhas usando um comando head and tail. Para poder usar esses comandos, tivemos que redirecionar stderr para stdout usando o redirecionamento 2 > & 1, pois o ltrace, por padrão, reportará em stderr. Se você estiver interessado em aprender mais sobre redirecionamento, consulte Bash Automation and Scripting Basics (Parte 3).
Publicidade
Agora que adicionamos a opção -S, podemos ver todas as bibliotecas acessadas. Por exemplo, vemos /etc/ld. so. preload sendo acessado. A saída é sequencial (de cima para baixo), então se houver outros eventos (subprocessamento sendo bifurcado, etc.) entre eles, eles serão mostrados em linha no momento em que ocorrerem. Também poderíamos adicionar a opção -t para saída baseada em tempo:
Concluindo
Neste artigo, apresentamos e discutimos o versátil programa ltrace, que é uma ótima ferramenta que permite rastrear todas as chamadas de biblioteca dinâmicas feitas por um determinado programa. Instalamos o ltrace, configuramos um ambiente de teste e executamos alguns comandos do ltrace com as opções mais comumente usadas.
Nenhum comentário