2009-09-11 3 views
8

함수에 대한 호출을 catch하는 DTrace 프로브가 있는데이 함수의 인수 중 하나는 CFStringRef입니다. 이것은 유니 코드 문자열에 대한 포인터를 보유하는 개인 구조입니다. 그러나 CFStringRef은 자체가 char*이 아니므로 copyinstr()과 같은 일반적인 DTrace 메서드는 ?cp?을 반환합니다. 이는 정확히 도움이되지 않습니다.DTrace 액션에서 CFStringRef를 어떻게 인쇄합니까?

그렇다면 DTrace 작업에서 문자열을 어떻게 인쇄 할 수 있습니까?

답변

12

내가 아는 한, 이런 종류의 것에 대한 내장 지원은 없습니다. 일반적으로 라이브러리는 문자열을 해독하는 프로브를 게시합니다 (Brad 언급). 따라서 라이브러리를 수정할 수 없기 때문에 pid 공급자를 사용하여 사용자 함수에 연결하고 직접 디코딩해야합니다.

std::string을 덤프하기 위해 C++에서 사용하는 방법과 매우 비슷합니다.이 솔루션은 기본 CFStringRef 포인터에서 2 워드 오프셋으로 저장된 포인터를 덤프하는 것입니다. CFString은 문자열을 다양한 형식과 표현으로 내부적으로 저장할 수 있으므로 변경 될 수 있습니다. 사소한 테스트 응용 프로그램을 감안할 때

는 :

#!/usr/sbin/dtrace -s 

/* 
    Dumps a CFStringRef parameter to a function, 
    assuming MacRoman or ASCII encoding. 
    The C-style string is found at an offset of 
    2 words past the CFStringRef pointer. 
    This appears to work in 10.6 in 32- and 64-bit 
    binaries, but is an implementation detail that 
    is subject to change. 

    Written by Gavin Baker <gavinb.antonym.org> 
*/ 

#pragma D option quiet 

/* Uncomment for LP32 */ 
/* typedef long ptr_t; */ 
/* Uncomment for LP64 */ 
typedef long long ptr_t; 

pid$target::mungeString:entry 
{ 
    printf("Called mungeString:\n"); 
    printf("arg0 = 0x%p\n",arg0); 

    this->str = *(ptr_t*)copyin(arg0+2*sizeof(ptr_t), sizeof(ptr_t)); 
    printf("string addr = %p\n", this->str); 
    printf("string val = %s\n", copyinstr(this->str)); 

} 

그리고 출력이 될 것입니다 뭔가 :

#include <CoreFoundation/CoreFoundation.h> 

int mungeString(CFStringRef someString) 
{ 
    const char* str = CFStringGetCStringPtr(someString, kCFStringEncodingMacRoman); 
    if (str) 
     return strlen(str); 
    else 
     return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    CFStringRef data = CFSTR("My test data"); 

    printf("%u\n", mungeString(data)); 

    return 0; 
} 

첫 번째 인수의 문자열 값을 출력합니다 다음 dtrace 스크립트, 그것은 가정은 CFStringRef입니다 좋아요 :

$ sudo dtrace -s dump.d -c ./build/Debug/dtcftest 
12 
Called mungeString: 
arg0 = 0x2030 
string addr = 1fef 
string val = My test data 

단순히 unco 32 비트 또는 64 비트 바이너리 중 어느 것을 실행 중인지에 따라 오른쪽 typedef을 작성하십시오. 필자는 10.6에서이 두 아키텍처를 모두 테스트했으며 정상적으로 작동합니다.

+0

이 프로그램과이 프로브 파일을 사용하면 다음과 같은 큰 목록을 얻을 수 있습니다 : dtrace : 사용 된 프로브 ID 1 (ID 93815 : pid11402 : sc : mungeString : entry)의 오류 : 조치 # 5의 잘못된 주소 (0x7c8) 두 번째, 다른 상수 문자열을 추가 는 arg0 = 0x100001068 문자열 요지 = 7c8 : mungeString 호출 : DIF에서 나는 모든 문자열 addrs가이 특이한 약간 것을 볼, (12)는 문자열을 출력 라인을 촬영 오프셋 (offset) mungeString을 사용하면 두 문자열에 동일한 문자열 addr이 표시됩니다. – TALlama

+0

좋아요, 메모리 주소에서 10.6을 사용해야하고 64 비트 앱을 작성해야한다고 말할 수 있습니다. 내가 시험 응용 프로그램을 썼습니다 (서둘러!) 10.5에 그 당시에 내가 액세스 할 수있는 것이 전부였습니다. 필자는 DTrace 스크립트의 오프셋에 sizeof (intptr_t)를 사용하여 아치 - 중립 (64 비트 응용 프로그램에서 16이되는 하드 코드 8이 아니라)으로 사용해야했습니다. 나는 10.6 대의 기계를 살펴볼 것이다. – gavinb

+0

@ TALlama 위의 업데이트 된 스크립트를 사용해보십시오. 필자는 32 비트와 64 비트 바이너리 모두에서이를 테스트했으며 정상적으로 작동합니다. – gavinb

1

나는 이것을 직접 할 수는 없지만 copyinstr()과 함께 사용할 수있는 char *로 CFString/NSString을 피드하는 사용자 정의 정적 프로브를 만들 수 있다고 생각합니다. 이 기사의 내용은 here입니다.

+0

불행히도, 내가 제어 할 수없는 컴파일 된 코드를 탐색하기 위해이 코드를 사용하여 소스를 변경할 수 없습니다. – TALlama

관련 문제