2014-01-15 1 views
5

나는 일반적으로 0x400460에 엔트리 포인트를 갖기 위해 컴파일 한 사용자 프로그램이 있습니다.이 엔트리 포인트는 리눅스에로드 된 공유 라이브러리 중 2GB에서 시작하는 엔트리 포인트를 갖기 위해 재배치해야합니다. 예 : linux-vdso.so.1 => (0x00007fff109cd000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcd195e6000) /lib64/ld-linux-x86-64.so.2 (0x00007fcd199af000) x86_64 linux에서 2GB 이상의 프로그램을 재배치 할 때 링커 오류가 발생합니까?

.text 세그먼트의 시작 주소를 지정하려면 gcc 명령 줄 인수 -Wl,-Ttext=0x80000000을 사용하고 있습니다.

문제는 그 나는있는 링커 오류가 무엇입니까이 인수에 2GB 위의 주소를 제공하고 때 나는 거쳐 밖으로 만들 수있는만큼 지금까지 그 이유 :

gcc test.c -ggdb -Wl,-Ttext=0x80000000 -o test1 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 10 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 11 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 10 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 5 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 6 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 7 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 8 has invalid symbol index 2 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 9 has invalid symbol index 2 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 10 has invalid symbol index 11 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 12 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 20 has invalid symbol index 20 
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2 
/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': 
(.text+0x12): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_fini' defined in .text section in /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS) 
/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': 
(.text+0x19): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_init' defined in .text section in /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS) 
/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': 
(.text+0x20): relocation truncated to fit: R_X86_64_32S against symbol `main' defined in .text section in /tmp/ccFshK69.o 
/var/services/homes/adabral/elider/gc/a1/lib/gcc/x86_64-unknown-linux- gnu/4.8.2/crtbegin.o: In function `deregister_tm_clones': 
crtstuff.c:(.text+0x8): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table' 
/var/services/homes/adabral/elider/gc/a1/lib/gcc/x86_64-unknown-linux- gnu/4.8.2/crtbegin.o: In function `register_tm_clones': 
crtstuff.c:(.text+0x38): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table' 
collect2: error: ld returned 1 exit status 

을 몇 가지 SO 질문 및 포럼은 일부 섹션이 여전히 주소가 낮은 2GB으로 매핑 될 수 있습니다.

텍스트 세그먼트가 2GB (0x79990000) 바로 아래에 컴파일 된 바이너리의 경우 readelf -a의 결과입니다.

Dynamic section at offset 0x190310 contains 24 entries: 
Tag  Type       Name/Value 
0x0000000000000001 (NEEDED)    Shared library: [libc.so.6] 
0x000000000000000c (INIT)    0x4003f0 
0x000000000000000d (FINI)    0x79990204 
0x0000000000000019 (INIT_ARRAY)   0x79b902f8 
0x000000000000001b (INIT_ARRAYSZ)  8 (bytes) 
0x000000000000001a (FINI_ARRAY)   0x79b90300 
0x000000000000001c (FINI_ARRAYSZ)  8 (bytes) 
0x0000000000000004 (HASH)    0x400278 
0x0000000000000005 (STRTAB)    0x400318 
0x0000000000000006 (SYMTAB)    0x4002a0 
0x000000000000000a (STRSZ)    72 (bytes) 
0x000000000000000b (SYMENT)    24 (bytes) 
0x0000000000000015 (DEBUG)    0x0 
0x0000000000000003 (PLTGOT)    0x79b904e8 
0x0000000000000002 (PLTRELSZ)   72 (bytes) 
0x0000000000000014 (PLTREL)    RELA 
0x0000000000000017 (JMPREL)    0x4003a8 
0x0000000000000007 (RELA)    0x400390 
0x0000000000000008 (RELASZ)    24 (bytes) 
0x0000000000000009 (RELAENT)   24 (bytes) 
0x000000006ffffffe (VERNEED)   0x400370 
0x000000006fffffff (VERNEEDNUM)   1 
0x000000006ffffff0 (VERSYM)    0x400360 
0x0000000000000000 (NULL)    0x0 

당신은 INIT 및 일부 다른 부분은 여전히 ​​낮은 2GB 주소 공간에서 시작 것을 볼 수 있습니다. 따라서 동적 링커는 재배치 유형이 R_X86_64_32이므로 런타임에 재배치 주소를 오프셋 할 수 없습니다.

  • 그래서 gcc -mcmodel=large 플래그로 코드를 컴파일했지만 동일한 링커 오류가 발생했습니다. large 모델을 사용하면이 오류를 수정해야하지만 그렇지 않습니다.

  • 나는이 시점에서 붙어있어, 어떤 도움을 주시면 감사하겠습니다.

감사

+0

"Linux에로드 된 공유 라이브러리의 2GB 이내에서 시작하는 엔트리 포인트를 가져야합니다."- 예를 들어 공유 라이브러리가로드 될 것으로 예상되는 위치에 * 절대적으로 * 보장 할 수는 없습니다. 'echo 1>/proc/sys/vm/legacy_va_layout' 이후에로드 주소가 크게 바뀔 것으로 기대하십시오). 게다가 왜 공유 라이브러리의 2GB 이내에 있어야할까요? –

+0

@EmployedRussian 저는 이것을 요구하는 일부 학술 프로젝트에 참여하고 있습니다. – abhi

답변

6

먼저 x86_64에 대한 ABI가 여러 가지 "모델"을 가지고 있음을 이해해야한다 (내가 x86_64에 우분투 기계 GCC의 버전? 4.8.2 작업입니다.) : 작은, 커널, 매체, 큰. 이들은 여기에 GCC -mcmodel 옵션에 설명되어 있습니다 : http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html

당신이 겪고있는 것은 그 crt1.o, 초기 ELF 레지스터/스택 상태를 복용하고 libc의로 전달에 대한 책임이 모든 프로그램에 링크됩니다 시작 코드 결국 main을 호출하는 시작 코드는 작은 모델을 사용하고있는 것 같습니다. 당신은 여기에서 볼 수 있습니다 : 무슨 일이에요

/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': 
(.text+0x20): relocation truncated to fit: R_X86_64_32S against symbol `main' defined in .text section in /tmp/ccFshK69.o 

crt1.o 32 비트 주소를 기입 할 경우에만 허용 main의 주소에 대한 재배치를 가지고 있다는 것입니다 (참고 :. main이 공유에 정의 된 경우에도 라이브러리가 아니라 실행 파일에 PLT 항목이 있고이 PLT 항목의 주소는 재배치가 해결 될 main의 공식 주소가됩니다.

이 문제를 해결하려면 전체 64 비트 주소를 처리 할 수있는 crt1.o이 필요합니다. 이를 얻는 한 가지 방법은 일반적으로 crt1.o 대신에 PIE 실행 파일에만 사용되는 Scrt1.o을 사용하는 것입니다.-nostartfiles으로이 작업을 수행하고 링크 명령 행에서 모든 시작 파일을 수동으로 지정할 수 있습니다. glibc에 대한 버그 보고서를 제출하여 x86_64 crt1.o을 "대형 모델"로 변환하여 32 비트 범위에서 링크되지 않은 주 프로그램과 함께 작동하도록 요청하는 것이 좋습니다.

높은 주소에서 올바르게 링크하고 작동하게하려면 모든 코드에 대해 -mcmodel=large (또는 아마도 -fPIE)이 필요합니다. 이것은 상당히 크고 느려질 수 있습니다. 당신은 왜 이것을하고 있는지, 그리고 정말로해야하는지 다시 생각해 볼 수 있습니다.

+0

답변 해 주셔서 감사합니다. 다른 방법으로도 할 수 있습니까? 예를 들어, libc.so와 같은 공유 라이브러리가 작은 모델을 사용하는 동안 초기 2Gb 주소 공간에로드되도록 할 수 있습니까? 다시 한 번 감사합니다 – abhi

+0

쉽지 않습니다. 동기 부여 란 무엇입니까? 나는 당신이 필요로하는 것에 따라 대안적인 해결책을 가지고 있을지도 모른다. –

+0

실제로 다른 방법으로 공유 라이브러리 함수에 액세스하려고하고 있습니다 (PLT 및 GOT 테이블을 통한 간접 참조 사용). – abhi