/* * File dumping utility * * Copyright 2001,2005 Eric Pouech * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include "wine/port.h" #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_MMAN_H #include #endif #include #define NONAMELESSUNION #define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" #include "winedump.h" static void* dump_base; static unsigned long dump_total_len; void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix ) { unsigned int i, j; printf( "%s%08x: ", prefix, 0 ); if (!ptr) { printf("NULL\n"); return; } for (i = 0; i < size; i++) { printf( "%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ' ); if ((i % 16) == 15) { printf( " " ); for (j = 0; j < 16; j++) printf( "%c", isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.' ); if (i < size-1) printf( "\n%s%08x: ", prefix, i + 1 ); } } if (i % 16) { printf( "%*s ", 3 * (16-(i%16)), "" ); for (j = 0; j < i % 16; j++) printf( "%c", isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.' ); } printf( "\n" ); } const char *get_time_str(unsigned long _t) { const time_t t = (const time_t)_t; const char *str = ctime(&t); size_t len; static char buf[128]; if (!str) /* not valid time */ { strcpy(buf, "not valid time"); return buf; } len = strlen(str); /* FIXME: I don't get the same values from MS' pedump running under Wine... * I wonder if Wine isn't broken wrt to GMT settings... */ if (len && str[len-1] == '\n') len--; if (len >= sizeof(buf)) len = sizeof(buf) - 1; memcpy( buf, str, len ); buf[len] = 0; return buf; } unsigned int strlenW( const WCHAR *str ) { const WCHAR *s = str; while (*s) s++; return s - str; } void dump_unicode_str( const WCHAR *str, int len ) { if (len == -1) len = strlenW( str ); printf( "L\""); while (len-- > 0 && *str) { WCHAR c = *str++; switch (c) { case '\n': printf( "\\n" ); break; case '\r': printf( "\\r" ); break; case '\t': printf( "\\t" ); break; case '"': printf( "\\\"" ); break; case '\\': printf( "\\\\" ); break; default: if (c >= ' ' && c <= 126) putchar(c); else printf( "\\u%04x",c); } } printf( "\"" ); } const void* PRD(unsigned long prd, unsigned long len) { return (prd + len > dump_total_len) ? NULL : (const char*)dump_base + prd; } unsigned long Offset(const void* ptr) { if (ptr < dump_base) {printf("<<<<= (const char*)dump_base + dump_total_len) {printf("<<<<e_lfanew, sizeof(DWORD)); if (pdw) { if (*pdw == IMAGE_NT_SIGNATURE) { sig = SIG_PE; } else if (*(const WORD *)pdw == IMAGE_OS2_SIGNATURE) { sig = SIG_NE; } else if (*(const WORD *)pdw == IMAGE_VXD_SIGNATURE) { sig = SIG_LE; } else { printf("No PE Signature found\n"); } } else { printf("Can't get the extented signature, aborting\n"); } } return sig; case 0x4944: /* "DI" */ return SIG_DBG; case 0x444D: /* "MD" */ pdw = PRD(0, sizeof(DWORD)); if (pdw && *pdw == 0x504D444D) /* "MDMP" */ return SIG_MDMP; return SIG_UNKNOWN; default: break; } p = PRD(0, IMAGE_ARCHIVE_START_SIZE); if (p && !strncmp(p, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE)) return SIG_COFFLIB; printf("No known main signature (%.2s/%x), aborting\n", (const char *)pw, *pw); return SIG_UNKNOWN; } int dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig) { int fd; enum FileSig effective_sig; int ret = 1; struct stat s; setbuf(stdout, NULL); fd = open(name, O_RDONLY | O_BINARY); if (fd == -1) fatal("Can't open file"); if (fstat(fd, &s) < 0) fatal("Can't get size"); dump_total_len = s.st_size; #ifdef HAVE_MMAP if ((dump_base = mmap(NULL, dump_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1) #endif { if (!(dump_base = malloc( dump_total_len ))) fatal( "Out of memory" ); if ((unsigned long)read( fd, dump_base, dump_total_len ) != dump_total_len) fatal( "Cannot read file" ); } effective_sig = check_headers(); if (wanted_sig == SIG_UNKNOWN || wanted_sig == effective_sig) { switch (effective_sig) { case SIG_UNKNOWN: /* shouldn't happen... */ printf("Can't get a recognized file signature, aborting\n"); ret = 0; break; case SIG_PE: case SIG_NE: case SIG_LE: printf("Contents of \"%s\": %ld bytes\n\n", name, dump_total_len); (*fn)(effective_sig); break; case SIG_DBG: dbg_dump(); break; case SIG_DOS: ret = 0; break; case SIG_MDMP: mdmp_dump(); break; case SIG_COFFLIB: printf("Contents of \"%s\": %ld bytes\n\n", name, dump_total_len); lib_dump(dump_base, dump_total_len); break; } } else { printf("Can't get a suitable file signature, aborting\n"); ret = 0; } if (ret) printf("Done dumping %s\n", name); #ifdef HAVE_MMAP if (munmap(dump_base, dump_total_len) == -1) #endif { free( dump_base ); } close(fd); return ret; } void dump_file(const char* name) { dump_analysis(name, do_dump, SIG_UNKNOWN); }