Pregunta

Tengo una sonda DTrace que captura llamadas a una función, y uno de los argumentos de la función es un 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? , que no es exactamente útil.

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

¿Fue útil?

Solución

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

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

Dada 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 siguiente script dtrace imprimirá el valor de cadena del primer argumento, suponiendo que sea un 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 así como:

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

Simplemente descomente el typedef correcto, dependiendo de si está ejecutando contra un binario de 32 bits o de 64 bits. He probado esto en ambas arquitecturas en 10.6 y funciona bien.

Otros consejos

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top