dump.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * File dumping utility
  3. *
  4. * Copyright 2001,2007 Eric Pouech
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <time.h>
  25. #include "../tools.h"
  26. #include "windef.h"
  27. #include "winbase.h"
  28. #include "winedump.h"
  29. void *dump_base = NULL;
  30. unsigned long dump_total_len = 0;
  31. void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix )
  32. {
  33. unsigned int i, j;
  34. printf( "%s%08x: ", prefix, 0 );
  35. if (!ptr)
  36. {
  37. printf("NULL\n");
  38. return;
  39. }
  40. for (i = 0; i < size; i++)
  41. {
  42. printf( "%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ' );
  43. if ((i % 16) == 15)
  44. {
  45. printf( " " );
  46. for (j = 0; j < 16; j++)
  47. printf( "%c", isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.' );
  48. if (i < size-1) printf( "\n%s%08x: ", prefix, i + 1 );
  49. }
  50. }
  51. if (i % 16)
  52. {
  53. printf( "%*s ", 3 * (16-(i%16)), "" );
  54. for (j = 0; j < i % 16; j++)
  55. printf( "%c", isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.' );
  56. }
  57. printf( "\n" );
  58. }
  59. static char* dump_want_n(unsigned sz)
  60. {
  61. static char buffer[4 * 1024];
  62. static unsigned idx;
  63. char* ret;
  64. assert(sz < sizeof(buffer));
  65. if (idx + sz >= sizeof(buffer)) idx = 0;
  66. ret = &buffer[idx];
  67. idx += sz;
  68. return ret;
  69. }
  70. const char *get_time_str(unsigned long _t)
  71. {
  72. const time_t t = (const time_t)_t;
  73. const char *str = ctime(&t);
  74. size_t len;
  75. char* buf;
  76. if (!str) return "not valid time";
  77. len = strlen(str);
  78. /* FIXME: I don't get the same values from MS' pedump running under Wine...
  79. * I wonder if Wine isn't broken wrt to GMT settings...
  80. */
  81. if (len && str[len-1] == '\n') len--;
  82. buf = dump_want_n(len + 1);
  83. if (buf)
  84. {
  85. memcpy( buf, str, len );
  86. buf[len] = 0;
  87. }
  88. return buf;
  89. }
  90. unsigned int strlenW( const WCHAR *str )
  91. {
  92. const WCHAR *s = str;
  93. while (*s) s++;
  94. return s - str;
  95. }
  96. void dump_unicode_str( const WCHAR *str, int len )
  97. {
  98. if (len == -1) len = strlenW( str );
  99. printf( "L\"");
  100. while (len-- > 0 && *str)
  101. {
  102. WCHAR c = *str++;
  103. switch (c)
  104. {
  105. case '\n': printf( "\\n" ); break;
  106. case '\r': printf( "\\r" ); break;
  107. case '\t': printf( "\\t" ); break;
  108. case '"': printf( "\\\"" ); break;
  109. case '\\': printf( "\\\\" ); break;
  110. default:
  111. if (c >= ' ' && c <= 126) putchar(c);
  112. else printf( "\\u%04x",c);
  113. }
  114. }
  115. printf( "\"" );
  116. }
  117. const char* get_symbol_str(const char* symname)
  118. {
  119. char* tmp;
  120. const char* ret;
  121. if (!symname) return "(nil)";
  122. if (globals.do_demangle)
  123. {
  124. parsed_symbol symbol;
  125. symbol_init(&symbol, symname);
  126. if (!symbol_demangle(&symbol))
  127. ret = symname;
  128. else if (symbol.flags & SYM_DATA)
  129. {
  130. ret = tmp = dump_want_n(strlen(symbol.arg_text[0]) + 1);
  131. if (tmp) strcpy(tmp, symbol.arg_text[0]);
  132. }
  133. else
  134. {
  135. unsigned int i, len, start = symbol.flags & SYM_THISCALL ? 1 : 0;
  136. len = strlen(symbol.return_text) + 3 /* ' __' */ +
  137. strlen(symbol_get_call_convention(&symbol)) + 1 /* ' ' */+
  138. strlen(symbol.function_name) + 1 /* ')' */;
  139. if (!symbol.argc || (symbol.argc == 1 && symbol.flags & SYM_THISCALL))
  140. len += 4 /* "void" */;
  141. else for (i = start; i < symbol.argc; i++)
  142. len += (i > start ? 2 /* ", " */ : 0 /* "" */) + strlen(symbol.arg_text[i]);
  143. if (symbol.varargs) len += 5 /* ", ..." */;
  144. len += 2; /* ")\0" */
  145. ret = tmp = dump_want_n(len);
  146. if (tmp)
  147. {
  148. sprintf(tmp, "%s __%s %s(",
  149. symbol.return_text,
  150. symbol_get_call_convention(&symbol),
  151. symbol.function_name);
  152. if (!symbol.argc || (symbol.argc == 1 && symbol.flags & SYM_THISCALL))
  153. strcat(tmp, "void");
  154. else for (i = start; i < symbol.argc; i++)
  155. {
  156. if (i > start) strcat(tmp, ", ");
  157. strcat(tmp, symbol.arg_text[i]);
  158. }
  159. if (symbol.varargs) strcat(tmp, ", ...");
  160. strcat(tmp, ")");
  161. }
  162. }
  163. symbol_clear(&symbol);
  164. }
  165. else ret = symname;
  166. return ret;
  167. }
  168. const char* get_guid_str(const GUID* guid)
  169. {
  170. char* str;
  171. str = dump_want_n(39);
  172. if (str)
  173. sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
  174. guid->Data1, guid->Data2, guid->Data3,
  175. guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
  176. guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
  177. return str;
  178. }
  179. const char *get_unicode_str( const WCHAR *str, int len )
  180. {
  181. char *buffer;
  182. int i = 0;
  183. if (len == -1) len = strlenW( str );
  184. buffer = dump_want_n( len * 6 + 3);
  185. buffer[i++] = '"';
  186. while (len-- > 0 && *str)
  187. {
  188. WCHAR c = *str++;
  189. switch (c)
  190. {
  191. case '\n': strcpy( buffer + i, "\\n" ); i += 2; break;
  192. case '\r': strcpy( buffer + i, "\\r" ); i += 2; break;
  193. case '\t': strcpy( buffer + i, "\\t" ); i += 2; break;
  194. case '"': strcpy( buffer + i, "\\\"" ); i += 2; break;
  195. case '\\': strcpy( buffer + i, "\\\\" ); i += 2; break;
  196. default:
  197. if (c >= ' ' && c <= 126) buffer[i++] = c;
  198. else i += sprintf( buffer + i, "\\u%04x",c);
  199. }
  200. }
  201. buffer[i++] = '"';
  202. buffer[i] = 0;
  203. return buffer;
  204. }
  205. const void* PRD(unsigned long prd, unsigned long len)
  206. {
  207. return (prd + len > dump_total_len) ? NULL : (const char*)dump_base + prd;
  208. }
  209. unsigned long Offset(const void* ptr)
  210. {
  211. if (ptr < dump_base) {printf("<<<<<ptr below\n");return 0;}
  212. if ((const char *)ptr >= (const char*)dump_base + dump_total_len) {printf("<<<<<ptr above\n");return 0;}
  213. return (const char *)ptr - (const char *)dump_base;
  214. }
  215. static const struct dumper
  216. {
  217. enum FileSig kind;
  218. enum FileSig (*get_kind)(void);
  219. file_dumper dumper; /* default dump tool */
  220. }
  221. dumpers[] =
  222. {
  223. {SIG_DOS, get_kind_exec, dos_dump},
  224. {SIG_PE, get_kind_exec, pe_dump},
  225. {SIG_DBG, get_kind_dbg, dbg_dump},
  226. {SIG_PDB, get_kind_pdb, pdb_dump},
  227. {SIG_NE, get_kind_exec, ne_dump},
  228. {SIG_LE, get_kind_exec, le_dump},
  229. {SIG_COFFLIB, get_kind_lib, lib_dump},
  230. {SIG_MDMP, get_kind_mdmp, mdmp_dump},
  231. {SIG_LNK, get_kind_lnk, lnk_dump},
  232. {SIG_EMF, get_kind_emf, emf_dump},
  233. {SIG_MF, get_kind_mf, mf_dump},
  234. {SIG_FNT, get_kind_fnt, fnt_dump},
  235. {SIG_TLB, get_kind_tlb, tlb_dump},
  236. {SIG_NLS, get_kind_nls, nls_dump},
  237. {SIG_UNKNOWN, NULL, NULL} /* sentinel */
  238. };
  239. BOOL dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig)
  240. {
  241. int fd;
  242. BOOL ret = TRUE;
  243. struct stat s;
  244. const struct dumper *dpr;
  245. setbuf(stdout, NULL);
  246. fd = open(name, O_RDONLY | O_BINARY);
  247. if (fd == -1) fatal("Can't open file");
  248. if (fstat(fd, &s) < 0) fatal("Can't get size");
  249. dump_total_len = s.st_size;
  250. dump_base = xmalloc( dump_total_len );
  251. if ((unsigned long)read( fd, dump_base, dump_total_len ) != dump_total_len) fatal( "Cannot read file" );
  252. printf("Contents of %s: %ld bytes\n\n", name, dump_total_len);
  253. for (dpr = dumpers; dpr->kind != SIG_UNKNOWN; dpr++)
  254. {
  255. if (dpr->get_kind() == dpr->kind &&
  256. (wanted_sig == SIG_UNKNOWN || wanted_sig == dpr->kind))
  257. {
  258. if (fn) fn(); else dpr->dumper();
  259. break;
  260. }
  261. }
  262. if (dpr->kind == SIG_UNKNOWN)
  263. {
  264. printf("Can't get a suitable file signature, aborting\n");
  265. ret = FALSE;
  266. }
  267. if (ret) printf("Done dumping %s\n", name);
  268. free( dump_base );
  269. close(fd);
  270. return ret;
  271. }
  272. void dump_file(const char* name)
  273. {
  274. dump_analysis(name, NULL, SIG_UNKNOWN);
  275. }