如何获得结构数据的hexdump ?

时间:2021-03-21 01:07:37
 ....
 finalize(char *hdrs, sendip_data *headers[], int index,
                    sendip_data *data, sendip_data *pack)
 {

 ........

For debugging purposes I want a hex dump of the data and pack structures, which are of type sendip_data, a really complex structure. Actually they contain some binary information so I am not sure whether output of my project is correct or not. So for debugging purposes, I want to write the data into a file so that I can use hexdump as follows -

出于调试目的,我想要数据和包结构的十六进制转储,它们是sendip_data类型的,是一个非常复杂的结构。实际上它们包含一些二进制信息,所以我不确定我的项目的输出是否正确。为了调试的目的,我想把数据写到一个文件中,这样我就可以像下面这样使用hexdump了

$hexdump -C file.txt

Also as this is a run time generation of a n/w packet so I am also not sure about the length of data and pack structure which I think fread / fwrite will require ..So please suggest me something.

由于这是n/w包的运行时生成,所以我也不确定fread / fwrite需要的数据长度和包结构。所以请给我建议。

2 个解决方案

#1


102  

The following code will give you a hex dump of arbitrary memory from within your code.

下面的代码将给出代码中任意内存的十六进制转储。

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

You pass into hexDump a description, memory address and length, and it will output a hex dump (including character data) for examination. When you run it with the included main, the output is:

您传入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.

#2


4  

A hex dump for Android, should be suitable for other platforms as well.

Android的十六进制转储也应该适用于其他平台。

LOGD(), same as DLOG(), plays the role of printf() because printf() does not work in Android. For platforms other than Android, you may #define DLOG printf.

LOGD()和DLOG()扮演printf()的角色,因为printf()在Android中不能工作。对于Android以外的平台,可以使用#定义DLOG printf。

dlog.h:

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:

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

Usage example:

使用的例子:

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

Output:

输出:

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

UPDATE: see dump.cpp and re_dump.h in reDroid (github), it includes a recursive dump that checks if a pointer is valid.

更新:看到转储。cpp和re_dump。在reDroid (github)中,它包含一个递归转储,用于检查指针是否有效。

#1


102  

The following code will give you a hex dump of arbitrary memory from within your code.

下面的代码将给出代码中任意内存的十六进制转储。

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

You pass into hexDump a description, memory address and length, and it will output a hex dump (including character data) for examination. When you run it with the included main, the output is:

您传入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.

#2


4  

A hex dump for Android, should be suitable for other platforms as well.

Android的十六进制转储也应该适用于其他平台。

LOGD(), same as DLOG(), plays the role of printf() because printf() does not work in Android. For platforms other than Android, you may #define DLOG printf.

LOGD()和DLOG()扮演printf()的角色,因为printf()在Android中不能工作。对于Android以外的平台,可以使用#定义DLOG printf。

dlog.h:

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:

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

Usage example:

使用的例子:

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

Output:

输出:

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

UPDATE: see dump.cpp and re_dump.h in reDroid (github), it includes a recursive dump that checks if a pointer is valid.

更新:看到转储。cpp和re_dump。在reDroid (github)中,它包含一个递归转储,用于检查指针是否有效。