如何获取结构数据的十六进制转储

发布于 2024-12-10 08:19:51 字数 527 浏览 1 评论 0原文

 ....
 finalize(char *hdrs, sendip_data *headers[], int index,
                    sendip_data *data, sendip_data *pack)
 {

 ........

出于调试目的,我需要 datapack 结构的十六进制转储,它们的类型为 sendip_data,这是一个非常复杂的结构。实际上它们包含一些二进制信息,所以我不确定我的项目的输出是否正确。因此,出于调试目的,我想将数据写入文件,以便可以按如下方式使用 hexdump -

$hexdump -C file.txt

另外,因为这是 an/w 数据包的运行时生成,所以我也不确定 data 的长度pack 结构,我认为 fread / fwrite 需要......所以请给我一些建议。

 ....
 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 -

$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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温柔戏命师 2024-12-17 08:19:51

以下代码将为您提供代码中任意内存的十六进制转储。

#include <stdio.h>

// Usage:
//     hexDump(desc, addr, len, perLine);
//         desc:    if non-NULL, printed as a description before hex dump.
//         addr:    the address to start dumping from.
//         len:     the number of bytes to dump.
//         perLine: number of bytes on each output line.

void hexDump (
    const char * desc,
    const void * addr,
    const int len,
    int perLine
) {
    // Silently ignore silly per-line values.

    if (perLine < 4 || perLine > 64) perLine = 16;

    int i;
    unsigned char buff[perLine+1];
    const unsigned char * pc = (const unsigned char *)addr;

    // Output description if given.

    if (desc != NULL) printf ("%s:\n", desc);

    // Length checks.

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

    // Process every byte in the data.

    for (i = 0; i < len; i++) {
        // Multiple of perLine means new or first line (with line offset).

        if ((i % perLine) == 0) {
            // Only print previous-line ASCII buffer for lines beyond first.

            if (i != 0) printf ("  %s\n", buff);

            // Output the offset of current line.

            printf ("  %04x ", i);
        }

        // Now the hex code for the specific character.

        printf (" %02x", pc[i]);

        // And buffer a printable ASCII character for later.

        if ((pc[i] < 0x20) || (pc[i] > 0x7e)) // isprint() may be better.
            buff[i % perLine] = '.';
        else
            buff[i % perLine] = pc[i];
        buff[(i % perLine) + 1] = '\0';
    }

    // Pad out last line if not exactly perLine characters.

    while ((i % perLine) != 0) {
        printf ("   ");
        i++;
    }

    // And print the final ASCII buffer.

    printf ("  %s\n", buff);
}

// Very simple test harness.

int main (int argc, char *argv[]) {
    char my_str[] = "a char string greater than 16 chars";
    hexDump ("my_str", &my_str, sizeof (my_str), 16);
    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.

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

#include <stdio.h>

// Usage:
//     hexDump(desc, addr, len, perLine);
//         desc:    if non-NULL, printed as a description before hex dump.
//         addr:    the address to start dumping from.
//         len:     the number of bytes to dump.
//         perLine: number of bytes on each output line.

void hexDump (
    const char * desc,
    const void * addr,
    const int len,
    int perLine
) {
    // Silently ignore silly per-line values.

    if (perLine < 4 || perLine > 64) perLine = 16;

    int i;
    unsigned char buff[perLine+1];
    const unsigned char * pc = (const unsigned char *)addr;

    // Output description if given.

    if (desc != NULL) printf ("%s:\n", desc);

    // Length checks.

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

    // Process every byte in the data.

    for (i = 0; i < len; i++) {
        // Multiple of perLine means new or first line (with line offset).

        if ((i % perLine) == 0) {
            // Only print previous-line ASCII buffer for lines beyond first.

            if (i != 0) printf ("  %s\n", buff);

            // Output the offset of current line.

            printf ("  %04x ", i);
        }

        // Now the hex code for the specific character.

        printf (" %02x", pc[i]);

        // And buffer a printable ASCII character for later.

        if ((pc[i] < 0x20) || (pc[i] > 0x7e)) // isprint() may be better.
            buff[i % perLine] = '.';
        else
            buff[i % perLine] = pc[i];
        buff[(i % perLine) + 1] = '\0';
    }

    // Pad out last line if not exactly perLine characters.

    while ((i % perLine) != 0) {
        printf ("   ");
        i++;
    }

    // And print the final ASCII buffer.

    printf ("  %s\n", buff);
}

// Very simple test harness.

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

You pass into hexDump a description, memory address, length, and how many bytes you want on each line.

It will output a hex dump (including character data) for examination. When you run it with the included main, the output is:

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.
请远离我 2024-12-17 08:19:51

适用于 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.cppre_dump.hre_dump.h com/18446744073709551615/reDroid/tree/master/jni" rel="noreferrer">reDroid (github),它包含一个递归转储,用于检查指针是否有效。

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

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.

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文