Pergunta

Eu tenho um teste do DTrace captura chamadas para uma função, e um dos argumentos da função é uma CFStringRef. Esta é a estrutura privada que contém um ponteiro para uma seqüência de caracteres Unicode. Mas o CFStringRef não é em si uma char*, então métodos normais do DTrace como copyinstr() apenas ?cp? retornar, o que não é exatamente útil.

Então, como posso imprimir a cadeia na ação DTrace?

Foi útil?

Solução

Tanto quanto eu sei, não há suporte embutido para este tipo de coisa. Normalmente uma biblioteca iria publicar uma sonda que decodifica a string para você (como Brad menciona). Então, já que no seu caso, você não pode modificar a biblioteca, você vai precisar usar o provedor pid e gancho em uma função de usuário, e decodificá-lo a si mesmo.

A solução (que é muito semelhante à abordagem que você usaria em C ++ para despejar um std::string) é para despejar o ponteiro que é armazenado em um deslocamento do ponteiro de base CFStringRef 2 palavra. Note-se que uma vez que um CFString pode armazenar seqüências internamente em uma variedade de formatos e representações, esta é sujeita a alterações.

Dada a aplicação de teste trivial:

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

O script a seguir dtrace irá imprimir o valor da cadeia do primeiro argumento, supondo que ele é um 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));

}

E a saída será algo como:

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

Simplesmente remova o comentário da typedef direita, dependendo se você estiver executando contra um binário de 32 bits ou 64 bits. Eu testei este contra ambas as arquiteturas em 10,6 e ele funciona muito bem.

Outras dicas

Eu acredito que você não pode fazer isso diretamente, mas você pode criar uma sonda estática personalizado que alimentações no CFString / NSString como um char *, que você pode usar com copyinstr (). Eu descrevo como fazer isso em um artigo aqui .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top