Frage

Ich habe eine DTrace Sonde Anrufe an eine Funktion zu kontrollieren, und eines der Argumente der Funktion ist ein CFStringRef. Dies ist ein Privat Struktur, die einen Zeiger auf einen Unicode-String enthält. Aber die CFStringRef ist nicht selbst ein char*, so normal DTrace Methoden wie copyinstr() nur zurückgeben ?cp?, was nicht gerade hilfreich ist.

Wie kann ich die Zeichenfolge in der DTrace Aktion ausdrucken?

War es hilfreich?

Lösung

Soweit ich weiß, ist es nicht eine integrierte Unterstützung für diese Art der Sache. Normalerweise wird eine Bibliothek würde veröffentlichen eine Sonde, die die Zeichenfolge für Sie dekodiert (als Brad erwähnt). So, da in Ihrem Fall können Sie die Bibliothek nicht ändern, müssen Sie den pid-Anbieter verwenden und in eine Benutzerfunktion Haken und entschlüsseln Sie es selbst.

Die Lösung (die der Ansatz sehr ähnlich ist, dass Sie in C ++ verwenden würde eine std::string Dump) ist der Zeiger auf auskippen, die in einem 2 Wort von der Basis CFStringRef Zeiger Offset gespeichert wird. Beachten Sie, dass da ein CFString Strings intern in einer Vielzahl von Formaten und Darstellungen speichern kann, dieses Thema ändern.

In Anbetracht der triviale Testanwendung:

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

Das folgende dtrace Skript wird den String-Wert des ersten Arguments drucken, vorausgesetzt, es ist ein CFStringRef ist:

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

}

Und wird der Ausgang so etwas wie:

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

Kommentar- einfach das passende typedef je nachdem, ob Sie laufen gegen einen 32-Bit- oder 64-Bit-Binär. Ich habe getestet dies gegen beide Architekturen auf 10,6 und es funktioniert gut.

Andere Tipps

Ich glaube, dass Sie dies nicht direkt tun können, aber man kann eine eigene statische Sonde erstellen, die in der CFString / NSString als char *-Feeds, die Sie mit copyinstr verwenden können (). Ich beschreibe, wie dies in einem Artikel zu tun, hier .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top