4 * Copyright 2001,2007 Eric Pouech
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.
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.
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
33 void *dump_base
= NULL
;
34 size_t dump_total_len
= 0;
36 void dump_data( const unsigned char *ptr
, unsigned int size
, const char *prefix
)
40 printf( "%s%08x: ", prefix
, 0 );
46 for (i
= 0; i
< size
; i
++)
48 printf( "%02x%c", ptr
[i
], (i
% 16 == 7) ? '-' : ' ' );
52 for (j
= 0; j
< 16; j
++)
53 printf( "%c", isprint(ptr
[i
-15+j
]) ? ptr
[i
-15+j
] : '.' );
54 if (i
< size
-1) printf( "\n%s%08x: ", prefix
, i
+ 1 );
59 printf( "%*s ", 3 * (16-(i
%16)), "" );
60 for (j
= 0; j
< i
% 16; j
++)
61 printf( "%c", isprint(ptr
[i
-(i
%16)+j
]) ? ptr
[i
-(i
%16)+j
] : '.' );
66 static char* dump_want_n(unsigned sz
)
68 static char buffer
[4 * 1024];
72 assert(sz
< sizeof(buffer
));
73 if (idx
+ sz
>= sizeof(buffer
)) idx
= 0;
79 const char *get_time_str(unsigned long _t
)
81 const time_t t
= (const time_t)_t
;
82 const char *str
= ctime(&t
);
86 if (!str
) return "not valid time";
89 /* FIXME: I don't get the same values from MS' pedump running under Wine...
90 * I wonder if Wine isn't broken wrt to GMT settings...
92 if (len
&& str
[len
-1] == '\n') len
--;
93 buf
= dump_want_n(len
+ 1);
96 memcpy( buf
, str
, len
);
102 unsigned int strlenW( const WCHAR
*str
)
104 const WCHAR
*s
= str
;
109 void dump_unicode_str( const WCHAR
*str
, int len
)
111 if (len
== -1) len
= strlenW( str
);
113 while (len
-- > 0 && *str
)
118 case '\n': printf( "\\n" ); break;
119 case '\r': printf( "\\r" ); break;
120 case '\t': printf( "\\t" ); break;
121 case '"': printf( "\\\"" ); break;
122 case '\\': printf( "\\\\" ); break;
124 if (c
>= ' ' && c
<= 126) putchar(c
);
125 else printf( "\\u%04x",c
);
131 const char* get_symbol_str(const char* symname
)
136 if (!symname
) return "(nil)";
137 if (globals
.do_demangle
)
139 parsed_symbol symbol
;
141 symbol_init(&symbol
, symname
);
142 if (!symbol_demangle(&symbol
))
144 else if (symbol
.flags
& SYM_DATA
)
146 ret
= tmp
= dump_want_n(strlen(symbol
.arg_text
[0]) + 1);
147 if (tmp
) strcpy(tmp
, symbol
.arg_text
[0]);
151 unsigned int i
, len
, start
= symbol
.flags
& SYM_THISCALL
? 1 : 0;
153 len
= strlen(symbol
.return_text
) + 3 /* ' __' */ +
154 strlen(symbol_get_call_convention(&symbol
)) + 1 /* ' ' */+
155 strlen(symbol
.function_name
) + 1 /* ')' */;
156 if (!symbol
.argc
|| (symbol
.argc
== 1 && symbol
.flags
& SYM_THISCALL
))
157 len
+= 4 /* "void" */;
158 else for (i
= start
; i
< symbol
.argc
; i
++)
159 len
+= (i
> start
? 2 /* ", " */ : 0 /* "" */) + strlen(symbol
.arg_text
[i
]);
160 if (symbol
.varargs
) len
+= 5 /* ", ..." */;
161 len
+= 2; /* ")\0" */
163 ret
= tmp
= dump_want_n(len
);
166 sprintf(tmp
, "%s __%s %s(",
168 symbol_get_call_convention(&symbol
),
169 symbol
.function_name
);
170 if (!symbol
.argc
|| (symbol
.argc
== 1 && symbol
.flags
& SYM_THISCALL
))
172 else for (i
= start
; i
< symbol
.argc
; i
++)
174 if (i
> start
) strcat(tmp
, ", ");
175 strcat(tmp
, symbol
.arg_text
[i
]);
177 if (symbol
.varargs
) strcat(tmp
, ", ...");
181 symbol_clear(&symbol
);
187 const char* get_guid_str(const GUID
* guid
)
191 str
= dump_want_n(39);
193 sprintf(str
, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
194 (unsigned int)guid
->Data1
, guid
->Data2
, guid
->Data3
,
195 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
196 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
200 const char *get_unicode_str( const WCHAR
*str
, int len
)
205 if (len
== -1) len
= strlenW( str
);
206 buffer
= dump_want_n( len
* 6 + 3);
208 while (len
-- > 0 && *str
)
213 case '\n': strcpy( buffer
+ i
, "\\n" ); i
+= 2; break;
214 case '\r': strcpy( buffer
+ i
, "\\r" ); i
+= 2; break;
215 case '\t': strcpy( buffer
+ i
, "\\t" ); i
+= 2; break;
216 case '"': strcpy( buffer
+ i
, "\\\"" ); i
+= 2; break;
217 case '\\': strcpy( buffer
+ i
, "\\\\" ); i
+= 2; break;
219 if (c
>= ' ' && c
<= 126) buffer
[i
++] = c
;
220 else i
+= sprintf( buffer
+ i
, "\\u%04x",c
);
228 const void* PRD(unsigned long prd
, unsigned long len
)
230 return (prd
+ len
> dump_total_len
) ? NULL
: (const char*)dump_base
+ prd
;
233 unsigned long Offset(const void* ptr
)
235 if (ptr
< dump_base
) {printf("<<<<<ptr below\n");return 0;}
236 if ((const char *)ptr
>= (const char*)dump_base
+ dump_total_len
) {printf("<<<<<ptr above\n");return 0;}
237 return (const char *)ptr
- (const char *)dump_base
;
240 static const struct dumper
243 enum FileSig (*get_kind
)(void);
244 file_dumper dumper
; /* default dump tool */
248 {SIG_DOS
, get_kind_exec
, dos_dump
},
249 {SIG_PE
, get_kind_exec
, pe_dump
},
250 {SIG_DBG
, get_kind_dbg
, dbg_dump
},
251 {SIG_PDB
, get_kind_pdb
, pdb_dump
},
252 {SIG_NE
, get_kind_exec
, ne_dump
},
253 {SIG_LE
, get_kind_exec
, le_dump
},
254 {SIG_COFFLIB
, get_kind_lib
, lib_dump
},
255 {SIG_MDMP
, get_kind_mdmp
, mdmp_dump
},
256 {SIG_LNK
, get_kind_lnk
, lnk_dump
},
257 {SIG_EMF
, get_kind_emf
, emf_dump
},
258 {SIG_MF
, get_kind_mf
, mf_dump
},
259 {SIG_FNT
, get_kind_fnt
, fnt_dump
},
260 {SIG_TLB
, get_kind_tlb
, tlb_dump
},
261 {SIG_NLS
, get_kind_nls
, nls_dump
},
262 {SIG_UNKNOWN
, NULL
, NULL
} /* sentinel */
265 BOOL
dump_analysis(const char *name
, file_dumper fn
, enum FileSig wanted_sig
)
268 const struct dumper
*dpr
;
270 setbuf(stdout
, NULL
);
272 if (!(dump_base
= read_file( name
, &dump_total_len
))) fatal( "Cannot read file" );
274 printf("Contents of %s: %zu bytes\n\n", name
, dump_total_len
);
276 for (dpr
= dumpers
; dpr
->kind
!= SIG_UNKNOWN
; dpr
++)
278 if (dpr
->get_kind() == dpr
->kind
&&
279 (wanted_sig
== SIG_UNKNOWN
|| wanted_sig
== dpr
->kind
))
281 if (fn
) fn(); else dpr
->dumper();
285 if (dpr
->kind
== SIG_UNKNOWN
)
287 printf("Can't get a suitable file signature, aborting\n");
291 if (ret
) printf("Done dumping %s\n", name
);
297 void dump_file(const char* name
)
299 dump_analysis(name
, NULL
, SIG_UNKNOWN
);