Question

J'ai une sonde DTrace interceptant les appels d'une fonction et l'un des arguments de cette fonction est un CFStringRef . C'est une structure privée qui contient un pointeur sur une chaîne unicode. Mais CFStringRef n'est pas lui-même un char * , donc les méthodes DTrace normales telles que copyinstr () renvoient simplement ? Cp? , ce qui n’est pas vraiment utile.

Alors, comment puis-je imprimer la chaîne dans l'action DTrace?

Était-ce utile?

La solution

Autant que je sache, il n’existe pas de support intégré pour ce genre de chose. Habituellement, une bibliothèque publie une sonde qui décode la chaîne pour vous (comme le mentionne Brad). Donc, comme dans votre cas, vous ne pouvez pas modifier la bibliothèque, vous devez utiliser le fournisseur pid , vous connecter à une fonction utilisateur et la décoder vous-même.

La solution (qui est très similaire à l'approche que vous utiliseriez en C ++ pour vider un std :: string ) consiste à vider le pointeur qui est stocké à un décalage de 2 mots de la base. CFStringRef pointeur. Notez que, dans la mesure où CFString peut stocker des chaînes en interne dans divers formats et représentations, cela peut être modifié.

Étant donné l'application de test triviale:

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

Le script dtrace suivant affichera la valeur de chaîne du premier argument, en supposant qu'il s'agisse d'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));

}

Et le résultat sera quelque chose comme:

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

Supprimez simplement le commentaire typedef approprié selon que vous utilisez un fichier binaire 32 bits ou 64 bits. J'ai testé cela sur les deux architectures le 10.6 et cela fonctionne bien.

Autres conseils

Je pense que vous ne pouvez pas le faire directement, mais vous pouvez créer une sonde statique personnalisée qui se nourrit dans CFString / NSString en tant que char *, que vous pouvez utiliser avec copyinstr (). Je décris comment faire cela dans un article ici .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top