2017-01-25 55 views
5

Próbuję wykonać odpowiedź na this thread, która niestety nie do końca rozwiązuje mój problem. Kod próbuję uruchomić to w następujący sposób:X86 64-bitowy montaż Linux "Hello World" linkujący numer

; File hello.asm 

     section .data 
msg: db  "Hello World!",0x0a,0 

     section .text 
     global main 
     extern printf 

main: 
     push rbp 
     mov rbp, rsp 
     lea rdi, [msg] ; parameter 1 for printf 
     xor eax, eax ; 0 floating point parameter 
     call printf 
     xor eax, eax ; returns 0 
     pop rbp 
     ret 

Mój system to debian odcinek:

$ uname -a 
Linux <host> 4.8.0-1-amd64 #1 SMP Debian 4.8.7-1 (2016-11-13) x86_64 GNU/Linux 

Używam yasm asembler następująco:

$ yasm -f elf64 -g dwarf2 hello.asm 

Ponieważ mój wpis punkt w powyższym źródle to main z ostateczną instrukcją ret, zgaduję, że muszę połączyć się z gcc zamiast ld -e main:

$ gcc -lc hello.o 

jednak otrzymuję następujący komunikat o błędzie:

/usr/bin/ld: hello.o: relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC 
/usr/bin/ld: final link failed: Nonrepresentable section on output 
collect2: error: ld returned 1 exit status 

Ten błąd wspomina coś o rekompilacji z -fPIC ale jest to ważna opcja w asemblerze yasm opcja gcc kompilator nie . Więc nie wiem, co robić tutaj.

Właśnie przez wzgląd na testach, starałem się połączyć z ld:

$ ld -e main -lc hello.o 

co jest skuteczne, ale uzyskać ten sam błąd, o którym mowa w powyższym wątku, gdy uruchomiony:

$ ./a.out 
bash: ./a.out: No such file or directory  # The file *is* there ... 

(po odpowiedzi na wątek, próbowałem porównać bibliotekę .so wspomnianą w pliku binarnym ld z biblioteką mojego systemu i oba są /lib64/ld-linux-x86-64.so.2.)

Próbowałem również zastąpić punkt wejścia main za pomocą _start (zapomniałem o problemie wyjścia z programu na razie) i połączyć z ld -lc hello.o, ale pojawia się ten sam błąd "Brak takiego pliku lub katalogu" jak wcześniej. Nadal będę się z tym bawił, ale myślałem, że też zapytam.

Każda sugestia pracy (z main lub _start, gcc lub ld) zostanie docenione ciepło.

EDIT: Jak sugeruje Jim Dodałem default rel na szczycie hello.asm i uzyskać inny komunikat o błędzie podczas łączenia z gcc (bez zmian ze ld -e main -lc)

$ gcc -lc hello.o 

/usr/bin/ld: hello.o: relocation R_X86_64_PC32 against symbol `[email protected]@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC 
/usr/bin/ld: final link failed: Bad value 
collect2: error: ld returned 1 exit status 

EDIT2: Ten post odnosi się do niepowodzenia: debian stretch:

Linux: 4.8.0-1-amd64 #1 SMP Debian 4.8.7-1 (2016-11-13) x86_64 GNU/Linux 
yasm: 1.3.0 
gcc: (Debian 6.2.1-5) 6.2.1 20161124 
ld: GNU ld (GNU Binutils for Debian) 2.27.51.20161220 

Następna ng na komentarzem Jima właśnie testowane ten sam kod nadebian jessiektóry działa perfekcyjnie z gcc -lc hello.o i następujących wersjach:

Linux: 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux 
yasm: 1.2.0 
gcc: (Debian 4.9.2-10) 4.9.2 
ld: GNU ld (GNU Binutils for Debian) 2.25 

EDIT 3: W oczekiwaniu na formalną odpowiedź od Michaela Petch: problem rozwiązany zgcc -static hello.o

+1

Twój kod faktycznie działa dla mnie (w innej dystrybucji). Twój problem wydaje się być związany z typem relokacji 'hello.o'. Sugerowałbym dodanie dyrektywy 'default rel' do początku' hello.asm' i zobaczenie, czy to działa lub daje inny błąd. Czy celowo używasz przeniesienia R_X86_64_32? –

+0

@ Jimd. bardzo ci dziękuje za pomoc. Zmodyfikowałem mój post, aby wskazać nowy komunikat o błędzie. –

+2

Co się stanie, jeśli kompilujesz statycznie za pomocą 'gcc -static hello.o' –

Odpowiedz

6

GCC w dystrybucji Debian defaults to building position independent executables, do budowania pliku wykonywalnego połączonego z konkretnym adresem, tak jak jest to tradycyjne hasło -no-pie do GCC.

Alternatywnie określić właściwy typ relokacji, nie wiem jak to zrobić w yasm.

+0

Cześć Tymoteusz, a 'gcc -static hello.o' zakończył się pomyślnie, polecenie łączenia' gcc -fno-pie hello.o' kończy się niepowodzeniem na mojej maszynie 'debian stretch'. czego mi brakuje? –

+0

Przepraszamy, to powinno być '-no-pie' podczas łączenia, kompilacja kontrolek' -fno-pie'. –

+0

Dziękuję Timothy, zarówno 'gcc -static hello.o' jak i' gcc -no-pie hello.o' działają doskonale! –