Вопрос

У меня есть зонд DTrace, перехватывающий вызовы функции, и один из аргументов функции - это CFStringRef . Это частная структура, которая содержит указатель на строку Unicode. Но CFStringRef сам по себе не является char * , поэтому обычные методы DTrace, такие как copyinstr () , просто возвращают ? Cp? , что не совсем полезно.

Так как я могу распечатать строку в действии DTrace?

Это было полезно?

Решение

Насколько я знаю, для такого рода вещей нет встроенной поддержки. Обычно библиотека публикует зонд, который декодирует строку для вас (как упоминает Брэд). Так как в вашем случае вы не можете изменить библиотеку, вам нужно будет использовать провайдера pid , подключиться к пользовательской функции и декодировать ее самостоятельно.

Решение (которое очень похоже на подход, который вы бы использовали в C ++ для выгрузки std :: string ) состоит в том, чтобы выгрузить указатель, который хранится со смещением в 2 слова из базы указатель CFStringRef . Обратите внимание, что поскольку CFString может хранить строки внутри различных форматов и представлений, это может быть изменено.

Учитывая тривиальное тестовое приложение:

#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, и он отлично работает.

Другие советы

Я считаю, что вы не можете сделать это напрямую, но вы можете создать собственный статический пробник, который передает CFString / NSString как char *, который вы можете использовать с copyinstr (). Я описываю, как это сделать, в статье .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top