web-dev-qa-db-ja.com

構造データのhexdumpを取得する方法

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

 ........

デバッグのために、sendip_data型のdataおよびpack構造の16進ダンプが必要です。これは本当に複雑な構造です。実際にはいくつかのバイナリ情報が含まれているため、プロジェクトの出力が正しいかどうかはわかりません。したがって、デバッグの目的で、次のようにhexdumpを使用できるように、データをファイルに書き込みます。

$hexdump -C file.txt

また、これはan/wパケットのランタイム生成なので、fread / fwriteが必要だと思うdataおよびpack構造の長さもわかりません。私に何か。

30
Udit Gupta

次のコードは、コード内から任意のメモリの16進ダンプを提供します。

#include <stdio.h>

void hexDump (const char *desc, const void *addr, const int len) {
    int i;
    unsigned char buff[17];
    const unsigned char *pc = (const 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に説明、メモリアドレス、および長さを渡すと、検査のために16進ダンプ(文字データを含む)が出力されます。含まれる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.
113
paxdiablo

Android用の16進ダンプは、他のプラットフォームにも適しているはずです。

LOGD()DLOG()と同じですが、printf()はAndroidでは機能しないため、printf()の役割を果たします。 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

UPDATE:dump.cpp および re_dump.h in reDroid(github ) 、ポインターが有効かどうかをチェックする再帰ダンプが含まれています。