Apoiador Nibble Fabiano Furtado Postado Setembro 27, 2019 em 14:39 Apoiador Nibble Compartilhar Postado Setembro 27, 2019 em 14:39 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. Link para o comentário Compartilhar em outros sites More sharing options...
fredericopissarra Postado Setembro 27, 2019 em 15:36 Compartilhar Postado Setembro 27, 2019 em 15:36 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... Link para o comentário Compartilhar em outros sites More sharing options...
Apoiador Nibble Fabiano Furtado Postado Setembro 29, 2019 em 15:27 Autor Apoiador Nibble Compartilhar Postado Setembro 29, 2019 em 15:27 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. Link para o comentário Compartilhar em outros sites More sharing options...
fredericopissarra Postado Setembro 29, 2019 em 20:49 Compartilhar Postado Setembro 29, 2019 em 20:49 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 Link para o comentário Compartilhar em outros sites More sharing options...
Apoiador Nibble Fabiano Furtado Postado Setembro 30, 2019 em 13:08 Autor Apoiador Nibble Compartilhar Postado Setembro 30, 2019 em 13:08 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! Link para o comentário Compartilhar em outros sites More sharing options...
Administradores Fernando Mercês Postado Setembro 30, 2019 em 14:51 Administradores Compartilhar Postado Setembro 30, 2019 em 14:51 Posta aí como, vai! :D Fiquei curioso hehehehe Link para o comentário Compartilhar em outros sites More sharing options...
Apoiador Nibble Fabiano Furtado Postado Outubro 7, 2019 em 15:06 Autor Apoiador Nibble Compartilhar Postado Outubro 7, 2019 em 15:06 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 Link para o comentário Compartilhar em outros sites More sharing options...
Administradores Fernando Mercês Postado Outubro 7, 2019 em 15:49 Administradores Compartilhar Postado Outubro 7, 2019 em 15:49 CREDO! kkkkkk Hahahaha valeu por compartilhar. Essas respostas frutos de pesquisas são muito interessantes! ? Link para o comentário Compartilhar em outros sites More sharing options...
fredericopissarra Postado Outubro 7, 2019 em 17:48 Compartilhar Postado Outubro 7, 2019 em 17:48 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 Link para o comentário Compartilhar em outros sites More sharing options...
Apoiador Nibble Fabiano Furtado Postado Outubro 22, 2019 em 12:56 Autor Apoiador Nibble Compartilhar Postado Outubro 22, 2019 em 12:56 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. Link para o comentário Compartilhar em outros sites More sharing options...
fredericopissarra Postado Outubro 22, 2019 em 13:56 Compartilhar Postado Outubro 22, 2019 em 13:56 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)... Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados
Arquivado
Este tópico foi arquivado e está fechado para novas respostas.