Jump to content
Sign in to follow this  
Fabiano Furtado

"Segmentation fault" no "Hello World!"

Recommended Posts

Pessoal...

fiz um "Hello World!" em C para testes e estou tendo um "Segmentation fault". Vou reproduzir os passos que fiz.

Primeiramente, compilei com "gcc -Wall -O3 -save-temps hello.c -o hello". Até aí, tudo certo. Execução sem erros.

Como queria fazer a link edição "na mão", dei um "ldd hello" e...

        linux-vdso.so.1 (0x00007fffb3558000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007fc34bbc7000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fc34bde6000)

Após isso, link editei o arquivo com o comando "ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/libc.so.6  hello.o -o hello", recebi um "ld: warning: cannot find entry symbol _start; defaulting to 0000000000401020" e executei...

$ ./hello
Hello World!
Segmentation fault (core dumped)


Fiz um debug no GDB e no ret da main() o RIP apresenta um valor esquisito!

O que estou fazendo de errado nesta link edição?

Desde já, agradeço.

Share this post


Link to post
Share on other sites

Provavelmente seu GCC está instalado errado. Não consigo reproduzir o erro com o simples código de um "hello world":

#include <stdio.h>

int main( void ) { puts( "Hello, world!" ); }

Por que você está mantendo os arquivos temporários (-save-temps)?
 

PS: Que /usr/lib64/  é esse? Normalmente esse diretório não existe em distros Linux...

Share this post


Link to post
Share on other sites
Em 27/09/2019 em 12:36, fredericopissarra disse:

Provavelmente seu GCC está instalado errado. Não consigo reproduzir o erro com o simples código de um "hello world":


#include <stdio.h>

int main( void ) { puts( "Hello, world!" ); }

Por que você está mantendo os arquivos temporários (-save-temps)?
 

PS: Que /usr/lib64/  é esse? Normalmente esse diretório não existe em distros Linux...

Bom... o GCC não está instalado errado. Isso eu posso te garantir.

Eu uso o Arch Linux e nele há links simbólicos apontando para /lib64/ld-2.29.so e /usr/lib64/ld-2.29.so, que são arquivos idênticos.

Eu mantive os arquivos temporários para poder utilizar o hello.o no ld e usar o ld para fazer a link edição, e não o GCC.

Utilizando-se o GCC, o erro não ocorre, mas usando o ld, sim.

Share this post


Link to post
Share on other sites

Não há necessidade de usar -save-temps para compilar o fonte apenas para o objeto, basta fazer:

$ gcc -O3 -c -o hello.o hello.c   # Compila para o objeto hello.o

A opção -c faz isso. Quanto ao ld, qual a linha de comando você está usando? Note que código em C exige a linkagem de uma série de outros objetos (Scrt0.o, crti.o, crtn.o), bem como outras libs além da libc (libgcc, por exemplo). O GCC toma conta disso sozinho, o ld, não.

Veja algumas linhas de comando usadas pelo GCC adicionando a opção -v

Edited by fredericopissarra
  • Curtir 1

Share this post


Link to post
Share on other sites
16 horas atrás, fredericopissarra disse:

Não há necessidade de usar -save-temps para compilar o fonte apenas para o objeto, basta fazer:


$ gcc -O3 -c -o hello.o hello.c   # Compila para o objeto hello.o

A opção -c faz isso. Quanto ao ld, qual a linha de comando você está usando? Note que código em C exige a linkagem de uma série de outros objetos (Scrt0.o, crti.o, crtn.o), bem como outras libs além da libc (libgcc, por exemplo). O GCC toma conta disso sozinho, o ld, não.

Veja algumas linhas de comando usadas pelo GCC adicionando a opção -v

Oi Frederico... agora sim! Usando alguns parâmetros que a opção -v me mostrou, eu consegui fazer o hello world funcionar e entender o problema. Muito obrigado!

Share this post


Link to post
Share on other sites
Em 30/09/2019 em 11:51, Fernando Mercês disse:

Posta aí como, vai! :D

Fiquei curioso hehehehe

Opa...

Segue a linha...

$ ld --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o hello /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../.. -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crtn.o hello.o

  • l33t 1

Share this post


Link to post
Share on other sites
2 horas atrás, Fabiano Furtado disse:

Opa...

Segue a linha...

$ ld --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o hello /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../.. -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crtn.o hello.o

Algumas coisas podem ser retiradas... Eis um makefile para seu hello.c:
 

CFLAGS=-O2 -fno-stack-protector

# No meu caso, as libs do GCC 7 estão no diretório CRT_GCC_PATH.
# CRT de "C RunTime".
CRT_GCC_PATH=/usr/lib/gcc/x86_64-linux-gnu/7
CRT_PATH=/usr/lib/x86_64-linux-gnu/

# O linker precisa do plugin dynamic linker para linkar códigos do GCC (por quê executáveis no modo x86-64 são, essencialmente, shared
# objects que são carregados por esse "runtime");
#
# O executável precisa ser PIE (para o x86-64);
#
# Scrt1.o, crti.o, crtbeginS.o, crtendS.o e crtn.o precisam ser linkados junto com libgcc_s e libgcc, bem como a libc.
# Esses são os códigos de inicialização e finalização da libc (e builtins do GCC).
#
# O formato do elf é elf_x86_64 por default, assim a opção -m é desnecessária.
LDFLAGS=--dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -L$(CRT_GCC_PATH) -L$(CRT_PATH) -s
CRT_OBJECTS=$(CRT_PATH)/Scrt1.o $(CRT_PATH)/crti.o $(CRT_GCC_PATH)/crtbeginS.o $(CRT_GCC_PATH)/crtendS.o $(CRT_PATH)/crtn.o
LIBS=-lc -lgcc_s -lgcc

# Em essência isso faz a mesma coisa que `gcc -o hello hello.o`.
# Adicionei um exemplo onde apago a section .comment do binário final, diminuindo o tamanho um pouquinho...
hello: hello.o Makefile
	$(LD) $(LDFLAGS) -o $@.elf $(CRT_OBJECTS) $< $(LIBS)
	objcopy -R .comment $@.elf $@ && rm $@.elf

hello.o: hello.c

Como demonstração da alegação do executável ser um shared object:

$ make
cc -O2 -fno-stack-protector   -c -o hello.o hello.c
ld --dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/x86_64-linux-gnu/ -s -o hello.elf /usr/lib/x86_64-linux-gnu//Scrt1.o /usr/lib/x86_64-linux-gnu//crti.o /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o /usr/lib/x86_64-linux-gnu//crtn.o hello.o -lc -lgcc_s -lgcc
objcopy -R .comment hello.elf hello && rm hello.elf

$ ./hello
Hello

$ file hello
hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, stripped

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...