как получить шестнадцатеричного представления структуры данных
....
finalize(char *hdrs, sendip_data *headers[], int index,
sendip_data *data, sendip_data *pack)
{
........
Для отладки мне нужен шестнадцатеричный дамп структур data
и pack
, которые имеют тип sendip_data
, действительно сложную структуру. На самом деле они содержат некоторую двоичную информацию, поэтому я не уверен, является ли вывод моего проекта правильным или нет. Поэтому для отладки я хочу записать данные в файл, чтобы использовать hexdump следующим образом -
$hexdump -C file.txt
Также, как это генерация времени выполнения пакета n / w, поэтому я также не уверен в длине структуры data
и pack
что, я думаю, fread / fwrite
потребует ..так что, пожалуйста, предложите мне что-нибудь.
2 ответа:
Следующий код даст вам шестнадцатеричный дамп произвольной памяти из вашего кода.
#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.
Шестнадцатеричный дамп для Android, должен быть пригоден и для других платформ.
LOGD()
, так же, какDLOG()
, играет рольprintf()
, потому чтоprintf()
не работает в Android. Для платформ, отличных от Android, вы можете#define DLOG printf
.длог.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
свалка.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
Обновление: см. дамп.cpp и re_dump.h В reDroid (github) , он включает в себя рекурсивный дамп, который проверяет, является ли указатель допустимым.