C -如何获得结构数据的hexdump


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

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

$hexdump -C file.txt

也因为这是一个n/w包的运行时生成,所以我也不确定datapack结构的长度,我认为fread / fwrite将需要。

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

#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 LENGTHn");
        return;
    }
    if (len < 0) {
        printf("  NEGATIVE LENGTH: %dn", 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 ("  %sn", 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] = '';
    }
    // Pad out last line if not exactly perLine characters.
    while ((i % perLine) != 0) {
        printf ("   ");
        i++;
    }
    // And print the final ASCII buffer.
    printf ("  %sn", 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.

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("%sn",addr,len,linelen);
}

使用例子:

log_dumpf("args: %sn", &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

更新:参见reDroid (github)中的dump.cpp和re_dump.h,它包括一个递归转储,检查指针是否有效。

相关内容

  • 没有找到相关文章

最新更新