내가 해결하기 위해 노력하고 재미 학업 문제의 상징 스텁 사용하려면, 내가 많이 Facebook's fishhook repo처럼, 실행시에 동적으로 문자를 리 바인드하려고 C 코드에서기능 개재, 마크 C의 기능은 항상 대신 직접 전화
을하는 기능 심볼을 다시 바인딩합니다. 나는 주로 Mach-O 실행 파일의 __DATA.__la_symbol_ptr
섹션에서 참조 된 심볼을 참고한다. fishhook 구현을 사용하면 대체 할 함수를 나타내는 문자열과 원래의 대체 된 함수를 호출 할 전역 함수 포인터를 제공합니다. 낚시의 환매 특약의 README에서 가져온 예를 들어
, ...
static int (*orig_close)(int);
int my_close(int fd) {
return orig_close(fd);
}
... 다음 main
rebind_symbols((struct rebinding[1]){{"close", my_close, (void *)&orig_close}}, 1);
이 굉장하지만 완전히 전환 할 수 원하는에서 모든 호출은 이고 모든 호출은 close
이고 그 반대의 경우는 내 모듈입니다. 예를 들어, 대신 원래 close
를 가리키는 전역 함수 포인터, I는 다음과 같이 내 구현을 원하는 것 :이 심볼이 동일한 모듈에서 참조되기 때문에
int my_close(int fd) {
return my_close(fd);
}
불행하게도,이 기호가 얻을 것이다 기호 스텁 대신 직접 호출을 통해 호출됩니다. main
0x100001e00 <+0>: push rbp
0x100001e01 <+1>: mov rbp, rsp
0x100001e04 <+4>: sub rsp, 0x20
0x100001e08 <+8>: xor eax, eax
0x100001e0a <+10>: mov dword ptr [rbp - 0x4], 0x0
0x100001e11 <+17>: mov dword ptr [rbp - 0x8], edi
0x100001e14 <+20>: mov qword ptr [rbp - 0x10], rsi
0x100001e18 <+24>: mov edi, eax
0x100001e1a <+26>: call 0x100001da0 ; my_close at main.m:42
0x100001e1f <+31>: xor edi, edi
0x100001e21 <+33>: mov dword ptr [rbp - 0x14], eax
0x100001e24 <+36>: mov eax, edi
0x100001e26 <+38>: add rsp, 0x20
0x100001e2a <+42>: pop rbp
0x100001e2b <+43>: ret
좋아, 충분히 쉬운 수정에서이 함수를 호출 할 때 다음 어셈블리가, 난 기능이 약한 표시 어셈블러 지시어를 사용하여 잠재적 인 스택 오버 플로우에 대해 컴파일러를 종료하기 위해 weakref를 사용할 수 있습니다. 에 my_close
을 변경하면 :
static int f(int) __attribute__ ((weakref ("my_close")));
__attribute__((weak))
int my_close(int fd) {
return f(fd);
}
다음 main
에서 다음 어셈블리를 생성합니다 :
0x100001df0 <+0>: push rbp
0x100001df1 <+1>: mov rbp, rsp
0x100001df4 <+4>: sub rsp, 0x20
0x100001df8 <+8>: xor eax, eax
0x100001dfa <+10>: mov dword ptr [rbp - 0x4], 0x0
0x100001e01 <+17>: mov dword ptr [rbp - 0x8], edi
0x100001e04 <+20>: mov qword ptr [rbp - 0x10], rsi
0x100001e08 <+24>: mov edi, eax
0x100001e0a <+26>: call 0x100001e5e ; symbol stub for: my_close
0x100001e0f <+31>: xor edi, edi
0x100001e11 <+33>: mov dword ptr [rbp - 0x14], eax
0x100001e14 <+36>: mov eax, edi
0x100001e16 <+38>: add rsp, 0x20
0x100001e1a <+42>: pop rbp
0x100001e1b <+43>: ret
그래서 나는 여기에 부착하고있는 부분 :
my_close
내부
my_close
를 참조 할 때, 항상 직접 호출을 초래한다. 예를 들어 : 여기
my_close
0x100001dd0 <+0>: push rbp
0x100001dd1 <+1>: mov rbp, rsp
0x100001dd4 <+4>: sub rsp, 0x10
0x100001dd8 <+8>: mov dword ptr [rbp - 0x4], edi
0x100001ddb <+11>: mov edi, dword ptr [rbp - 0x4]
0x100001dde <+14>: call 0x100001dd0 ; <+0> at main.m:44
0x100001de3 <+19>: add rsp, 0x10
0x100001de7 <+23>: pop rbp
0x100001de8 <+24>: ret
의 조립 내가 my_close
내에서 호출 될 때 그루터기로 취급 할 my_close
에게 (내가 놓친 것을)를 사용할 수있는 어셈블러 지시어가있다인가? 그래, 내가 원본을 얻을 수 dlsym
을 사용할 수 있습니다 알고 있지만, 내가 고집하고 있습니다 :]
그리고 다시 함수가 static으로 선언 될 필요가 있기 때문에 그 것을 한 번에 상관없이 작동하지 않을 수 있었던 것처럼 보인다'weakref''__attribute__'에서 찾고. 나는 그래도 질문을 떠날 것이다. –
그냥 생각 ... 전역 함수 포인터 형식으로'my_call' 선언 (어쩌면'volatile' 속성을 사용하여 원자와 정렬이되어 있는지 확인하는 것이 좋습니다), 심볼에 대한 모든 참조는 실제로 전역 변수 (어느 순간에 업데이트 할 수 있습니다) ....? – Myst
대체 경로는 https://stackoverflow.com/a/34120249/5329717 –