как получить hexdump данных структуры - PullRequest
30 голосов
/ 15 октября 2011
 ....
 finalize(char *hdrs, sendip_data *headers[], int index,
                    sendip_data *data, sendip_data *pack)
 {

 ........

Для целей отладки мне нужен шестнадцатеричный дамп структур data и pack, которые имеют тип sendip_data, очень сложная структура.На самом деле они содержат некоторую двоичную информацию, поэтому я не уверен, что вывод моего проекта правильный или нет.Поэтому для целей отладки я хочу записать данные в файл, чтобы я мог использовать hexdump следующим образом -

$hexdump -C file.txt

Также, поскольку это генерация во время выполнения пакета / w, поэтому я тоже неуверен в длине структуры data и pack, которая, я думаю, потребует fread / fwrite. Поэтому, пожалуйста, предложите мне что-нибудь.

Ответы [ 2 ]

112 голосов
/ 15 октября 2011

Следующий код даст вам шестнадцатеричный дамп произвольной памяти из вашего кода.

#include <stdio.h>

void hexDump (char *desc, void *addr, int len) {
    int i;
    unsigned char buff[17];
    unsigned char *pc = (unsigned char*)addr;

    // Output description if given.
    if (desc != NULL)
        printf ("%s:\n", desc);

    if (len == 0) {
        printf("  ZERO LENGTH\n");
        return;
    }
    if (len < 0) {
        printf("  NEGATIVE LENGTH: %i\n",len);
        return;
    }

    // Process every byte in the data.
    for (i = 0; i < len; i++) {
        // Multiple of 16 means new line (with line offset).

        if ((i % 16) == 0) {
            // Just don't print ASCII for the zeroth line.
            if (i != 0)
                printf ("  %s\n", buff);

            // Output the offset.
            printf ("  %04x ", i);
        }

        // Now the hex code for the specific character.
        printf (" %02x", pc[i]);

        // And store a printable ASCII character for later.
        if ((pc[i] < 0x20) || (pc[i] > 0x7e))
            buff[i % 16] = '.';
        else
            buff[i % 16] = pc[i];
        buff[(i % 16) + 1] = '\0';
    }

    // Pad out last line if not exactly 16 characters.
    while ((i % 16) != 0) {
        printf ("   ");
        i++;
    }

    // And print the final ASCII bit.
    printf ("  %s\n", buff);
}

int main (int argc, char *argv[]) {
    char my_str[] = "a char string greater than 16 chars";
    hexDump ("my_str", &my_str, sizeof (my_str));
    return 0;
}

Вы передаете в hexDump описание, адрес и длину памяти и выводите шестнадцатеричный дамп(включая символьные данные) для проверки.Когда вы запускаете его с включенным main, вывод будет:

my_str:
  0000  61 20 63 68 61 72 20 73 74 72 69 6e 67 20 67 72  a char string gr
  0010  65 61 74 65 72 20 74 68 61 6e 20 31 36 20 63 68  eater than 16 ch
  0020  61 72 73 00                                      ars.
4 голосов
/ 07 мая 2014

Шестнадцатеричный дамп для Android, должен подходить и для других платформ.

LOGD(), так же как и DLOG(), играет роль printf(), поскольку printf() не работает в Android,Для платформ, отличных от Android, вы можете #define DLOG printf.

dlog.h:

// Android logging
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "~~~~~~", __VA_ARGS__)
#define DLOG(...) __android_log_print(ANDROID_LOG_DEBUG  , "~~~~~~", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "~~~~~~", __VA_ARGS__)
#define ELOG(...) __android_log_print(ANDROID_LOG_ERROR  , "~~~~~~", __VA_ARGS__)

#ifdef __cplusplus
extern "C" {
#endif

void log_dump(const void*addr,int len,int linelen);
void log_dumpf(const char*fmt,const void*addr,int len,int linelen);

#ifdef __cplusplus
}
#endif

dump.cpp:

#include <dlog.h>
//#include <alloca.h>

inline char hdigit(int n){return "0123456789abcdef"[n&0xf];};

#define LEN_LIMIT 8
#define SUBSTITUTE_CHAR '`'

static const char* dumpline(char*dest, int linelen, const char*src, const char*srcend)
{
    if(src>=srcend) {
        return 0;
    }
    int i;
    unsigned long s = (unsigned long)src;
    for(i=0; i<8; i++) {
        dest[i] = hdigit(s>>(28-i*4));
    }
    dest[8] = ' ';
    dest += 9;
    for(i=0; i<linelen/4 ; i++) {
        if(src+i<srcend) {
            dest[i*3] = hdigit(src[i]>>4);
            dest[i*3+1] = hdigit(src[i]);
            dest[i*3+2] = ' ';
            dest[linelen/4*3+i] = src[i] >= ' ' && src[i] < 0x7f ? src[i] : SUBSTITUTE_CHAR;
        }else{
            dest[i*3] = dest[i*3+1] = dest[i*3+2] = dest[linelen/4*3+i] = ' ';
        }
    }
    return src+i;
}

void log_dumpf(const char*fmt,const void*addr,int len,int linelen)
{
#if LEN_LIMIT
    if(len>linelen*LEN_LIMIT) {
        len=linelen*LEN_LIMIT;
    }
#endif
    linelen *= 4;
    static char _buf[4096];
    char*buf = _buf;//(char*)alloca(linelen+1); // alloca() causes the initialization to fail!!!!
    buf[linelen]=0;
    const char*start = (char*)addr;
    const char*cur = start;
    const char*end = start+len;
    while(!!(cur = dumpline(buf,linelen,cur,start+len))){DLOG(fmt,buf);}
}

void log_dump(const void*addr,int len,int linelen)
{
    log_dumpf("%s\n",addr,len,linelen);
}

Пример использования:

log_dumpf("args: %s\n", &p, 0x20, 0x10);

Вывод:

args: 61efadc4 00 3c 17 01 6d bc 59 61 02 00 00 00 80 ae ef 61 `<``m`Ya```````a
args: 61efadd4 00 3c 17 01 00 00 00 00 31 a5 59 61 80 ae ef 61 `<``````1`Ya```a

ОБНОВЛЕНИЕ: см. dump.cpp и re_dump.h в reDroid (github) , он включает в себя рекурсивный дамп, который проверяет, является ли указатель действительным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...