Domanda

Ho una sonda DTrace che rileva le chiamate a una funzione e uno degli argomenti della funzione è un CFStringRef . Questa è una struttura privata che contiene un puntatore a una stringa unicode. Ma CFStringRef non è esso stesso un char * , quindi i normali metodi DTrace come copyinstr () restituiscono semplicemente ? Cp? , che non è esattamente utile.

Quindi, come posso stampare la stringa nell'azione DTrace?

È stato utile?

Soluzione

Per quanto ne so, non esiste un supporto integrato per questo tipo di cose. Di solito una libreria pubblica un probe che decodifica la stringa per te (come menziona Brad). Quindi poiché nel tuo caso non puoi modificare la libreria, dovrai usare il provider pid e agganciarti a una funzione utente e decodificarla tu stesso.

La soluzione (che è molto simile all'approccio che useresti in C ++ per scaricare un std :: string ) è scaricare il puntatore che è memorizzato con un offset di 2 parole dalla base Puntatore CFStringRef . Si noti che poiché un CFString può memorizzare stringhe internamente in una varietà di formati e rappresentazioni, questo è soggetto a modifiche.

Data la banale applicazione di test:

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

Il seguente script dtrace stamperà il valore di stringa del primo argomento, supponendo che sia 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));

}

E l'output sarà simile a:

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

Rimuovi semplicemente il commento dal typedef corretto a seconda che tu stia eseguendo un binario a 32 o 64 bit. Ho provato questo su entrambe le architetture su 10.6 e funziona benissimo.

Altri suggerimenti

Credo che non sia possibile farlo direttamente, ma è possibile creare un probe statico personalizzato che alimenta CFString / NSString come carattere *, che è possibile utilizzare con copyinstr (). Descrivo come farlo in un articolo qui .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top