2009-09-11 14 views
8

Tengo una sonda DTrace atrapando llamadas a una función, y uno de los argumentos de la función es CFStringRef. Esta es una estructura privada que contiene un puntero a una cadena Unicode. Pero el CFStringRef no es en sí mismo un char*, por lo que los métodos normales de DTrace como copyinstr() simplemente devuelven ?cp?, lo cual no es exactamente útil.¿Cómo imprimo CFStringRef en una acción de DTrace?

Entonces, ¿cómo puedo imprimir la cadena en la acción DTrace?

Respuesta

12

Hasta donde yo sé, no hay soporte incorporado para este tipo de cosas. Por lo general, una biblioteca publicará una sonda que decodifica la cadena por usted (como lo menciona Brad). Entonces, como en su caso no puede modificar la biblioteca, necesitará usar el proveedor pid y enganchar en una función de usuario, y decodificarla usted mismo.

La solución (que es muy similar al enfoque que utilizaría en C++ para volcar un std::string) es volcar el puntero que está almacenado en un desplazamiento de 2 palabras desde el puntero CFStringRef base. Tenga en cuenta que dado que un CFString puede almacenar cadenas internamente en una variedad de formatos y representaciones, esto está sujeto a cambios.

Teniendo en cuenta la aplicación de prueba trivial:

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

El dtrace siguiente script imprimirá el valor de cadena del primer argumento, si se asume que es una 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)); 

} 

Y la salida será algo como:

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

Simply unco modifique el typedef derecho dependiendo de si se está ejecutando contra un binario de 32 bits o de 64 bits. He probado esto en ambas arquitecturas en 10.6 y funciona bien.

+0

Usando este programa y este archivo de prueba, acabo de obtener una gran lista de esto: dtrace: error en la sonda ID habilitada 1 (ID 93815: pid11402: sc: mungeString: entrada): dirección no válida (0x7c8) en la acción # 5 en DIF desplazamiento 12 Tomando la línea que imprime la cadena, veo que todos los addrs de cuerdas son un poco inusual: Llamado mungeString: arg0 = 0x100001068 cadena addr = 7C8 Adición de una segunda cadena diferente, constante y mungeString'ing, obtengo el mismo addr de cadena para ambas cadenas. – TALlama

+0

Ok, puedo decir por las direcciones de memoria que debe estar usando 10.6 y compilando una aplicación de 64 bits. Escribí la aplicación de prueba (¡con prisa!) En 10.5 ya que era todo lo que tenía acceso en ese momento. Debería haber usado sizeof (intptr_t) para que el desplazamiento en el script DTrace sea archi neutral (en lugar de hardcode 8, que ahora sería 16 en una aplicación de 64 bits). Echaré un vistazo a una máquina 10.6. – gavinb

+0

@TALlama Por favor intente el script actualizado arriba. Lo probé en binarios de 32 bits y de 64 bits y funciona bien. – gavinb

1

Creo que no puede hacer esto directamente, pero puede crear una sonda estática personalizada que alimente CFString/NSString como un char *, que puede usar con copyinstr(). Describo cómo hacer esto en un artículo here.

+0

Desafortunadamente, estoy tratando de usar esto para sondear un código compilado sobre el que no tengo control, por lo que no es posible cambiar el origen. – TALlama

Cuestiones relacionadas