2017-09-08 6 views
1

이것은 이전에는 발생하지 않았던 문제입니다. 나는 아마 내 패키지 repos (아마 최근에 내 아치 시스템을 다시 설치하고 이것은 단지 일이 시작된)와 문제가 있다고 확신 해요. GCC로 어셈블하면 .data와 관련하여 이상한 재배치 오류가 발생합니다.

나는 x86_64에있는 작은 안녕하세요 세계를 썼다 :

.data 
str: .asciz "Test" 

.text 
.globl main 
main: 
    sub $8, %rsp 
    mov $str, %rdi 
    call puts 
    add $8, %rsp 
    ret 

을 한 후 나는 GCC를 사용하여 조립 및 링크를 시도 - 내가 과거에 여러 번했던 것처럼 -로, 단순히 :

gcc test.s -o test

하고는이 오류가 출력 :

/usr/bin/ld: /tmp/ccAKVV4D.o: relocation R_X86_64_32S 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

이 오류는 지금까지 나에게 발생하지 않았다. 나는 동일한 오류 메시지를 검색하여 문제를 해결하려고 시도했지만이 문제는 일반적인 문제로 생각할 수있는 반면 매우 구체적인 문제가 발생합니다. 나는 base-devel과 전체 GCC toolchain을 재설치하려고 시도했다. 나는 내가 뭘 할 수 있는지 모르겠다. (제발 nasm을 사용하지 말아라. 이단).

저는 분명히 뭔가를 놓치고 있다고 생각하고 싶습니다. 그러나 저는 오랫동안 제 어셈블리를 위해 GCC를 사용했습니다.

+0

필자는 일종의 복제본이지만 나중에 검색 할 예정이므로 잠깐 간략히 요약 해 보겠습니다. 데비안은 얼마 전에 64b 모드에서 PIC/PIE 바이너리로 전환했습니다 (OS X이 이미 오랜 시간 동안 했었던 것처럼 지금 다른 배포자도 따라갔습니다). 따라서 툴 체인의 기본값이 수정되었고 귀하의 경우에 gcc가 당신의 객체를 PIC로 연결하려하지만'mov $ str, % rdi'에서 절대 주소를 접하게 될 것입니다. 그래서 당신은 코드를 어디에서나 상대방에게'rip'되도록 재 작성해야합니다. 또는 실행 파일의 PIC가 아닌 연결을 강제하기 위해 gcc 연결을 설정하는 방법이있을 수 있습니다. – Ped7g

+0

Insight @ Ped7g에 감사드립니다. – oldjohn1994

+4

GCC에서 기본적으로 변경 가능한 64 비트 코드를 사용하는 최신/다른 버전의 아치 리눅스를 사용하고 계신 것 같습니다. 이를 처리하는 가장 좋은 방법은 RIP (instruction pointer relative) 주소 지정을 사용하도록 코드를 수정하는 것입니다. 'mov '를'lea str (% rip), % rdi'로 변경하고 _C_ 라이브러리를 호출 할 때'call puts' 대신'call puts @ plt'를 사용하십시오. –

답변

3

이 오류 주위에 얻을 수있는 방법은 no-pie (비 위치 독립적 인 실행) 실행 파일을 생성하는 것입니다 :

이 동작하는 이유는 다음과 같이 @ Ped7g에 의해 설명
gcc -no-pie test.s -o test 

:

데비안은 PIC로 전환/PIE 바이너리를 64 비트 모드로 사용 & 사례의 GCC가 개체를 PIC로 연결하려고 시도하지만 절대 주소가 mov $str, %rdi이됩니다.

+2

그는이 경우 Arch를 사용하고 있지만 Debian에도 동일하게 적용됩니다. 문자열의 주소가 유일한 문제는 아닙니다. _C_ 라이브러리에 대한 호출도 수정해야합니다. –

+0

@MichaelPetch :'-no-pie'는 모든 것을 고쳐주고'call puts'를'call puts @ plt'로 변환합니다. PIE에서 작동하게하려면'call' 명령어 만 수정하면됩니다. 특히,'gcc -fno-plt' (쓰기 가능 + 실행 가능 PLT를 회피하고 여분의 간접 참조를 피하기위한 비 지연 동적 링크) 또는'call puts @ PLT'를 사용하여 빌드 할 경우'call * puts @ GOTPCREL (% rip) 기본 방식으로. (또는'call puts @ plt'도 작동합니다. 컴파일러는 C를 컴파일 할 때 대문자 PLT를 내 보냅니다.) –