2009-09-11 12 views
8

Mam sondę DTrace przechwytującą połączenia do funkcji, a jednym z argumentów funkcji jest CFStringRef. Jest to struktura prywatna przechowująca wskaźnik do łańcucha unicode. Ale CFStringRef sam w sobie nie jest char*, więc zwykłe metody DTrace, takie jak copyinstr(), po prostu zwracają ?cp?, co nie jest dokładnie pomocne.Jak wydrukować CFStringRef w akcji DTrace?

Jak mogę wydrukować ciąg znaków w akcji DTrace?

Odpowiedz

12

O ile mi wiadomo, nie ma wbudowanej obsługi tego typu rzeczy. Zazwyczaj biblioteka publikuje sondę, która dekoduje ciąg znaków (jak wspomina Brad). Ponieważ w twoim przypadku nie możesz zmodyfikować biblioteki, musisz skorzystać z dostawcy pid i podłączyć się do funkcji użytkownika i sam ją odkodować.

Rozwiązanie (które jest bardzo podobne do podejścia, którego można użyć w C++ do zrzutu std::string) jest zrzucenie wskaźnika, który jest przechowywany z przesunięciem 2 słów od wskaźnika bazowego CFStringRef. Zauważ, że ponieważ CFString może przechowywać łańcuchy wewnętrznie w różnych formatach i reprezentacjach, może to ulec zmianie.

Biorąc trywialne zastosowanie testu:

#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; 
} 

Poniższy dtrace skrypt wypisze wartość ciągu pierwszego argumentu, zakładając, że jest to CFStringRef:

#!/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)); 

} 

a wyjście będzie coś na przykład:

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

Simply unco w zależności od tego, czy używasz 32-bitowego, czy 64-bitowego pliku binarnego. Przetestowałem to na obu architekturach na 10.6 i działa dobrze.

+0

Używając tego programu i tego pliku sondy, dostaję dużą listę tego: dtrace: błąd przy włączonym ID sondy 1 (ID 93815: pid11402: sc: mungeString: wpis): nieprawidłowy adres (0x7c8) w akcji # 5 w DIF przesunięcie 12 Zaciągnięcie linię, która drukuje ciąg, widzę, że wszyscy addrs smyczkowe są odrobinę nietypowe: Called mungeString: arg0 = 0x100001068 ciąg addr = 7c8 Dodawanie drugi, inny stały ciąg i mungeString'ing to, otrzymuję ten sam addr string dla obu ciągów. – TALlama

+0

Ok, z adresów pamięci mogę stwierdzić, że musisz używać wersji 10.6 i tworzyć aplikację 64-bitową. Napisałem aplikację testową (w pośpiechu!) Na 10.5, ponieważ było to wszystko, do czego miałem dostęp w tym czasie. Powinienem był użyć sizeof (intptr_t), aby przesunięcie w skrypcie DTrace było neutralne względem łuku (zamiast twardego kodu 8, który miałby teraz 16 w 64-bitowej aplikacji). Przyjrzę się maszynie 10.6. – gavinb

+0

@ TALlama Proszę wypróbować zaktualizowany skrypt powyżej. Przetestowałem to na 32-bitowych i 64-bitowych plikach binarnych i działa dobrze. – gavinb

1

Uważam, że nie można tego zrobić bezpośrednio, ale można utworzyć niestandardową sondę statyczną, która będzie podawana w CFString/NSString jako char *, którą można użyć z copyinstr(). Opisuję, jak to zrobić w artykule here.

+0

Niestety, próbuję użyć tego do sondowania skompilowanego kodu, nad którym nie mam kontroli, więc zmiana źródła nie jest możliwa. – TALlama