- Implement dumping of COFF debug symbol table.
- Fix winedump syntax description.
- Spelling fixes.

diff --git a/tools/winedump/README b/tools/winedump/README
index 293ac63..1a7732a 100644
--- a/tools/winedump/README
+++ b/tools/winedump/README
@@ -59,7 +59,7 @@
 - demangling MSVC C++ symbol names
 - dumping the 'PE' files contents
 
-Usage: winedump [-h sym <sym> spec <dll> dump <dll>] [mode options]
+Usage: winedump [-h | sym <sym> | spec <dll> | dump <dll>] [mode options]
 When used in -h mode
    -h           Display this help message
 When used in sym mode
@@ -436,7 +436,7 @@
 by value, its size also needs to be correct in order to forward the call
 correctly to a native DLL. In this case the structure is 8 bytes in size, which
 means that the gcc compile flag -freg-struct-return must be given when
-compiling the function in order to be compatable with the native DLL. (In 
+compiling the function in order to be compatable with the native DLL. (In
 general this is not an issue, but you need to be aware of such issues if you
 encounter problems with your forwarding DLL).
 
@@ -472,7 +472,7 @@
 The output should be piped through 'sort' and 'uniq' to remove multiple
 declarations, e.g:
 
-winedump -d foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h
+winedump foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h
 
 By adding '#include "fixup.h"' to foobar_dll.h your compile errors will be
 greatly reduced.
@@ -481,7 +481,7 @@
 the _cabs example above), it also prints a FIXME message like:
 
 /* FIXME: By value type: Assumed 'int' */ typedef int ldiv_t;
- 
+
 If the type is not an int, you will need to change the code and possibly
 the .spec entry in order to forward correctly. Otherwise, include the typedef
 in your fixup header to avoid compile errors.
@@ -582,10 +582,13 @@
 Dumping
 -------
 
-Another tool might be helpful digging into a 32bit DLL (and any PE image file):
+Another tool might be helpful for digging into a 32bit DLL (and any PE image file):
 pedump.
 
 Usage:
+winedump [-h | sym <sym> | spec <dll> | dump <dll> ] [switches]
+
+winedump switches:
    -h           Display this help message
    -d <dll>     Use dll for input file and generate implementation code
    -C           Turns on symbol demangling
@@ -593,13 +596,13 @@
    -j dir_name  Dumps only the content of directory dir_name (import, export, debug)
    -x           Dumps everything
 
-The basic usage, to look everything in a file is:
-winedump dump -d mydll.dll -x
+The basic usage, to look at everything in a file is:
+winedump dump mydll.dll -x
 
 It'll print any available information on the file. This information can be splitted
 into sub-categories:
-- file hedaers (request by -f or -x) are made of the standard PE header structures, 
+- file headers (request by -f or -x) are made of the standard PE header structures,
   plus the COFF sections
-- directories: you can print them one after the other using the -j switch. Currently, 
-  only the import, export and debug directories are implemented.
+- directories: you can print them one after the other using the -j switch.
+  Currently, only the import, export and debug directories are implemented.
 - -x displays the file headers and any available directory.
diff --git a/tools/winedump/debug.c b/tools/winedump/debug.c
index bd9164e..988a8b3 100644
--- a/tools/winedump/debug.c
+++ b/tools/winedump/debug.c
@@ -97,6 +97,10 @@
  *    (OMFDirHeader.cDir)
  */
 
+extern void			*PE_base;
+
+extern IMAGE_NT_HEADERS*        PE_nt_headers;
+
 static	void*		cv_base /* = 0 */;
 
 static int dump_cv_sst_module(OMFDirEntry* omfde)
@@ -482,7 +486,106 @@
     dump_codeview_all_modules(dirHeader);
 }
 
+static const char*   get_coff_name( PIMAGE_SYMBOL coff_sym, const char* coff_strtab )
+{
+   static       char    namebuff[9];
+   const char*          nampnt;
+
+   if( coff_sym->N.Name.Short )
+      {
+         memcpy(namebuff, coff_sym->N.ShortName, 8);
+         namebuff[8] = '\0';
+         nampnt = &namebuff[0];
+      }
+   else
+      {
+         nampnt = coff_strtab + coff_sym->N.Name.Long;
+      }
+
+   if( nampnt[0] == '_' )
+      nampnt++;
+   return nampnt;
+}
+
+void	dump_coff(unsigned long coffbase, unsigned long len)
+{
+    PIMAGE_COFF_SYMBOLS_HEADER coff;
+    PIMAGE_SYMBOL                 coff_sym;
+    PIMAGE_SYMBOL                 coff_symbols;
+    PIMAGE_LINENUMBER             coff_linetab;
+    char                        * coff_strtab;
+    IMAGE_SECTION_HEADER *sectHead = (IMAGE_SECTION_HEADER*)((char*)PE_nt_headers + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader);
+    unsigned int i;
+    const char                  * nampnt;
+    int naux;
+
+    coff = (PIMAGE_COFF_SYMBOLS_HEADER)PRD(coffbase, len);
+
+    coff_symbols = (PIMAGE_SYMBOL) ((unsigned int) coff + coff->LvaToFirstSymbol);
+    coff_linetab = (PIMAGE_LINENUMBER) ((unsigned int) coff + coff->LvaToFirstLinenumber);
+    coff_strtab = (char *) (coff_symbols + coff->NumberOfSymbols);
+
+    printf("\nDebug table: COFF format. modbase %p, coffbase %p\n", PE_base, coff);
+    printf("  ID  | seg:offs    [  abs   ] | symbol/function name\n");
+  for(i=0; i < coff->NumberOfSymbols; i++ )
+    {
+      coff_sym = coff_symbols + i;
+      naux = coff_sym->NumberOfAuxSymbols;
+
+      if( coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE )
+        {
+	  printf("file %s\n", (char *) (coff_sym + 1));
+          i += naux;
+          continue;
+        }
+
+      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
+          && (naux == 0)
+          && (coff_sym->SectionNumber == 1) )
+        {
+          DWORD base = sectHead[coff_sym->SectionNumber - 1].VirtualAddress;
+          /*
+           * This is a normal static function when naux == 0.
+           * Just register it.  The current file is the correct
+           * one in this instance.
+           */
+          nampnt = get_coff_name( coff_sym, coff_strtab );
+
+	  printf("%05d | %02d:%08lx [%08lx] | %s\n", i, coff_sym->SectionNumber - 1, coff_sym->Value - base, coff_sym->Value, nampnt);
+	  i += naux;
+	  continue;
+	}
+
+      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
+          && ISFCN(coff_sym->Type)
+          && (coff_sym->SectionNumber > 0) )
+        {
+          DWORD base = sectHead[coff_sym->SectionNumber - 1].VirtualAddress;
+
+          nampnt = get_coff_name( coff_sym, coff_strtab );
+
+	  /* FIXME: add code to find out the file this symbol belongs to,
+	   * see winedbg */
+	  printf("%05d | %02d:%08lx [%08lx] | %s\n", i, coff_sym->SectionNumber - 1, coff_sym->Value - base, coff_sym->Value, nampnt);
+          i += naux;
+          continue;
+	}
+
+      /*
+       * For now, skip past the aux entries.
+       */
+      i += naux;
+
+    }
+}
+
 void	dump_codeview(unsigned long base, unsigned long len)
 {
     dump_codeview_headers(base, len);
 }
+
+void	dump_frame_pointer_omission(unsigned long base, unsigned long len)
+{
+	/* FPO is used to describe nonstandard stack frames */
+	printf("FIXME: FPO (frame pointer omission) debug symbol dumping not implemented yet.\n");
+}
diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c
index 058cdeb..1da91df 100644
--- a/tools/winedump/pe.c
+++ b/tools/winedump/pe.c
@@ -46,9 +46,9 @@
 # define O_BINARY 0
 #endif
 
-static void*			base;
-static unsigned long		total_len;
-static IMAGE_NT_HEADERS*	nt_headers;
+void*			PE_base;
+unsigned long		PE_total_len;
+IMAGE_NT_HEADERS*	PE_nt_headers;
 
 enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG};
 
@@ -85,14 +85,14 @@
 
 void*	PRD(unsigned long prd, unsigned long len)
 {
-    return (prd + len > total_len) ? NULL : (char*)base + prd;
+    return (prd + len > PE_total_len) ? NULL : (char*)PE_base + prd;
 }
 
 unsigned long Offset(void* ptr)
 {
-    if (ptr < base) {printf("<<<<<ptr below\n");return 0;}
-    if ((char *)ptr >= (char*)base + total_len) {printf("<<<<<ptr above\n");return 0;}
-    return (char*)ptr - (char*)base;
+    if (ptr < PE_base) {printf("<<<<<ptr below\n");return 0;}
+    if ((char *)ptr >= (char*)PE_base + PE_total_len) {printf("<<<<<ptr above\n");return 0;}
+    return (char*)ptr - (char*)PE_base;
 }
 
 void*	RVA(unsigned long rva, unsigned long len)
@@ -100,13 +100,13 @@
     IMAGE_SECTION_HEADER*	sectHead;
     int				i;
 
-    sectHead = (IMAGE_SECTION_HEADER*)((char*)nt_headers + sizeof(DWORD) +
+    sectHead = (IMAGE_SECTION_HEADER*)((char*)PE_nt_headers + sizeof(DWORD) +
 				       sizeof(IMAGE_FILE_HEADER) +
-				       nt_headers->FileHeader.SizeOfOptionalHeader);
+				       PE_nt_headers->FileHeader.SizeOfOptionalHeader);
 
     if (rva == 0) return NULL;
 
-    for (i = nt_headers->FileHeader.NumberOfSections - 1; i >= 0; i--)
+    for (i = PE_nt_headers->FileHeader.NumberOfSections - 1; i >= 0; i--)
     {
         if (sectHead[i].VirtualAddress <= rva &&
             rva + len <= (DWORD)sectHead[i].VirtualAddress + sectHead[i].SizeOfRawData)
@@ -125,10 +125,10 @@
 
 static	void*	get_dir(unsigned idx)
 {
-    if (idx >= nt_headers->OptionalHeader.NumberOfRvaAndSizes)
+    if (idx >= PE_nt_headers->OptionalHeader.NumberOfRvaAndSizes)
 	return NULL;
-    return RVA(nt_headers->OptionalHeader.DataDirectory[idx].VirtualAddress,
-	       nt_headers->OptionalHeader.DataDirectory[idx].Size);
+    return RVA(PE_nt_headers->OptionalHeader.DataDirectory[idx].VirtualAddress,
+	       PE_nt_headers->OptionalHeader.DataDirectory[idx].Size);
 }
 
 static const char*	DirectoryNames[16] = {
@@ -146,7 +146,7 @@
     unsigned			i;
 
     printf("File Header\n");
-    fileHeader = &nt_headers->FileHeader;
+    fileHeader = &PE_nt_headers->FileHeader;
 
     printf("  Machine:                      %04X (%s)\n",
 	   fileHeader->Machine, get_machine_str(fileHeader->Machine));
@@ -175,7 +175,7 @@
 
     /* hope we have the right size */
     printf("Optional Header\n");
-    optionalHeader = &nt_headers->OptionalHeader;
+    optionalHeader = &PE_nt_headers->OptionalHeader;
     printf("  Magic                              0x%-4X         %u\n",
 	   optionalHeader->Magic, optionalHeader->Magic);
     printf("  linker version                     %u.%02u\n",
@@ -401,12 +401,12 @@
     unsigned			nb_imp, i;
 
     if (!importDesc)	return;
-    nb_imp = nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size /
+    nb_imp = PE_nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size /
 	sizeof(*importDesc);
     if (!nb_imp) return;
 
     printf("Import Table size: %lu\n",
-	   nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size);/* FIXME */
+	   PE_nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size);/* FIXME */
 
     for (i = 0; i < nb_imp - 1; i++) /* the last descr is set as 0 as a sentinel */
     {
@@ -495,11 +495,13 @@
     case IMAGE_DEBUG_TYPE_UNKNOWN:
 	break;
     case IMAGE_DEBUG_TYPE_COFF:
+	dump_coff(idd->PointerToRawData, idd->SizeOfData);
 	break;
     case IMAGE_DEBUG_TYPE_CODEVIEW:
 	dump_codeview(idd->PointerToRawData, idd->SizeOfData);
 	break;
     case IMAGE_DEBUG_TYPE_FPO:
+	dump_frame_pointer_omission(idd->PointerToRawData, idd->SizeOfData);
 	break;
     case IMAGE_DEBUG_TYPE_MISC:
     {
@@ -535,7 +537,7 @@
     unsigned			nb_dbg, i;
 
     if (!debugDir) return;
-    nb_dbg = nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_DEBUG_DIRECTORY].Size /
+    nb_dbg = PE_nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_DEBUG_DIRECTORY].Size /
 	sizeof(*debugDir);
     if (!nb_dbg) return;
 
@@ -740,10 +742,10 @@
     if (globals.do_dumpheader)
     {
 	dump_pe_header();
-	/* FIX%E: should check ptr */
-	dump_sections((char*)nt_headers + sizeof(DWORD) +
-		      sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader,
-		      nt_headers->FileHeader.NumberOfSections);
+	/* FIXME: should check ptr */
+	dump_sections((char*)PE_nt_headers + sizeof(DWORD) +
+		      sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader,
+		      PE_nt_headers->FileHeader.NumberOfSections);
     }
     else if (!globals.dumpsect)
     {
@@ -792,7 +794,7 @@
 	    {
 		if (*pdw == IMAGE_NT_SIGNATURE)
 		{
-		    nt_headers = PRD(dh->e_lfanew, sizeof(DWORD));
+		    PE_nt_headers = PRD(dh->e_lfanew, sizeof(DWORD));
 		    sig = SIG_PE;
 		}
 		else
@@ -830,14 +832,14 @@
     if (fd == -1) fatal("Can't open file");
 
     if (fstat(fd, &s) < 0) fatal("Can't get size");
-    total_len = s.st_size;
+    PE_total_len = s.st_size;
 
 #ifdef HAVE_MMAP
-    if ((base = mmap(NULL, total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
+    if ((PE_base = mmap(NULL, PE_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
 #endif
     {
-        if (!(base = malloc( total_len ))) fatal( "Out of memory" );
-        if (read( fd, base, total_len ) != total_len) fatal( "Cannot read file" );
+        if (!(PE_base = malloc( PE_total_len ))) fatal( "Out of memory" );
+        if (read( fd, PE_base, PE_total_len ) != PE_total_len) fatal( "Cannot read file" );
     }
 
     effective_sig = check_headers();
@@ -854,7 +856,7 @@
 	case SIG_UNKNOWN: /* shouldn't happen... */
 	    ret = 0; break;
 	case SIG_PE:
-	    printf("Contents of \"%s\": %ld bytes\n\n", name, total_len);
+	    printf("Contents of \"%s\": %ld bytes\n\n", name, PE_total_len);
 	    (*fn)();
 	    break;
 	case SIG_DBG:
@@ -872,10 +874,10 @@
 
     if (ret) printf("Done dumping %s\n", name);
 #ifdef HAVE_MMAP
-    if (munmap(base, total_len) == -1)
+    if (munmap(PE_base, PE_total_len) == -1)
 #endif
     {
-        free( base );
+        free( PE_base );
     }
     close(fd);
 
diff --git a/tools/winedump/pe.h b/tools/winedump/pe.h
index a01f61c..a258b29 100644
--- a/tools/winedump/pe.h
+++ b/tools/winedump/pe.h
@@ -19,7 +19,8 @@
  */
 
 extern void		dump_codeview(unsigned long ptr, unsigned long len);
+extern void		dump_coff(unsigned long coffbase, unsigned long len);
+extern void		dump_frame_pointer_omission(unsigned long base, unsigned long len);
 extern void*		PRD(unsigned long prd, unsigned long len);
 extern unsigned long	Offset(void* ptr);
 extern char*		get_time_str(DWORD _t);
-