Por que o gdb está procurando por arquivos de montagem?

0

Estou tentando aprender sobre o gdb usando o Ubuntu 13.10. Eu estou usando o compilador gcc e o seguinte exemplo:

link

Em vez da saída mostrada no exemplo, recebo:

Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2_pminub () at ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S:38
38      ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S: No such file or directory.

Por que o depurador está procurando o que eu suponho ser um arquivo de origem de assembly, que eu aparentemente não instalei?

    
por Jason K 29.10.2013 / 23:26

3 respostas

1

Note que a página wiki diz que sua saída pode ser diferente. Você pode seguir a discussão sobre esse assunto exemplo que levou a que o aviso fosse adicionado à página do Wiki no LinuxQuestions.

Em geral, essas diferenças são baseadas em como coisas como libc (e talvez gdb ) são compiladas em sistemas diferentes. Note que o exemplo é executado no Fedora, não no Ubuntu; Portanto, o sistema básico pode ter algumas diferenças importantes em sua configuração.

Acho que esse é o principal motivo da diferença. De fato, eu corri o exemplo no Fedora e recebi uma saída que era mais ou menos idêntica à saída do exemplo.

O ponto principal é que a saída que você está recebendo é a saída normal para o Ubuntu. Eu tenho a mesma saída. Você pode emitir o comando bt a partir desse ponto e o próximo conjunto de saída será muito semelhante à saída no exemplo.

Então, por que o gdb está procurando por arquivos de montagem quando você está trabalhando em C? Bem, lembre-se de que é libc que está procurando o arquivo de montagem. O GDB está apenas relatando o que aconteceu.

E libc está procurando o arquivo de montagem essencialmente porque ele deve: partes da biblioteca são implementadas na montagem.

Eu não sou um guru no funcionamento interno da biblioteca ou conjunto padrão C, portanto, quero ter cuidado para não dizer algo incorreto.

Mas observe duas coisas sobre este exemplo:

  1. É sobre comprimento, que por definição entrará em definições dependentes do sistema.

    Se você olhar a mensagem, verá que, de fato, a biblioteca está lendo seu próprio diretório interno sysdeps , onde os diretórios dependentes do sistema são armazenados. Este diretório faz parte da biblioteca compilada e não faz parte do sistema de arquivos visível no computador.

    De acordo com a documentação da Biblioteca GNU C , essa estrutura é criada com base no resultado do utilitário configure , que determina como a biblioteca é compilada.

    Se você olhar para o código-fonte da libc, verá que strlen chama funções internas ocultas com base na arquitetura do sistema, que por sua vez chama outro assembly oculto interno e dependente do sistema strlen.S (eu conto 18 arquivos com esse nome, todos para archives diferentes), que por sua vez chama (ou pode chamar?) na função .S para diferentes processadores. Os sse e pminub estão relacionados aos detalhes do processador.

  2. E por que não está encontrando o arquivo? Eu imagino que não encontre porque não está lá. O binário compilado não o inclui (presumo) porque não é necessário neste sistema e configure não disse que deveria ser criado durante a compilação.

    O ponto aqui é que o exemplo está passando um NULL para uma função que espera uma string, o que é um grande erro. Ao contrário das linguagens de nível superior, o compilador não detecta isso. O resultado é um comportamento indefinido, então tudo pode acontecer.

    Meu palpite é que a biblioteca está tentando encontrar a versão da função que acha que faz mais sentido; mas como o NULL não tem sentido aqui, ele adivinha errado e procura uma versão que não está lá.

    De qualquer forma, ele falhará com um dump principal. Eu também acho que a biblioteca compilada para o Fedora não exibe exatamente o mesmo comportamento por causa de várias diferenças no sistema e porque qualquer comportamento é legal neste momento.

por chaskes 30.10.2013 / 00:44
1

Por que procura um arquivo de origem de montagem?

Como o código em questão é o código da biblioteca que está escrito em assembler, e as informações de depuração para ele fazem referência a esse arquivo. (Em particular, é uma das implementações strlen() otimizadas da [e] glibc para x86-64 (também conhecido como amd64 ).

Presumivelmente, o debuggee passou um argumento incorreto para strlen() , e isso causou falha. (Teoricamente, isso poderia ser um problema com a implementação de strlen() , mas é pouco provável que uma função tão fundamental tenha bugs, especialmente dada a popularidade de amd64 e o fato de que [e] glibc tem apenas 3 opções de strlen() nesse arco

Por que esse arquivo não está instalado?

Principalmente porque não é fácil conseguir que isso aconteça.

O que se segue é um resumo bastante técnico das questões envolvidas, e pode esperar muito conhecimento que você, de fato, não tem; Se você tiver dúvidas, você pode perguntar em # debian-mentors em OFTC .

Principais fatos:

  • O Ubuntu usa basicamente a mesma coleção de pacotes fonte do Debian, com um número relativamente pequeno de pacotes que não são retirados diretamente do Debian.

  • A maioria das informações de depuração do Ubuntu está em -dbgsym pacotes gerados automaticamente em dh_strip de tempo por pkg-create-dbgsym (que instala um wrapper em torno de dh_strip ). (Isso não acontece no Debian.) Isso funciona porque 99% dos pacotes usam dh_strip para remover seus binários.

  • Alguns pacotes-chave geram explicitamente seus próprios -dbg packages, principalmente para que eles estejam disponíveis no Debian, mas potencialmente também porque eles precisam instalar mais do que apenas informações DWARF separadas.

  • eglibc é um desses principais pacotes de fontes.

Devido à liberdade quase ilimitada que os pacotes fonte Debian têm em como eles podem construir, é decididamente não trivial para uma ferramenta de propósito geral identificar quais arquivos, exatamente, são os arquivos fonte relevantes que devem ser empacotados em um arquivo. pacote de debugging-source.

Você pode pensar que apenas descompactar o pacote fonte seria suficiente, mas isso não funcionaria muito bem com pacotes como gcc que na verdade contêm um tarball dentro de seu chamado .orig tarball, ou mesmo com pacotes que meramente use um sistema de correção mais complicado do que o que você obtém com o formato 3.0 (quilt) . (Outra coisa que estragaria tudo seria se o pacote upstream gerasse quaisquer fontes durante o build que não tivessem #line directives, ou se referissem a elas mesmas naquelas #line directives.)

No entanto, parece que os binários do contêm caminhos absolutos para todos os arquivos de origem, então se eles ainda estão intactos no momento em que podem ser embalado. Infelizmente, pareço ter alucinado os objcopy flags que permitiriam que você reescrevesse os caminhos de origem no DWARF para corresponder aos caminhos de instalação, portanto o GDB ainda não seria capaz de encontrá-los .

    
por SamB 27.11.2013 / 06:35
1

Encontrei a resposta em este site

Aqui está a versão curta

  1. No terminal, execute strace -o gdboutput.txt gdb example e passe pelo exemplo do wiki vinculado a

  2. Abra gdboutput.txt e procure o texto No such file or directory . Lá você encontrará um caminho para strlen-sse2-pminub.S

  3. Faça o download da biblioteca glibc mais recente usando sudo apt-get source glibc

  4. Procure strlen-sse2-pminub.S no diretório que você acabou de baixar usando find -iname strlen-sse2-pminub.S

  5. Mova o glibc para o local encontrado na etapa 2. talvez seja necessário criar o diretório. Ou você pode alterar onde o gdb procura esses arquivos (ainda não sei o suficiente para fazer isso)

Agora, executar o exemplo do gdb não retornará um erro de arquivo não encontrado. Mas ainda não me deu o resultado da wikipedia. Estou usando o Ubuntu. Funcionou em um cent-os, como mostrado na wikipedia.

Vou copiar a discussão completa abaixo caso o site seja desativado.

Depuração no Ubuntu 12.10 - arquivo ausente syscall-template.S NOTA: Há uma atualização na parte inferior desta postagem. Por favor, leia!

Após atualizar minha máquina de desenvolvimento para o Ubuntu 12.04, fiquei desapontado ao descobrir que a depuração parou de funcionar corretamente. Toda vez que eu tentei, recebi o erro:

Cannot find file ‘../sysdeps/unix/syscall-template.S’

Depois disso, nenhuma das depurações fez muito sentido (e os avisos repetidos estavam apenas atrapalhando).

A vida meio que atrapalhou e eu não desenvolvi nada de C por um bom tempo - tanto que a atualização de 12,10 veio antes mesmo de eu pensar nisso. Infelizmente, o problema não foi embora, então, depois de outro período de inatividade, estou corrigindo isso agora.

Descobri que o arquivo em questão está nas origens da libc6. Estes podem ser obtidos usando o seguinte comando:

sudo apt-get source libc6

Isso faz o download das fontes para o diretório atual. De volta ao depurador, e ele ainda não conseguiu encontrar os arquivos - não é realmente uma surpresa, mas eu não sabia onde colocá-los. Em desespero, corri contra o depurador (nemiver, neste caso) para ver onde estava procurando o nosso amigo. Isso é o que eu consegui:

stat(“/build/buildd/eglibc-2.15/misc/../sysdeps/unix/syscall-template.S”, 0x7fff0ba361f0) = -1 ENOENT (No such file or directory)
stat(“/home/test/../sysdeps/unix/syscall-template.S”, 0x7fff0ba361f0) = -1 ENOENT (No such file or directory)
stat(“/build/buildd/eglibc-2.15/misc/syscall-template.S”, 0x7fff0ba36200) = -1 ENOENT (No such file or directory)
stat(“/home/test/syscall-template.S”, 0x7fff0ba36200) = -1 ENOENT (No such file or directory)

Não sabendo o funcionamento interno dos depuradores, e querendo manter os arquivos visíveis para todos os usuários, decidi criar o diretório /build/buildd e colocar os fontes libc6 lá:

sudo mkdir -p /build/buildd
cd /build/buildd
sudo mv ~/eglic* .

Sucesso! Nemiver encontrou os arquivos e ficou feliz para sempre. E como o nemiver é um wrapper no gdb, verifiquei e confirmei que isso também é uma boa ideia, por isso, se você é uma daquelas pessoas malucas que conseguem entender o gdb *, isso funcionará para você.

A propósito, eu não tenho ideia se esse é o jeito "certo" de fazer esse tipo de coisa, e eu suspeito strongmente que não é. Mas funciona, então estou feliz. Se alguém souber o que eu deveria ter feito, serei todo ouvidos.

* Minha única experiência de depuração antes de aprender C foi a depuração Java, que é a melhor experiência de depuração que você pode ter. Depois disso, o gdb é um pesadelo assustador.

ATUALIZAÇÃO 6 de maio de 2014: Parece que os fontes libc6 estão disponíveis em versões mais recentes do Ubuntu como um pacote instalável. Você deve ser capaz de fazer apenas

sudo apt-get install eglibc-source

e tudo será instalado no lugar certo e ficará visível para o depurador.

Esta informação veio até mim da Adventures in Code.

    
por Sean Vonaffeunternehmen 21.08.2016 / 13:41

Tags