Как я печатаю CFStringRef в действии DTrace?

Моя команда разделяет версии файлов конфигурации для каждой среды (web.config.dev, web.config.test, web.config.prod). Наши сценарии развертывания копируют правильную версию, переименовывая его к web.config. Таким образом, мы имеем контроль полной версией на файлах конфигурации для каждой среды, может легко выполнить разность, и т.д.

8
задан TALlama 11 September 2009 в 22:58
поделиться

2 ответа

Насколько мне известно, нет встроенная поддержка такого рода вещей. Обычно библиотека публикует зонд, который декодирует строку за вас (как упоминает Брэд). Так как в вашем случае вы не можете изменить библиотеку, вам нужно будет использовать поставщика 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, и он отлично работает.

12
ответ дан 5 December 2019 в 13:00
поделиться

I believe that you can't do this directly, but you can create a custom static probe that feeds in the CFString / NSString as a char *, which you can use with copyinstr(). I describe how to do this in an article here.

1
ответ дан 5 December 2019 в 13:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: