8

我有一个 DTrace 探针捕获对函数的调用,该函数的参数之一是CFStringRef. 这是一个私有结构,它包含一个指向 unicode 字符串的指针。但CFStringRef它本身不是 a char*,所以普通的 DTrace 方法,比如copyinstr()return ?cp?,这并不是很有帮助。

那么如何在 DTrace 操作中打印出字符串呢?

4

2 回答 2

13

据我所知,这种东西没有内置支持。通常一个库会发布一个为你解码字符串的探针(正如布拉德提到的)。因此,由于在您的情况下您无法修改库,因此您需要使用pid提供程序并挂钩到用户函数,然后自己对其进行解码。

解决方案(这与您在 C++ 中用于转储 a 的方法非常相似std::string)是转储存储在距基指针 2 个字偏移量处的CFStringRef指针。请注意,由于 aCFString可以在内部以各种格式和表示形式存储字符串,因此可能会发生变化。

给定简单的测试应用程序:

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

以下dtrace脚本将打印第一个参数的字符串值,假设它是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));

}

输出将类似于:

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

typedef根据您是针对 32 位还是 64 位二进制文​​件运行,只需取消对右侧的注释即可。我已经在 10.6 上针对这两种架构进行了测试,并且效果很好。

于 2009-09-22T04:31:54.900 回答
1

我相信您不能直接执行此操作,但您可以创建一个自定义静态探针,将 CFString / NSString 作为 char * 提供,您可以将其与 copyinstr() 一起使用。我在这里的一篇文章中描述了如何做到这一点。

于 2009-09-12T01:30:45.313 回答