R_X86_64_32S 및 R_X86_64_64 재배치란 무엇입니까?
64비트 FreeB에서 C 애플리케이션을 컴파일하려고 했을 때 다음 오류가 발생하였습니다.SD:
공유 개체를 만들 때 재배치 R_X86_64_32S를 사용할 수 없습니다. -fPIC로 다시 컴파일하십시오.
뭐가R_X86_64_32S
이전과 같은 것R_X86_64_64
?
에러에 대해 구글을 검색했습니다.원인이 있을 수 있습니다.R_X86_64_32S의 진의를 알 수 있으면 좋겠습니다.
이 중 하나를 이해하기 위해서는 먼저 다음을 수행해야 합니다.
- 재배치의 최소한의 예를 참조해 주세요.https://stackoverflow.com/a/30507725/895245
- ELF 파일의 기본 구조를 이해합니다.https://stackoverflow.com/a/30648229/895245
표준
R_X86_64_64
,R_X86_64_32
그리고.R_X86_64_32S
는 모두 시스템 V AMD ABI에 의해 정의되며, 여기에는 ELF 파일 형식의 AMD64 사양이 포함되어 있습니다.
이러한 값들은 모두 다음 값에서 사용할 수 있는 값입니다.ELF32_R_TYPE
재배치 엔트리의 필드(ELF 형식의 아키텍처 중립 부분을 지정하는 System V ABI 4.1(1997)에 규정되어 있습니다.이 표준은 필드만 지정하고 아치 종속 값은 지정하지 않습니다.
4.4.1 "Relocation Types" 아래에 요약 표가 표시됩니다.
Name Field Calculation
------------ ------ -----------
R_X86_64_64 word64 A + S
R_X86_64_32 word32 A + S
R_X86_64_32S word32 A + S
이 표는 나중에 설명하겠습니다.
그리고 메모:
그
R_X86_64_32
그리고.R_X86_64_32S
재배치에서는 계산된 값이 32비트로 잘립니다.링커는 R_X86_64_32(R_X86_64_32S) 재배치용으로 생성된 값이 원래 64비트 값으로 제로 확장(부호 확장)되는지 확인해야 합니다.
R_X86_64_64 및 R_X86_64_32의 예
먼저 알아봅시다R_X86_64_64
그리고.R_X86_64_32
:
.section .text
/* Both a and b contain the address of s. */
a: .long s
b: .quad s
s:
그 후, 다음과 같이 입력합니다.
as --64 -o main.o main.S
objdump -dzr main.o
내용:
0000000000000000 <a>:
0: 00 00 add %al,(%rax)
0: R_X86_64_32 .text+0xc
2: 00 00 add %al,(%rax)
0000000000000004 <b>:
4: 00 00 add %al,(%rax)
4: R_X86_64_64 .text+0xc
6: 00 00 add %al,(%rax)
8: 00 00 add %al,(%rax)
a: 00 00 add %al,(%rax)
Ubuntu 14.04, Binutils 2.24로 테스트 완료.
지금은 디스어셈블리를 무시하고(데이터이므로 의미가 없음) 라벨, 바이트 및 재배치만 확인합니다.
첫 번째 재배치:
0: R_X86_64_32 .text+0xc
즉, 다음과 같습니다.
0
: 바이트 0(라벨)에 따라 동작합니다.a
)R_X86_64_
: AMD64 시스템 V ABI의 모든 재배치 유형에 사용되는 프레픽스32
: 라벨의 64비트주소s
32비트 주소로 잘려나간 이유는.long
(4바이트).text
: 델은.text
부분0xc
: 재배치 엔트리의 필드인 추가입니다.
재배치 주소는 다음과 같이 계산됩니다.
A + S
장소:
A
: 추가, 여기0xC
S
: 이전 전 기호 값, 여기00 00 00 00 == 0
따라서 재배치 후 새 주소는 0xC == 12바이트가 됩니다..text
부분.
이게 바로 우리가 예상했던 거야s
다음에 오다.long
(4바이트) 및 a.quad
(8 바이트).
R_X86_64_64
여기서 주소를 잘라낼 필요가 없기 때문에 유사하지만 단순합니다.s
이는 표준에서 ~word64
대신word32
에서Field
기둥.
R_X86_64_32S와 R_X86_64_32의 비교
의 차이점R_X86_64_32S
대R_X86_64_32
링커가 "적합하도록 재배치가 잘려 있다"고 불만을 제기하는 경우:
32
: 재배치 후 잘린 값이 이전 값을 확장하지 않는 경우(잘린 바이트가 0이어야 함) 불만을 제기합니다.예:
FF FF FF FF 80 00 00 00
로.80 00 00 00
에 의해 불만이 발생합니다.FF FF FF FF
0이 아닙니다.32S
: 재배치 후 잘린 값이 이전 값을 확장하지 않으면 불만을 제기합니다.예:
FF FF FF FF 80 00 00 00
로.80 00 00 00
괜찮아요, 왜냐하면 마지막 부분인80 00 00 00
잘린 비트는 모두 1입니다.
다음 항목도 참조하십시오.이 GCC 오류 "..."에 맞게 재배치가 잘렸습니다." " " " " ? ?
R_X86_64_32S
다음 방법으로 생성할 수 있습니다.
.section .text
.global _start
_start:
mov s, %eax
s:
그 후, 다음과 같이 입력합니다.
as --64 -o main.o main.S
objdump -dzr main.o
제공 내용:
0000000000000000 <_start>:
0: 8b 04 25 00 00 00 00 mov 0x0,%eax
3: R_X86_64_32S .text+0x7
이제 다음 위치에 맞게 잘린 "재배치"를 관찰할 수 있습니다.32S
링커 스크립트 사용:
SECTIONS
{
. = 0xFFFFFFFF80000000;
.text :
{
*(*)
}
}
지금:
ld -Tlink.ld a.o
문제 없습니다.0xFFFFFFFF80000000
로 잘리다80000000
부호 확장자입니다.
단, 링커 스크립트를 다음과 같이 변경했을 경우:
. = 0xFFFF0FFF80000000;
이 시점에서 에러가 발생합니다.왜냐하면0
더 이상 신호 연장을 하지 않게 만들었죠
사용 이유32S
는, 「」를 참조해 주세요.32
즉시용:어셈블러가 R_X86_64_32와 같은 0 확장 대신 R_X86_64_32S와 같은 부호 확장 재배치를 사용하는 것이 좋은 때는 언제입니까?
R_X86_64_32S 및 PIE(위치에 의존하지 않는 실행 파일)
는 위치 파일(예: R_X86_64_32S)에서할 수 gcc -pie
그렇지 않으면 다음 링크에서 장애가 발생합니다.
relocation R_X86_64_32S against `.text' can not be used when making a PIE object; recompile with -fPIC
l
gcc 및 ld의 위치 독립 실행 파일에 대한 -fPIE 옵션은 무엇입니까?에서 설명하는 최소한의 예를 제시했습니다.
R_X86_64_32S
★★★★★★★★★★★★★★★★★」R_X86_64_64
는 amd64 아키텍처용으로 컴파일된 코드의 재배치 유형 이름입니다.모두 amd64 ABI에서 검색할 수 있습니다.그 말에 따르면R_X86_64_64
할 수 있습니다.
- R_X86_64 - 모든 이름 앞에 이 문자가 붙습니다.
- 64 - 64비트 직접 재배치
★★★★★★★★★★★★★★★★★」R_X86_64_32S
삭제:
- R_X86_64 - 프리픽스
- 32S - 값을 32비트로 잘라내고 부호 확장
이는 기본적으로 두 경우 모두 "이번 이전으로 지적된 심볼의 가치와 추가 사항"을 의미합니다.★★★의 R_X86_64_32S
링커는 생성된 값이 원래 64비트 값으로 시그널링되는지 확인합니다.
이제 실행 파일에서 코드 및 데이터 세그먼트에는 지정된 가상 기반 주소가 지정됩니다.실행 가능 코드는 공유되지 않으며 각 실행 가능 파일은 자체 새 주소 공간을 가집니다.즉, 컴파일러는 데이터 섹션의 위치를 정확히 알고 있으며 직접 참조할 수 있습니다.반면 라이브러리는 데이터 섹션이 기본 주소에서 지정된 오프셋에 있는 것만 알 수 있습니다. 기본 주소의 값은 실행 시에만 알 수 있습니다.따라서 모든 라이브러리는 메모리 내 어디에 있든 실행할 수 있는 코드(위치 독립 코드(또는 줄여서 PIC))를 사용하여 생성되어야 합니다.
이제 문제를 해결할 때 오류 메시지가 나타납니다.
, , 는, 는, 는을 사용하지 않고 한 것입니다.-fPIC
필요에 따라 플래그를 설정합니다.
gcc -shared foo.c -o libfoo.so # Wrong
전화하셔야 합니다.
gcc -shared -fPIC foo.c -o libfoo.so # Right
ELF 플랫폼(Linux)에서 공유 객체는 위치 독립 코드(메모리 내의 어느 위치에서나 실행할 수 있는 코드)로 컴파일됩니다.이 플래그를 지정하지 않으면 생성되는 코드는 위치에 따라 다르므로 이 공유 객체를 사용할 수 없습니다.
위의 답변은 이러한 재배치가 무엇인지 보여줍니다.GCC - mcmodel= large 플래그를 사용하여 x86_64 개체를 구축하면 이 모델에서는 컴파일러가 재배치된 주소에 대해 가정하지 않기 때문에 R_X86_64_32S를 방지할 수 있다는 것을 알게 되었습니다.
다음과 같은 경우:
extern int myarr[];
int test(int i)
{
return myarr[i];
}
gcc -O2 -fno-pie -c test_array.c
할 때는 분해해체해 주세요.objdump -drz test_array.o
하가있있 있있있다다
0: 48 63 ff movslq %edi,%rdi
3: 8b 04 bd 00 00 00 00 mov 0x0(,%rdi,4),%eax
6: R_X86_64_32S myarr
a: c3 ret
-mcmodel=large ,, -),gcc -mcmodel=large -O2 -fno-pie -c test_array.c
하가있있 있있있다다
0: 48 b8 00 00 00 00 00 movabs $0x0,%rax
7: 00 00 00
2: R_X86_64_64 myarr
a: 48 63 ff movslq %edi,%rdi
d: 8b 04 b8 mov (%rax,%rdi,4),%eax
10: c3 ret
나는 이 문제에 부딪혔는데 이 대답이 나에게 도움이 되지 않는다는 것을 알았다.정적 라이브러리를 공유 라이브러리와 연결하려고 했습니다.또, -fPIC 스위치를 커맨드 라인에 배치하는 것에 대해서도 조사했습니다(다른 회답에 기재되어 있습니다).이 문제를 해결한 유일한 방법은 정적 라이브러리를 공유로 변경하는 것이었습니다.fPIC 에 관한 에러 메세지는, 여러가지 원인으로 생각할 수 있습니다만, 기본적으로는 라이브러리가 어떻게 구축되고 있는지, 또 다른 방법으로 구축되고 있는지 의심해 보는 것이 좋습니다.
제 경우 컴파일할 프로그램이 리모트디렉토리에서 공유 라이브러리를 찾을 것으로 예상되어 문제가 발생했는데, 그 이유는 대응하는 정적 라이브러리만 실수로 존재했기 때문입니다.
사실 이 재배치 오류는 위장된 파일을 찾을 수 없는 오류입니다.
이 다른 스레드에는 어떻게 대처했는지 자세히 기재되어 있습니다.https://stackoverflow.com/a/42388145/5459638
언급URL : https://stackoverflow.com/questions/6093547/what-do-r-x86-64-32s-and-r-x86-64-64-relocation-mean
'programing' 카테고리의 다른 글
Vuetify 콤보 상자 항목 템플릿이 vuex로 업데이트되지 않음 (0) | 2022.07.04 |
---|---|
Vue 3 SSR 앱에서 라우터의 vuex 스토어를 사용하려면 어떻게 해야 합니까? (0) | 2022.07.04 |
Java: String 초기화 방법 [] (0) | 2022.07.04 |
Java에서 경로를 결합하는 방법 (0) | 2022.07.04 |
float가 정수인지 확인하는 중 (0) | 2022.07.03 |