Nibble Supporter Fabiano Furtado Posted September 27, 2019 Nibble Supporter Share Posted September 27, 2019 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. Quote Link to comment Share on other sites More sharing options...
fredericopissarra Posted September 27, 2019 Share Posted September 27, 2019 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... Quote Link to comment Share on other sites More sharing options...
Nibble Supporter Fabiano Furtado Posted September 29, 2019 Author Nibble Supporter Share Posted September 29, 2019 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. Quote Link to comment Share on other sites More sharing options...
fredericopissarra Posted September 29, 2019 Share Posted September 29, 2019 (edited) 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 September 29, 2019 by fredericopissarra 1 Quote Link to comment Share on other sites More sharing options...
Nibble Supporter Fabiano Furtado Posted September 30, 2019 Author Nibble Supporter Share Posted September 30, 2019 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! Quote Link to comment Share on other sites More sharing options...
Administrators Fernando Mercês Posted September 30, 2019 Administrators Share Posted September 30, 2019 Posta aí como, vai! :D Fiquei curioso hehehehe Quote Link to comment Share on other sites More sharing options...
Nibble Supporter Fabiano Furtado Posted October 7, 2019 Author Nibble Supporter Share Posted October 7, 2019 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 1 Quote Link to comment Share on other sites More sharing options...
Administrators Fernando Mercês Posted October 7, 2019 Administrators Share Posted October 7, 2019 CREDO! kkkkkk Hahahaha valeu por compartilhar. Essas respostas frutos de pesquisas são muito interessantes! ? Quote Link to comment Share on other sites More sharing options...
fredericopissarra Posted October 7, 2019 Share Posted October 7, 2019 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 1 Quote Link to comment Share on other sites More sharing options...
Nibble Supporter Fabiano Furtado Posted October 22, 2019 Author Nibble Supporter Share Posted October 22, 2019 (edited) Em 07/10/2019 em 14:48, fredericopissarra disse: Algumas coisas podem ser retiradas... Eis um makefile para seu hello.c: ..... Como demonstração da alegação do executável ser um shared object: ..... Cara... vc é o mestre!!!! Achei muito legal esse make! Depois vou testar... Em tempo, já que vc usou o objcopy para diminuir o tamanho do binário (aliás, achei bem legal isso), reparei que os meus binários estavam ficando MUITO grandes (mesmo os mais simples) e descobri o motivo. A partir da versão 2.30 (ou 2.31.. não sei ao certo) do LD, há um novo parâmetro para fazer a link edição chamado "-z noseparate-code". O default passa a ser "-z separate-code" e isso faz com que o linker preencha o binário com vários Null Bytes entre as seções. Eu li sobre esse parâmetro e o motivo da existência seria uma maior segurança contra ataques, em prol de um binário maior e relativamente mais lento. Você sabe me dizer mais sobre o uso desse parâmetro? Eu particularmente prefiro um binário menor. Edited October 22, 2019 by Fabiano Furtado Quote Link to comment Share on other sites More sharing options...
fredericopissarra Posted October 22, 2019 Share Posted October 22, 2019 53 minutos atrás, Fabiano Furtado disse: A partir da versão 2.30 (ou 2.31.. não sei ao certo) do LD, há um novo parâmetro para fazer a link edição chamado "-z noseparate-code". O default passa a ser "-z separate-code" e isso faz com que o linker preencha o binário com vários Null Bytes entre as seções. Eu li sobre esse parâmetro e o motivo da existência seria uma maior segurança contra ataques, em prol de um binário maior e relativamente mais lento. Você sabe me dizer mais sobre o uso desse parâmetro? Eu particularmente prefiro um binário menor. Pelo que vi, isso garante que a página onde a sessão de código (.text e outras semelhantes) seja carregadas será isolada das páginas de dados e pilha. Isso permite o uso do bit NX na tabela de página, protegendo o código e evitando que você crie um "shell code"... Quanto ao preenchimento, provavelmente isso não tem nenhum problema, já que, mesmo que a imagem binária seja pequena, o mínimo que será alocado na memória será algumas páginas de 4 KiB (pelo menos algumas para código: SEU código + códigos de inicialização da libc como todos aqueles ?crt*.o; algumas para dados (acho que a libc aloca, pelo menos 128 KiB; e pelo menos uma para a pilha)... 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.