/*
 * File msc.c - read VC++ debug information from COFF and eventually
 * from PDB files.
 *
 * Copyright (C) 1996, Eric Youngdale.
 *
 * Note - this handles reading debug information for 32 bit applications
 * that run under Windows-NT for example.  I doubt that this would work well
 * for 16 bit applications, but I don't think it really matters since the
 * file format is different, and we should never get in here in such cases.
 *
 * TODO:
 *	Get 16 bit CV stuff working.
 *	Add symbol size to internal symbol table.
 */

#include "config.h"
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include <fcntl.h>
#include <sys/stat.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#ifndef PATH_MAX
#define PATH_MAX _MAX_PATH
#endif
#include "debugger.h"
#include "neexe.h"
#include "peexe.h"
#include "file.h"

/*
    *dbg_filename must be at least MAX_PATHNAME_LEN bytes in size
*/
static void LocateDebugInfoFile(char *filename, char *dbg_filename)
{
    char	  *str1 = DBG_alloc(MAX_PATHNAME_LEN*10);
    char	  *str2 = DBG_alloc(MAX_PATHNAME_LEN);
    char	  *file;
    char	  *name_part;
    DOS_FULL_NAME fullname;
    
    file = strrchr(filename, '\\');
    if( file == NULL ) file = filename; else file++;

    if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", str1, MAX_PATHNAME_LEN))
	if (SearchPathA(str1, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part))
	    goto ok;
    if (GetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", str1, MAX_PATHNAME_LEN))
	if (SearchPathA(str1, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part))
	    goto ok;
    if (SearchPathA(NULL, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part))
	goto ok;
    else
    {
quit:	
        memcpy(dbg_filename, filename, MAX_PATHNAME_LEN);
	DBG_free(str1);
	DBG_free(str2);
	return;
    }
ok:
    if (DOSFS_GetFullName(str2, TRUE, &fullname))
	memcpy(dbg_filename, fullname.long_name, MAX_PATHNAME_LEN);
    else
	goto quit;
    DBG_free(str1);
    DBG_free(str2);
    return;
}
/*
 * This is an index we use to keep track of the debug information
 * when we have multiple sources.  We use the same database to also
 * allow us to do an 'info shared' type of deal, and we use the index
 * to eliminate duplicates.
 */
static int DEBUG_next_index = 0;

union any_size
{
  char		 * c;
  short		 * s;
  int		 * i;
  unsigned int   * ui;
};

/*
 * This is a convenience structure used to map portions of the
 * line number table.
 */
struct startend
{
  unsigned int	  start;
  unsigned int	  end;
};

/*
 * This is how we reference the various record types.
 */
union codeview_symbol
{
  struct
  {
    short int	len;
    short int	id;
  } generic;

  struct
  {
	short int	len;
	short int	id;
	unsigned int	offset;
	unsigned short	seg;
	unsigned short	symtype;
	unsigned char	namelen;
	unsigned char	name[1];
  } data;

  struct
  {
	short int	len;
	short int	id;
	unsigned int	pparent;
	unsigned int	pend;
	unsigned int	next;
	unsigned int	offset;
	unsigned short	segment;
	unsigned short	thunk_len;
	unsigned char	thtype;
	unsigned char	namelen;
	unsigned char	name[1];
  } thunk;
  struct
  {
	short int	len;
	short int	id;
	unsigned int	pparent;
	unsigned int	pend;
	unsigned int	next;
	unsigned int	proc_len;
	unsigned int	debug_start;
	unsigned int	debug_end;
	unsigned int	offset;
	unsigned short	segment;
	unsigned short	proctype;
	unsigned char	flags;
	unsigned char	namelen;
	unsigned char	name[1];
  } proc;
  struct
  {
	short int	len;	/* Total length of this entry */
	short int	id;		/* Always S_BPREL32 */
	unsigned int	offset;	/* Stack offset relative to BP */
	unsigned short	symtype;
	unsigned char	namelen;
	unsigned char	name[1];
  } stack;
};

union codeview_type
{
  struct
  {
    short int	len;
    short int	id;
  } generic;

  struct
  {
    short int		len;
    short int		id;
    short int		attribute;
    short int		datatype;
    unsigned char	variant[1];
  } pointer;

  struct
  {
    short int		len;
    short int		id;
    unsigned char	nbits;
    unsigned char	bitoff;
    unsigned short	type;
  } bitfield;

  struct
  {
    short int		len;
    short int		id;
    short int		elemtype;
    short int		idxtype;
    unsigned char	arrlen;
    unsigned char	namelen;
    unsigned char	name[1];
  } array;

  struct
  {
    short int		len;
    short int		id;
    short int		n_element;
    short int		fieldlist;
    short int		property;
    short int		derived;
    short int		vshape;
    unsigned short	structlen;
    unsigned char	namelen;
    unsigned char	name[1];
  } structure;

  struct
  {
    short int		len;
    short int		id;
    short int		count;
    short int		field;
    short int		property;
    unsigned short	un_len;
    unsigned char	namelen;
    unsigned char	name[1];
  } t_union;

  struct
  {
    short int		len;
    short int		id;
    short int		count;
    short int		type;
    short int		field;
    short int		property;
    unsigned char	namelen;
    unsigned char	name[1];
  } enumeration;

  struct
  {
    short int		id;
    short int		attribute;
    unsigned short int	value;
    unsigned char	namelen;
    unsigned char	name[1];
  } enumerate;

  struct
  {
    short int		id;
    short int		type;
    short int		attribute;
    unsigned short int	offset;
    unsigned char	namelen;
    unsigned char	name[1];
  } member;

  struct
  {
    short int		len;
    short int		id;
    short int		count;
    short int		type;
    short int		field;
    short int		property;
    unsigned char	namelen;
    unsigned char	name[1];
  } fieldlist;

};

#define S_BPREL	0x200
#define S_LDATA	0x201
#define S_GDATA	0x202
#define S_PUB		0x203
#define S_LPROC	0x204
#define S_GPROC	0x205
#define S_THUNK	0x206
#define S_BLOCK	0x207
#define S_WITH	0x208
#define S_LABEL	0x209

#define S_PROCREF	0x400
#define S_DATAREF	0x401
#define S_ALIGN		0x402
#define S_UNKNOWN	0x403

/*
 * This covers the basic datatypes that VC++ seems to be using these days.
 * 32 bit mode only.  There are additional numbers for the pointers in 16
 * bit mode.  There are many other types listed in the documents, but these
 * are apparently not used by the compiler, or represent pointer types
 * that are not used.
 */
#define T_NOTYPE	0x0000	/* Notype */
#define T_ABS		0x0001	/* Abs */
#define T_VOID		0x0003	/* Void */
#define T_CHAR		0x0010	/* signed char */
#define T_SHORT		0x0011	/* short */
#define T_LONG		0x0012	/* long */
#define T_QUAD		0x0013	/* long long */
#define T_UCHAR		0x0020	/* unsigned  char */
#define T_USHORT	0x0021	/* unsigned short */
#define T_ULONG		0x0022	/* unsigned long */
#define T_UQUAD		0x0023	/* unsigned long long */
#define T_REAL32	0x0040	/* float */
#define T_REAL64	0x0041	/* double */
#define T_RCHAR		0x0070	/* real char */
#define T_WCHAR		0x0071	/* wide char */
#define T_INT4		0x0074	/* int */
#define T_UINT4		0x0075	/* unsigned int */

#define T_32PVOID	0x0403	/* 32 bit near pointer to void */
#define T_32PCHAR	0x0410  /* 16:32 near pointer to signed char */
#define T_32PSHORT	0x0411  /* 16:32 near pointer to short */
#define T_32PLONG	0x0412  /* 16:32 near pointer to int */
#define T_32PQUAD	0x0413  /* 16:32 near pointer to long long */
#define T_32PUCHAR	0x0420  /* 16:32 near pointer to unsigned char */
#define T_32PUSHORT	0x0421  /* 16:32 near pointer to unsigned short */
#define T_32PULONG	0x0422	/* 16:32 near pointer to unsigned int */
#define T_32PUQUAD	0x0423  /* 16:32 near pointer to long long */
#define T_32PREAL32	0x0440	/* 16:32 near pointer to float */
#define T_32PREAL64	0x0441	/* 16:32 near pointer to float */
#define T_32PRCHAR	0x0470	/* 16:32 near pointer to real char */
#define T_32PWCHAR	0x0471	/* 16:32 near pointer to real char */
#define T_32PINT4	0x0474	/* 16:32 near pointer to int */
#define T_32PUINT4	0x0475  /* 16:32 near pointer to unsigned int */

#define LF_MODIFIER	0x1
#define LF_POINTER	0x2
#define LF_ARRAY	0x3
#define LF_CLASS	0x4
#define LF_STRUCTURE	0x5
#define LF_UNION	0x6
#define LF_ENUMERATION	0x7
#define LF_PROCEDURE	0x8
#define LF_MFUNCTION	0x9
#define LF_VTSHAPE	0xa
#define LF_BARRAY	0xd
#define LF_DIMARRAY	0x11
#define LF_VFTPATH	0x12

#define LF_SKIP		0x200
#define LF_ARGLIST	0x201
#define LF_FIELDLIST	0x204
#define LF_DERIVED	0x205
#define LF_BITFIELD	0x206

#define LF_BCLASS	0x400
#define LF_VBCLASS	0x401
#define LF_IVBCLASS	0x402
#define LF_ENUMERATE	0x403
#define LF_FRIENDFCN	0x404
#define LF_INDEX	0x405
#define LF_MEMBER	0x406
#define LF_STMEMBER	0x407
#define LF_METHOD	0x408
#define LF_NESTEDTYPE	0x409
#define LF_VFUNCTAB	0x40a
#define LF_FRIENDCLS	0x40b
#define LF_ONEMETHOD	0x40c
#define LF_FUNCOFF	0x40d

#define MAX_BUILTIN_TYPES	0x480
static struct datatype * cv_basic_types[MAX_BUILTIN_TYPES];
static int num_cv_defined_types = 0;
static struct datatype **cv_defined_types = NULL;

/*
 * For the type CODEVIEW debug directory entries, the debug directory
 * points to a structure like this.  The cv_name field is the name
 * of an external .PDB file.
 */
struct CodeViewDebug
{
	char		    cv_nbtype[8];
	unsigned int	    cv_timestamp;
	char		    cv_unknown[4];
	char		    cv_name[1];
};

struct MiscDebug {
    unsigned int       DataType;
    unsigned int       Length;
    char	       Unicode;
    char	       Reserved[3];
    char	       Data[1];
};

/*
 * This is the header that the COFF variety of debug header points to.
 */
struct CoffDebug {
    unsigned int   N_Sym;
    unsigned int   SymbolOffset;
    unsigned int   N_Linenum;
    unsigned int   LinenumberOffset;
    unsigned int   Unused[4];
};

struct CoffLinenum {
	unsigned int		VirtualAddr;
	unsigned short int	Linenum;
};

struct CoffFiles {
	unsigned int	startaddr;
	unsigned int	endaddr;
	char	      * filename;
	int		linetab_offset;
	int		linecnt;
	struct name_hash **entries;
	int		       neps;
	int		 neps_alloc;
};


struct CoffSymbol {
    union {
        char    ShortName[8];
        struct {
            unsigned int   NotLong;
            unsigned int   StrTaboff;
        } Name;
    } N;
    unsigned int   Value;
    short	   SectionNumber;
    short	   Type;
    char	   StorageClass;
    unsigned char  NumberOfAuxSymbols;
};

struct CoffAuxSection{
  unsigned int   Length;
  unsigned short NumberOfRelocations;
  unsigned short NumberOfLinenumbers;
  unsigned int   CheckSum;
  short          Number;
  char           Selection;
} Section;

/*
 * These two structures are used in the directory within a .DBG file
 * to locate the individual important bits that we might want to see.
 */
struct CV4_DirHead {
  short unsigned int	   dhsize;
  short unsigned int	   desize;
  unsigned int		   ndir;
  unsigned int		   next_offset;
  unsigned int		   flags;
};

struct CV4_DirEnt {
  short unsigned int	   subsect_number;
  short unsigned int	   module_number;
  unsigned int		   offset;
  unsigned int		   size;
};

/*
 * These are the values of interest that the subsect_number field takes.
 */
#define	sstAlignSym		0x125
#define	sstSrcModule		0x127

struct codeview_linetab_hdr
{
  unsigned int		   nline;
  unsigned int		   segno;
  unsigned int		   start;
  unsigned int		   end;
  char			 * sourcefile;
  unsigned short	 * linetab;
  unsigned int		 * offtab;
};

struct codeview_pdb_hdr
{
  char		ident[44];
  unsigned int	blocksize;	   /* Extent size */
  unsigned short loc_freelist;   /* freelist. */
  unsigned short alloc_filesize; /* # extents allocated. */
  unsigned int	toc_len;
  unsigned int	unknown;
  unsigned short toc_ext[1];	   /* array of extent #'s for toc. */
};

/*
 * This is our own structure that we use to keep track of the contents
 * of a PDB file.
 */
struct file_list
{
	int		record_len;
	int		nextents;
	short int     * extent_list;
	unsigned int	linetab_offset;
	unsigned int	linetab_len;
};

/*
 * These are the structures that represent how the file table is set up
 * within the PDB file.
 */
struct filetab_hdr
{
  unsigned short	tab1_file;
  unsigned short	tab2_file;
  unsigned short	gsym_file;
  unsigned short	padding;
  unsigned int		ftab_len;
  unsigned int		fofftab_len;
  unsigned int		hash_len;
  unsigned int		strtab_len;
};

struct file_ent
{
  unsigned int		reserved1;
  unsigned short	datasect_segment;
  unsigned short	reserved2;
  unsigned int		datasect_offset;
  unsigned int		datasect_size;
  unsigned int		datasect_flags;
  unsigned short	reserved3;
  unsigned short	index;
  unsigned short	num6a;
  unsigned short	file_number;
  unsigned int		linetab_offset;
  unsigned int		linetab_len;
  unsigned int		num9;
  unsigned int		num10;
  unsigned int		num11;
  unsigned char		filename[1];
};

/*
 ********************************************************************
 */
struct deferred_debug_info
{
	struct deferred_debug_info	* next;
	char				* load_addr;
	char				* module_name;
	char				* dbg_info;
	int				  dbg_size;
        HMODULE                         module;
	PIMAGE_DEBUG_DIRECTORY           dbgdir;
        PIMAGE_SECTION_HEADER	          sectp;
	int				  nsect;
	short int			  dbg_index;			
	char				  loaded;
};

struct deferred_debug_info * dbglist = NULL;

/*
 * A simple macro that tells us whether a given COFF symbol is a
 * function or not.
 */
#define N_TMASK                             0x0030
#define IMAGE_SYM_DTYPE_FUNCTION            2
#define N_BTSHFT                            4
#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT))


/*
 * This is what we are looking for in the COFF symbols.
 */
#define IMAGE_SYM_CLASS_EXTERNAL            0x2
#define IMAGE_SYM_CLASS_STATIC              0x3
#define IMAGE_SYM_CLASS_FILE                0x67

static 
struct datatype * DEBUG_GetCVType(int typeno)
{
  struct datatype * dt = NULL;

  /*
   * Convert Codeview type numbers into something we can grok internally.
   * Numbers < 0x1000 are all fixed builtin types.  Numbers from 0x1000 and
   * up are all user defined (structs, etc).
   */
  if( typeno < 0x1000 )
    {
      if( typeno < MAX_BUILTIN_TYPES )
	{
	  dt = cv_basic_types[typeno];
	}
    }
  else
    {
      if( typeno - 0x1000 < num_cv_defined_types )
	{
	  dt = cv_defined_types[typeno - 0x1000];
	} 
    }

  return dt;
}

static int
DEBUG_ParseTypeTable(char * table, int len)
{
  int				  arr_max;
  int				  curr_type;
  enum debug_type		  fieldtype;
  int				  elem_size;
  union any_size		  ptr;
  union any_size		  ptr2;
  struct datatype		* subtype;
  char				  symname[256];
  union codeview_type		* type;
  union codeview_type		* type2;
  struct datatype		* typeptr;

  curr_type = 0x1000;

  ptr.c = (table + 16);
  while( ptr.c - table < len )
    {
      type = (union codeview_type *) ptr.c;

      if( curr_type - 0x1000 >= num_cv_defined_types )
	{
	  num_cv_defined_types += 0x100;
	  cv_defined_types = (struct datatype **) DBG_realloc(cv_defined_types,
		  num_cv_defined_types * sizeof(struct datatype *));
	  memset(cv_defined_types + num_cv_defined_types - 0x100,
		 0,
		 0x100 * sizeof(struct datatype *));
	  if( cv_defined_types == NULL )
	    {
	      return FALSE;
	    }
	}

      switch(type->generic.id)
	{
	case LF_POINTER:
	  cv_defined_types[curr_type - 0x1000] = 
	    DEBUG_FindOrMakePointerType(DEBUG_GetCVType(type->pointer.datatype));
	  break;
	case LF_ARRAY:
	  if( type->array.arrlen >= 0x8000 )
	    {
	      /*
	       * This is a numeric leaf, I am too lazy to handle this right
	       * now.
	       */
	      fprintf(stderr, "Ignoring large numberic leaf.\n");
	      break;
	    }
	  if( type->array.namelen != 0 )
	    {
	      memset(symname, 0, sizeof(symname));
	      memcpy(symname, type->array.name, type->array.namelen);
	      typeptr = DEBUG_NewDataType(DT_ARRAY, symname);
	    }
	  else
	    {
	      typeptr = DEBUG_NewDataType(DT_ARRAY, NULL);
	    }
	  cv_defined_types[curr_type - 0x1000] = typeptr;

	  subtype = DEBUG_GetCVType(type->array.elemtype);
	  if(    (subtype == NULL)
	      || (elem_size = DEBUG_GetObjectSize(subtype)) == 0 )
	    {
	      arr_max = 0;
	    }
	  else
	    {
	      arr_max = type->array.arrlen / DEBUG_GetObjectSize(subtype);
	    }

	  DEBUG_SetArrayParams(typeptr, 0, arr_max, subtype);
	  break;
	case LF_FIELDLIST:
	  /*
	   * This is where the basic list of fields is defined for
	   * structures and classes.
	   *
	   * First, we need to look ahead and see whether we are building
	   * a fieldlist for an enum or a struct.
	   */
	  ptr2.i = ptr.i + 1;
	  type2 = (union codeview_type *) ptr2.c;
	  if( type2->member.id == LF_MEMBER )
	    {
	      typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
	      fieldtype = DT_STRUCT;
	    }
	  else if( type2->member.id == LF_ENUMERATE )
	    {
	      typeptr = DEBUG_NewDataType(DT_ENUM, NULL);
	      fieldtype = DT_ENUM;
	    }
	  else
	    {
	      break;
	    }

	  cv_defined_types[curr_type - 0x1000] = typeptr;
	  while( ptr2.c < (ptr.c + ((type->generic.len + 3) & ~3)) )
	    {
	      type2 = (union codeview_type *) ptr2.c;
	      if( type2->member.id == LF_MEMBER && fieldtype == DT_STRUCT )
		{
		  memset(symname, 0, sizeof(symname));
		  memcpy(symname, type2->member.name, type2->member.namelen);
		  
		  subtype = DEBUG_GetCVType(type2->member.type);
		  elem_size = 0;
		  if( subtype != NULL )
		    {
		      elem_size = DEBUG_GetObjectSize(subtype);
		    }
		  
		  if( type2->member.offset >= 0x8000 )
		    {
		      /*
		       * This is a numeric leaf, I am too lazy to handle this right
		       * now.
		       */
		      fprintf(stderr, "Ignoring large numberic leaf.\n");
		    }
		  else
		    {
		      DEBUG_AddStructElement(typeptr, symname, subtype, 
					     type2->member.offset << 3,
					     elem_size << 3);
		    }
		}
	      else if( type2->member.id == LF_ENUMERATE && fieldtype == DT_ENUM )
		{
		  memset(symname, 0, sizeof(symname));
		  memcpy(symname, type2->enumerate.name, type2->enumerate.namelen);
		  
		  if( type2->enumerate.value >= 0x8000 )
		    {
		      /*
		       * This is a numeric leaf, I am too lazy to handle this right
		       * now.
		       */
		      fprintf(stderr, "Ignoring large numberic leaf.\n");
		    }
		  else
		    {
		      DEBUG_AddStructElement(typeptr, symname, NULL, 
					     type2->enumerate.value, 0);
		    }
		}
	      else
		{
		  /*
		   * Something else I have never seen before.  Either wrong type of
		   * object in the fieldlist, or some other problem which I wouldn't
		   * really know how to handle until it came up.
		   */
		  fprintf(stderr, "Unexpected entry in fieldlist\n");
		  break;
		}


	      ptr2.c += ((type2->member.namelen + 9 + 3) & ~3);
	    }
	  break;
	case LF_STRUCTURE:
	case LF_CLASS:
	  if( type->structure.structlen >= 0x8000 )
	    {
	      /*
	       * This is a numeric leaf, I am too lazy to handle this right
	       * now.
	       */
	      fprintf(stderr, "Ignoring large numberic leaf.\n");
	      break;
	    }
	  memset(symname, 0, sizeof(symname));
	  memcpy(symname, type->structure.name, type->structure.namelen);
	  if( strcmp(symname, "__unnamed") == 0 )
	    {
	      typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
	    }
	  else
	    {
	      typeptr = DEBUG_NewDataType(DT_STRUCT, symname);
	    }
	  cv_defined_types[curr_type - 0x1000] = typeptr;

	  /*
	   * Now copy the relevant bits from the fieldlist that we specified.
	   */
	  subtype = DEBUG_GetCVType(type->structure.fieldlist);

	  if( subtype != NULL )
	    {
	      DEBUG_SetStructSize(typeptr, type->structure.structlen);
	      DEBUG_CopyFieldlist(typeptr, subtype);
	    }
	  break;
	case LF_UNION:
	  if( type->t_union.un_len >= 0x8000 )
	    {
	      /*
	       * This is a numeric leaf, I am too lazy to handle this right
	       * now.
	       */
	      fprintf(stderr, "Ignoring large numberic leaf.\n");
	      break;
	    }
	  memset(symname, 0, sizeof(symname));
	  memcpy(symname, type->t_union.name, type->t_union.namelen);

	  if( strcmp(symname, "__unnamed") == 0 )
	    {
	      typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
	    }
	  else
	    {
	      typeptr = DEBUG_NewDataType(DT_STRUCT, symname);
	    }

	  cv_defined_types[curr_type - 0x1000] = typeptr;

	  /*
	   * Now copy the relevant bits from the fieldlist that we specified.
	   */
	  subtype = DEBUG_GetCVType(type->t_union.field);

	  if( subtype != NULL )
	    {
	      DEBUG_SetStructSize(typeptr, type->t_union.un_len);
	      DEBUG_CopyFieldlist(typeptr, subtype);
	    }
	  break;
	case LF_BITFIELD:
	  typeptr = DEBUG_NewDataType(DT_BITFIELD, NULL);
	  cv_defined_types[curr_type - 0x1000] = typeptr;
	  DEBUG_SetBitfieldParams(typeptr, type->bitfield.bitoff,
				  type->bitfield.nbits, 
				  DEBUG_GetCVType(type->bitfield.type));
	  break;
	case LF_ENUMERATION:
	  memset(symname, 0, sizeof(symname));
	  memcpy(symname, type->enumeration.name, type->enumeration.namelen);
	  typeptr = DEBUG_NewDataType(DT_ENUM, symname);
	  cv_defined_types[curr_type - 0x1000] = typeptr;

	  /*
	   * Now copy the relevant bits from the fieldlist that we specified.
	   */
	  subtype = DEBUG_GetCVType(type->enumeration.field);

	  if( subtype != NULL )
	    {
	      DEBUG_CopyFieldlist(typeptr, subtype);
	    }
	  break;
	case LF_DIMARRAY:
	default:
	  break;
	}
      curr_type++;
      ptr.c += (type->generic.len + 3) & ~3;
    }

  return TRUE;
}

void
DEBUG_InitCVDataTypes()
{
  /*
   * These are the common builtin types that are used by VC++.
   */
  cv_basic_types[T_NOTYPE] = NULL;
  cv_basic_types[T_ABS] = NULL;
  cv_basic_types[T_VOID] = DEBUG_NewDataType(DT_BASIC, "void");
  cv_basic_types[T_CHAR] = DEBUG_NewDataType(DT_BASIC, "char");
  cv_basic_types[T_SHORT] = DEBUG_NewDataType(DT_BASIC, "short int");
  cv_basic_types[T_LONG] = DEBUG_NewDataType(DT_BASIC, "long int");
  cv_basic_types[T_QUAD] = DEBUG_NewDataType(DT_BASIC, "long long int");
  cv_basic_types[T_UCHAR] = DEBUG_NewDataType(DT_BASIC, "unsigned char");
  cv_basic_types[T_USHORT] = DEBUG_NewDataType(DT_BASIC, "short unsigned int");
  cv_basic_types[T_ULONG] = DEBUG_NewDataType(DT_BASIC, "long unsigned int");
  cv_basic_types[T_UQUAD] = DEBUG_NewDataType(DT_BASIC, "long long unsigned int");
  cv_basic_types[T_REAL32] = DEBUG_NewDataType(DT_BASIC, "float");
  cv_basic_types[T_REAL64] = DEBUG_NewDataType(DT_BASIC, "double");
  cv_basic_types[T_RCHAR] = DEBUG_NewDataType(DT_BASIC, "char");
  cv_basic_types[T_WCHAR] = DEBUG_NewDataType(DT_BASIC, "short");
  cv_basic_types[T_INT4] = DEBUG_NewDataType(DT_BASIC, "int");
  cv_basic_types[T_UINT4] = DEBUG_NewDataType(DT_BASIC, "unsigned int");

  cv_basic_types[T_32PVOID] = DEBUG_FindOrMakePointerType(cv_basic_types[T_VOID]);
  cv_basic_types[T_32PCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_CHAR]);
  cv_basic_types[T_32PSHORT] = DEBUG_FindOrMakePointerType(cv_basic_types[T_SHORT]);
  cv_basic_types[T_32PLONG] = DEBUG_FindOrMakePointerType(cv_basic_types[T_LONG]);
  cv_basic_types[T_32PQUAD] = DEBUG_FindOrMakePointerType(cv_basic_types[T_QUAD]);
  cv_basic_types[T_32PUCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_UCHAR]);
  cv_basic_types[T_32PUSHORT] = DEBUG_FindOrMakePointerType(cv_basic_types[T_USHORT]);
  cv_basic_types[T_32PULONG] = DEBUG_FindOrMakePointerType(cv_basic_types[T_ULONG]);
  cv_basic_types[T_32PUQUAD] = DEBUG_FindOrMakePointerType(cv_basic_types[T_UQUAD]);
  cv_basic_types[T_32PREAL32] = DEBUG_FindOrMakePointerType(cv_basic_types[T_REAL32]);
  cv_basic_types[T_32PREAL64] = DEBUG_FindOrMakePointerType(cv_basic_types[T_REAL64]);
  cv_basic_types[T_32PRCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_RCHAR]);
  cv_basic_types[T_32PWCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_WCHAR]);
  cv_basic_types[T_32PINT4] = DEBUG_FindOrMakePointerType(cv_basic_types[T_INT4]);
  cv_basic_types[T_32PUINT4] = DEBUG_FindOrMakePointerType(cv_basic_types[T_UINT4]);
}

/*
 * In this function, we keep track of deferred debugging information
 * that we may need later if we were to need to use the internal debugger.
 * We don't fully process it here for performance reasons.
 */
int
DEBUG_RegisterDebugInfo( HMODULE hModule, const char *module_name)
{
  int			  has_codeview = FALSE;
  int			  rtn = FALSE;
  int			  orig_size;
  PIMAGE_DEBUG_DIRECTORY dbgptr;
  u_long v_addr, size;
  PIMAGE_NT_HEADERS	  nth  = PE_HEADER(hModule);

  size = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  if (size) {
    v_addr = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
    dbgptr = (PIMAGE_DEBUG_DIRECTORY) (hModule + v_addr);
    orig_size = size;
    for(; size >= sizeof(*dbgptr); size -= sizeof(*dbgptr), dbgptr++ )
    {
      switch(dbgptr->Type)
	{
	case IMAGE_DEBUG_TYPE_CODEVIEW:
	case IMAGE_DEBUG_TYPE_MISC:
	  has_codeview = TRUE;
	  break;
	}
    }

    size = orig_size;
    dbgptr = (PIMAGE_DEBUG_DIRECTORY) (hModule + v_addr);
    for(; size >= sizeof(*dbgptr); size -= sizeof(*dbgptr), dbgptr++ )
    {
      switch(dbgptr->Type)
	{
	case IMAGE_DEBUG_TYPE_COFF:
	  /*
	   * If we have both codeview and COFF debug info, ignore the
	   * coff debug info as  it would just confuse us, and it is 
	   * less complete.
	   *
	   * FIXME - this is broken - if we cannot find the PDB file, then
	   * we end up with no debugging info at all.  In this case, we
	   * should use the COFF info as a backup.
	   */
	  if( has_codeview )
	    {
	      break;
	    }
	case IMAGE_DEBUG_TYPE_CODEVIEW:
	case IMAGE_DEBUG_TYPE_MISC:
	  /*
	   * This is usually an indirection to a .DBG file.
	   * This is similar to (but a slightly older format) from the
	   * PDB file.
	   *
	   * First check to see if the image was 'stripped'.  If so, it
	   * means that this entry points to a .DBG file.  Otherwise,
	   * it just points to itself, and we can ignore this.
	   */






          if(   (dbgptr->Type != IMAGE_DEBUG_TYPE_MISC) ||
                (PE_HEADER(hModule)->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0 )
            {
                char                 fn[PATH_MAX];
                int                  fd = -1;
                DOS_FULL_NAME        full_name;
                struct deferred_debug_info*      deefer = (struct deferred_debug_info *) DBG_alloc(sizeof(*deefer));
 
                deefer->module    = hModule;
                deefer->load_addr = (char *)hModule;
 
                /*
                 * Read the important bits.  What we do after this depends
                 * upon the type, but this is always enough so we are able
                 * to proceed if we know what we need to do next.
                 */                  
                /* basically, the PE loader maps all sections (data, resources...), but doesn't map
                 * the DataDirectory array's content. One its entry contains the *beloved*
                 * debug information. (Note the DataDirectory is mapped, not its content)
                 */
 
                 if (GetModuleFileNameA(hModule, fn, sizeof(fn)) > 0 &&
                    DOSFS_GetFullName(fn, TRUE, &full_name) &&
                    (fd = open(full_name.long_name, O_RDONLY)) > 0)
                {
                    deefer->dbg_info = mmap(NULL, dbgptr->SizeOfData,
                                            PROT_READ, MAP_PRIVATE, fd, dbgptr->PointerToRawData);
                    close(fd);
                    if( deefer->dbg_info == (char *) 0xffffffff )
                    {
                        DBG_free(deefer);
                        break;
                    }
                }
                else
                {
                    DBG_free(deefer);
                    fprintf(stderr, " (not mapped: fn=%s, lfn=%s, fd=%d)", fn, full_name.long_name, fd);
                    break;
                }
                deefer->dbg_size = dbgptr->SizeOfData;
                deefer->dbgdir = dbgptr;
                deefer->next = dbglist;
                deefer->loaded = FALSE;
                deefer->dbg_index = DEBUG_next_index;
                deefer->module_name = DBG_strdup(module_name);

                deefer->sectp = PE_SECTIONS(hModule);
                deefer->nsect = PE_HEADER(hModule)->FileHeader.NumberOfSections;

                dbglist = deefer;
            }
	  break;
#if 0
	default:
#endif
	}
    }
    DEBUG_next_index++;
  }
  /* look for .stabs/.stabstr sections */
  {
    PIMAGE_SECTION_HEADER      pe_seg = PE_SECTIONS(hModule);
    int i,stabsize=0,stabstrsize=0;
    unsigned int stabs=0,stabstr=0;
    
    for (i=0;i<nth->FileHeader.NumberOfSections;i++) {
      if (!strcasecmp(pe_seg[i].Name,".stab")) {
	stabs = pe_seg[i].VirtualAddress;
	stabsize = pe_seg[i].SizeOfRawData;
      }
      if (!strncasecmp(pe_seg[i].Name,".stabstr",8)) {
	stabstr = pe_seg[i].VirtualAddress;
	stabstrsize = pe_seg[i].SizeOfRawData;
      }
    }
    if (stabstrsize && stabsize) {
#ifdef _WE_SUPPORT_THE_STAB_TYPES_USED_BY_MINGW_TOO
      /* Won't work currently, since MINGW32 uses some special typedefs
       * which we do not handle yet. Support for them is a bit difficult.
       */
      DEBUG_ParseStabs(hModule,0,stabs,stabsize,stabstr,stabstrsize);
#endif
      fprintf(stderr,"(stabs not loaded)");
    }
  }
  return (rtn);
}

/*
 * ELF modules are also entered into the list - this is so that we
 * can make 'info shared' types of displays possible.
 */
int
DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, char * name)
{
  struct deferred_debug_info * deefer;

  deefer = (struct deferred_debug_info *) DBG_alloc(sizeof(*deefer));
  deefer->module = 0;
  
  /*
   * Read the important bits.  What we do after this depends
   * upon the type, but this is always enough so we are able
   * to proceed if we know what we need to do next.
   */
  deefer->dbg_size = size;
  deefer->dbg_info = (char *) NULL;
  
  deefer->load_addr = (char *) load_addr;
  deefer->dbgdir = NULL;
  deefer->next = dbglist;
  deefer->loaded = TRUE;
  deefer->dbg_index = DEBUG_next_index;
  deefer->module_name = DBG_strdup(name);
  dbglist = deefer;

  DEBUG_next_index++;

  return (TRUE);
}



/*
 * Process COFF debugging information embedded in a Win32 application.
 *
 */
static
int
DEBUG_ProcessCoff(struct deferred_debug_info * deefer)
{
  struct CoffAuxSection * aux;
  struct CoffDebug   * coff;
  struct CoffFiles   * coff_files = NULL;
  struct CoffLinenum * coff_linetab;
  char		     * coff_strtab;
  struct CoffSymbol  * coff_sym;
  struct CoffSymbol  * coff_symbol;
  struct CoffFiles   * curr_file = NULL;
  int		       i;
  int		       j;
  int		       k;
  struct CoffLinenum * linepnt;
  int		       linetab_indx;
  char		       namebuff[9];
  char		     * nampnt;
  int		       naux;
  DBG_ADDR	       new_addr;
  int		       nfiles = 0;
  int		       nfiles_alloc = 0;
  struct CoffFiles     orig_file;
  int		       rtn = FALSE;
  char		     * this_file = NULL;

  coff = (struct CoffDebug *) deefer->dbg_info;

  coff_symbol = (struct CoffSymbol *) ((unsigned int) coff + coff->SymbolOffset);
  coff_linetab = (struct CoffLinenum *) ((unsigned int) coff + coff->LinenumberOffset);
  coff_strtab = (char *) ((unsigned int) coff_symbol + 18*coff->N_Sym);

  linetab_indx = 0;

  for(i=0; i < coff->N_Sym; i++ )
    {
      /*
       * We do this because some compilers (i.e. gcc) incorrectly
       * pad the structure up to a 4 byte boundary.  The structure
       * is really only 18 bytes long, so we have to manually make sure
       * we get it right.
       *
       * FIXME - there must be a way to have autoconf figure out the
       * correct compiler option for this.  If it is always gcc, that
       * makes life simpler, but I don't want to force this.
       */
      coff_sym = (struct CoffSymbol *) ((unsigned int) coff_symbol + 18*i);
      naux = coff_sym->NumberOfAuxSymbols;

      if( coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE )
	{
	  if( nfiles + 1 >= nfiles_alloc )
	    {
	      nfiles_alloc += 10;
	      coff_files = (struct CoffFiles *) DBG_realloc(coff_files,
			nfiles_alloc * sizeof(struct CoffFiles));
	    }
	  curr_file = coff_files + nfiles;
	  nfiles++;
	  curr_file->startaddr = 0xffffffff;
	  curr_file->endaddr   = 0;
	  curr_file->filename =  ((char *) coff_sym) + 18;
	  curr_file->linetab_offset = -1;
	  curr_file->linecnt = 0;
	  curr_file->entries = NULL;
	  curr_file->neps = curr_file->neps_alloc = 0;
#if 0
	  fprintf(stderr,"New file %s\n", curr_file->filename);
#endif
	  i += naux;
	  continue;
	}

      /*
       * This guy marks the size and location of the text section
       * for the current file.  We need to keep track of this so
       * we can figure out what file the different global functions
       * go with.
       */
      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
	  && (naux != 0)
	  && (coff_sym->Type == 0)
	  && (coff_sym->SectionNumber == 1) )
	{
	  aux = (struct CoffAuxSection *) ((unsigned int) coff_sym + 18);

	  if( curr_file->linetab_offset != -1 )
	    {
#if 0
	      fprintf(stderr, "Duplicating sect from %s: %x %x %x %d %d\n",
		      curr_file->filename,
		      aux->Length,
		      aux->NumberOfRelocations,
		      aux->NumberOfLinenumbers,
		      aux->Number,
		      aux->Selection);
	      fprintf(stderr, "More sect %d %x %d %d %d\n", 
		      coff_sym->SectionNumber,
		      coff_sym->Value,
		      coff_sym->Type,
		      coff_sym->StorageClass,
		      coff_sym->NumberOfAuxSymbols);
#endif

	      /*
	       * Save this so we can copy bits from it.
	       */
	      orig_file = *curr_file;

	      /*
	       * Duplicate the file entry.  We have no way to describe
	       * multiple text sections in our current way of handling things.
	       */
	      if( nfiles + 1 >= nfiles_alloc )
		{
		  nfiles_alloc += 10;
		  coff_files = (struct CoffFiles *) DBG_realloc(coff_files,
							     nfiles_alloc * sizeof(struct CoffFiles));
		}
	      curr_file = coff_files + nfiles;
	      nfiles++;
	      curr_file->startaddr = 0xffffffff;
	      curr_file->endaddr   = 0;
	      curr_file->filename = orig_file.filename;
	      curr_file->linetab_offset = -1;
	      curr_file->linecnt = 0;
	      curr_file->entries = NULL;
	      curr_file->neps = curr_file->neps_alloc = 0;
	    }
#if 0
	  else
	    {
	      fprintf(stderr, "New text sect from %s: %x %x %x %d %d\n",
		      curr_file->filename,
		      aux->Length,
		      aux->NumberOfRelocations,
		      aux->NumberOfLinenumbers,
		      aux->Number,
		      aux->Selection);
	    }
#endif

	  if( curr_file->startaddr > coff_sym->Value )
	    {
	      curr_file->startaddr = coff_sym->Value;
	    }
	  
	  if( curr_file->startaddr > coff_sym->Value )
	    {
	      curr_file->startaddr = coff_sym->Value;
	    }
	  
	  if( curr_file->endaddr < coff_sym->Value + aux->Length )
	    {
	      curr_file->endaddr = coff_sym->Value + aux->Length;
	    }
	  
	  curr_file->linetab_offset = linetab_indx;
	  curr_file->linecnt = aux->NumberOfLinenumbers;
	  linetab_indx += aux->NumberOfLinenumbers;
	  i += naux;
	  continue;
	}

      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
	  && (naux == 0)
	  && (coff_sym->SectionNumber == 1) )
	{
	  /*
	   * This is a normal static function when naux == 0.
	   * Just register it.  The current file is the correct
	   * one in this instance.
	   */
	  if( coff_sym->N.Name.NotLong )
	    {
	      memcpy(namebuff, coff_sym->N.ShortName, 8);
	      namebuff[8] = '\0';
	      nampnt = &namebuff[0];
	    }
	  else
	    {
	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
	    }

	  if( nampnt[0] == '_' )
	    {
	      nampnt++;
	    }

	  new_addr.seg = 0;
	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);

	  if( curr_file->neps + 1 >= curr_file->neps_alloc )
	    {
	      curr_file->neps_alloc += 10;
	      curr_file->entries = (struct name_hash **) 
		DBG_realloc(curr_file->entries, 
			 curr_file->neps_alloc * sizeof(struct name_hash *));
	    }
#if 0
	  fprintf(stderr,"\tAdding static symbol %s\n", nampnt);
#endif
	  curr_file->entries[curr_file->neps++] =
	    DEBUG_AddSymbol( nampnt, &new_addr, this_file, SYM_WIN32 );
	  i += naux;
	  continue;
	}

      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
	  && ISFCN(coff_sym->Type)
          && (coff_sym->SectionNumber > 0) )
	{
	  if( coff_sym->N.Name.NotLong )
	    {
	      memcpy(namebuff, coff_sym->N.ShortName, 8);
	      namebuff[8] = '\0';
	      nampnt = &namebuff[0];
	    }
	  else
	    {
	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
	    }


	  if( nampnt[0] == '_' )
	    {
	      nampnt++;
	    }

	  new_addr.seg = 0;
	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);

#if 0
	  fprintf(stderr, "%d: %x %s\n", i, new_addr.off, nampnt);

	  fprintf(stderr,"\tAdding global symbol %s\n", nampnt);
#endif

	  /*
	   * Now we need to figure out which file this guy belongs to.
	   */
	  this_file = NULL;
	  for(j=0; j < nfiles; j++)
	    {
	      if( coff_files[j].startaddr <= coff_sym->Value
		  && coff_files[j].endaddr > coff_sym->Value )
		{
		  this_file = coff_files[j].filename;
		  break;
		}
	    }
	  if( coff_files[j].neps + 1 >= coff_files[j].neps_alloc )
	    {
	      coff_files[j].neps_alloc += 10;
	      coff_files[j].entries = (struct name_hash **) 
		DBG_realloc(coff_files[j].entries, 
			 coff_files[j].neps_alloc * sizeof(struct name_hash *));
	    }
	  coff_files[j].entries[coff_files[j].neps++] =
	    DEBUG_AddSymbol( nampnt, &new_addr, this_file, SYM_WIN32 );
	  i += naux;
	  continue;
	}

      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
          && (coff_sym->SectionNumber > 0) )
	{
	  /*
	   * Similar to above, but for the case of data symbols.
	   * These aren't treated as entrypoints.
	   */
	  if( coff_sym->N.Name.NotLong )
	    {
	      memcpy(namebuff, coff_sym->N.ShortName, 8);
	      namebuff[8] = '\0';
	      nampnt = &namebuff[0];
	    }
	  else
	    {
	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
	    }


	  if( nampnt[0] == '_' )
	    {
	      nampnt++;
	    }

	  new_addr.seg = 0;
	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);

#if 0
	  fprintf(stderr, "%d: %x %s\n", i, new_addr.off, nampnt);

	  fprintf(stderr,"\tAdding global data symbol %s\n", nampnt);
#endif

	  /*
	   * Now we need to figure out which file this guy belongs to.
	   */
	  DEBUG_AddSymbol( nampnt, &new_addr, NULL, SYM_WIN32 );
	  i += naux;
	  continue;
	}
	  
      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
	  && (naux == 0) )
	{
	  /*
	   * Ignore these.  They don't have anything to do with
	   * reality.
	   */
	  i += naux;
	  continue;
	}

#if 0
      fprintf(stderr,"Skipping unknown entry %d %d %d\n", coff_sym->StorageClass, 
	      coff_sym->SectionNumber, naux);
#endif

      /*
       * For now, skip past the aux entries.
       */
      i += naux;
      
    }
    
  /*
   * OK, we now should have a list of files, and we should have a list
   * of entrypoints.  We need to sort the entrypoints so that we are
   * able to tie the line numbers with the given functions within the
   * file.
   */
  if( coff_files != NULL )
    {
      for(j=0; j < nfiles; j++)
	{
	  if( coff_files[j].entries != NULL )
	    {
	      qsort(coff_files[j].entries, coff_files[j].neps,
		    sizeof(struct name_hash *), DEBUG_cmp_sym);
	    }
	}

      /*
       * Now pick apart the line number tables, and attach the entries
       * to the given functions.
       */
      for(j=0; j < nfiles; j++)
	{
	  i = 0;
	  if( coff_files[j].neps != 0 )
	    for(k=0; k < coff_files[j].linecnt; k++)
	    {
	      /*
	       * Another monstrosity caused by the fact that we are using
	       * a 6 byte structure, and gcc wants to pad structures to 4 byte
	       * boundaries.  Otherwise we could just index into an array.
	       */
	      linepnt = (struct CoffLinenum *) 
		((unsigned int) coff_linetab + 
		 6*(coff_files[j].linetab_offset + k));
	      /*
	       * If we have spilled onto the next entrypoint, then
	       * bump the counter..
	       */
	      while(TRUE)
		{
		  if (i+1 >= coff_files[j].neps) break;
		  DEBUG_GetSymbolAddr(coff_files[j].entries[i+1], &new_addr);
		  if( (((unsigned int)deefer->load_addr +
		        linepnt->VirtualAddr) >= new_addr.off) )
		  {
		      i++;
		  } else break;
		}

	      /*
	       * Add the line number.  This is always relative to the
	       * start of the function, so we need to subtract that offset
	       * first.
	       */
	      DEBUG_GetSymbolAddr(coff_files[j].entries[i], &new_addr);
	      DEBUG_AddLineNumber(coff_files[j].entries[i], 
				  linepnt->Linenum,
				  (unsigned int) deefer->load_addr 
				  + linepnt->VirtualAddr 
				  - new_addr.off);
	    }
	}
    }

  rtn = TRUE;

  if( coff_files != NULL )
    {
      for(j=0; j < nfiles; j++)
	{
	  if( coff_files[j].entries != NULL )
	    {
	      DBG_free(coff_files[j].entries);
	    }
	}
      DBG_free(coff_files);
    }

  return (rtn);

}

/*
 * Process a codeview line number table.  Digestify the thing so that
 * we can easily reference the thing when we process the rest of
 * the information.
 */
static struct codeview_linetab_hdr *
DEBUG_SnarfLinetab(char			     * linetab,
		   int			       size)
{
  int				  file_segcount;
  char				  filename[PATH_MAX];
  unsigned int			* filetab;
  char				* fn;
  int				  i;
  int				  k;
  struct codeview_linetab_hdr   * lt_hdr;
  unsigned int			* lt_ptr;
  int				  nfile;
  int				  nseg;
  union any_size		  pnt;
  union any_size		  pnt2;
  struct startend		* start;
  int				  this_seg;

  /*
   * Now get the important bits.
   */
  pnt.c = linetab;
  nfile = *pnt.s++;
  nseg = *pnt.s++;

  filetab = (unsigned int *) pnt.c;

  /*
   * Now count up the number of segments in the file.
   */
  nseg = 0;
  for(i=0; i<nfile; i++)
    {
      pnt2.c = linetab + filetab[i];
      nseg += *pnt2.s;
    }

  /*
   * Next allocate the header we will be returning.
   * There is one header for each segment, so that we can reach in
   * and pull bits as required.
   */
  lt_hdr = (struct codeview_linetab_hdr *) 
    DBG_alloc((nseg + 1) * sizeof(*lt_hdr));
  if( lt_hdr == NULL )
    {
      goto leave;
    }

  memset(lt_hdr, 0, sizeof(*lt_hdr) * (nseg+1));

  /*
   * Now fill the header we will be returning, one for each segment.
   * Note that this will basically just contain pointers into the existing
   * line table, and we do not actually copy any additional information
   * or allocate any additional memory.
   */

  this_seg = 0;
  for(i=0; i<nfile; i++)
    {
      /*
       * Get the pointer into the segment information.
       */
      pnt2.c = linetab + filetab[i];
      file_segcount = *pnt2.s;

      pnt2.ui++;
      lt_ptr = (unsigned int *) pnt2.c;
      start = (struct startend *) (lt_ptr + file_segcount);

      /*
       * Now snarf the filename for all of the segments for this file.
       */
      fn = (unsigned char *) (start + file_segcount);
      memset(filename, 0, sizeof(filename));
      memcpy(filename, fn + 1, *fn);
      fn = DBG_strdup(filename);

      for(k = 0; k < file_segcount; k++, this_seg++)
	{
	  pnt2.c = linetab + lt_ptr[k];
	  lt_hdr[this_seg].start      = start[k].start;
	  lt_hdr[this_seg].end	      = start[k].end;
	  lt_hdr[this_seg].sourcefile = fn;
	  lt_hdr[this_seg].segno      = *pnt2.s++;
	  lt_hdr[this_seg].nline      = *pnt2.s++;
	  lt_hdr[this_seg].offtab     =  pnt2.ui;
	  lt_hdr[this_seg].linetab    = (unsigned short *) 
	    (pnt2.ui + lt_hdr[this_seg].nline);
	}
    }

leave:

  return lt_hdr;

}

static int
DEBUG_SnarfCodeView(      struct deferred_debug_info * deefer,
			  char			     * cv_data,
			  int			       size,
			  struct codeview_linetab_hdr * linetab)
{
  struct name_hash	* curr_func = NULL;
  struct wine_locals	* curr_sym = NULL;
  int			  i;
  int			  j;
  int			  len;
  DBG_ADDR		  new_addr;
  int			  nsect;
  union any_size	  ptr;
  IMAGE_SECTION_HEADER  * sectp;
  union	codeview_symbol	* sym;
  char			  symname[PATH_MAX];
  struct name_hash	* thunk_sym = NULL;

  ptr.c = cv_data;
  nsect = deefer->nsect;
  sectp = deefer->sectp;

  /*
   * Skip over the first word.  Don't really know what it means, but
   * it is useless.
   */
  ptr.ui++;

  /*
   * Loop over the different types of records and whenever we
   * find something we are interested in, record it and move on.
   */
  while( ptr.c - cv_data < size )
    {
      sym = (union codeview_symbol *) ptr.c;

      if( sym->generic.len - sizeof(int) == (ptr.c - cv_data) )
	{
	  /*
	   * This happens when we have indirect symbols that VC++ 4.2
	   * sometimes uses when there isn't a line number table.
	   * We ignore it - we will process and enter all of the
	   * symbols in the global symbol table anyways, so there
	   * isn't much point in keeping track of all of this crap.
	   */
	  break;
	}

      memset(symname, 0, sizeof(symname));
      switch(sym->generic.id)
	{
	case S_GDATA:
	case S_LDATA:
	case S_PUB:
	  /*
	   * First, a couple of sanity checks.
	   */
	  if( sym->data.namelen == 0 )
	    {
	      break;
	    }

	  if( sym->data.seg == 0 || sym->data.seg > nsect )
	    {
	      break;
	    }

	  /*
	   * Global and local data symbols.  We don't associate these
	   * with any given source file.
	   */

	  memcpy(symname, sym->data.name, sym->data.namelen);
	  new_addr.seg = 0;
	  new_addr.type = DEBUG_GetCVType(sym->data.symtype);
	  new_addr.off = (unsigned int) deefer->load_addr + 
	    sectp[sym->data.seg - 1].VirtualAddress + 
	    sym->data.offset;
	  DEBUG_AddSymbol( symname, &new_addr, NULL, SYM_WIN32 | SYM_DATA );
	  break;
	case S_THUNK:
	  /*
	   * Sort of like a global function, but it just points
	   * to a thunk, which is a stupid name for what amounts to
	   * a PLT slot in the normal jargon that everyone else uses.
	   */
	  memcpy(symname, sym->thunk.name, sym->thunk.namelen);
	  new_addr.seg = 0;
	  new_addr.type = NULL;
	  new_addr.off = (unsigned int) deefer->load_addr + 
	    sectp[sym->thunk.segment - 1].VirtualAddress + 
	    sym->thunk.offset;
	  thunk_sym = DEBUG_AddSymbol( symname, &new_addr, NULL, 
				       SYM_WIN32 | SYM_FUNC);
	  DEBUG_SetSymbolSize(thunk_sym, sym->thunk.thunk_len);
	  break;
	case S_GPROC:
	case S_LPROC:
	  /*
	   * Global and static functions.
	   */
	  memcpy(symname, sym->proc.name, sym->proc.namelen);
	  new_addr.seg = 0;
	  new_addr.type = DEBUG_GetCVType(sym->proc.proctype);
	  new_addr.off = (unsigned int) deefer->load_addr + 
	    sectp[sym->proc.segment - 1].VirtualAddress + 
	    sym->proc.offset;
	  /*
	   * See if we can find a segment that this goes with.  If so,
	   * it means that we also may have line number information
	   * for this function.
	   */
	  for(i=0; linetab[i].linetab != NULL; i++)
	    {
	      if(     ((unsigned int) deefer->load_addr 
		       + sectp[linetab[i].segno - 1].VirtualAddress 
		       + linetab[i].start <= new_addr.off)
		  &&  ((unsigned int) deefer->load_addr 
		       + sectp[linetab[i].segno - 1].VirtualAddress 
		       + linetab[i].end > new_addr.off) )
		{
		  break;
		}
	    }

 	  DEBUG_Normalize(curr_func);
	  if( linetab[i].linetab == NULL )
	    {
	      curr_func = DEBUG_AddSymbol( symname, &new_addr, NULL,
					   SYM_WIN32 | SYM_FUNC);
	    }
	  else
	    {
	      /*
	       * First, create the entry.  Then dig through the linetab
	       * and add whatever line numbers are appropriate for this
	       * function.
	       */
	      curr_func = DEBUG_AddSymbol( symname, &new_addr, 
					   linetab[i].sourcefile,
					   SYM_WIN32 | SYM_FUNC);
	      for(j=0; j < linetab[i].nline; j++)
		{
		  if( linetab[i].offtab[j] >= sym->proc.offset 
		      && linetab[i].offtab[j] < sym->proc.offset 
		      + sym->proc.proc_len )
		    {
		      DEBUG_AddLineNumber(curr_func, linetab[i].linetab[j],
					  linetab[i].offtab[j] - sym->proc.offset);
		    }
		}

	    }

	  /*
	   * Add information about where we should set breakpoints
	   * in this function.
	   */
	  DEBUG_SetSymbolBPOff(curr_func, sym->proc.debug_start);
	  DEBUG_SetSymbolSize(curr_func, sym->proc.proc_len);
	  break;
	case S_BPREL:
	  /*
	   * Function parameters and stack variables.
	   */
	  memcpy(symname, sym->stack.name, sym->stack.namelen);
	  curr_sym = DEBUG_AddLocal(curr_func, 
			 0, 
			 sym->stack.offset, 
			 0, 
			 0, 
			 symname);
	  DEBUG_SetLocalSymbolType(curr_sym, DEBUG_GetCVType(sym->stack.symtype));
	  
	  break;
	default:
	  break;
	}

      /*
       * Adjust pointer to point to next entry, rounding up to a word
       * boundary.  MS preserving alignment?  Stranger things have
       * happened.
       */
      if( sym->generic.id == S_PROCREF
	  || sym->generic.id == S_DATAREF
	  || sym->generic.id == S_UNKNOWN )
	{
	  len = (sym->generic.len + 3) & ~3;
	  len += ptr.c[16] + 1;
	  ptr.c += (len + 3) & ~3;
	}
      else
	{
	  ptr.c += (sym->generic.len + 3) & ~3;
	}
    }

  if( linetab != NULL )
    {
      DBG_free(linetab);
    }

  return TRUE;
}


/*
 * Process PDB file which contains debug information.
 *
 * These are really weird beasts.  They are intended to be incrementally
 * updated by the incremental linker, and this means that you need to 
 * be able to remove and add information.  Thus the PDB file is sort of
 * like a block structured device, with a freelist and lists of extent numbers
 * that are used to get the relevant pieces.  In all cases seen so far, the
 * blocksize is always 0x400 bytes.  The header has a field which apparently
 * holds the blocksize, so if it ever changes we are safe.
 *
 * In general, every time we need to extract something from the pdb file,
 * it is easier to copy it into another buffer so we have the information
 * in one contiguous block rather than attempt to try and keep track of when
 * we need to grab another extent from the pdb file.
 *
 * The thing that is a real pain about some MS stuff is that they choose
 * data structures which are not representable in C.  Thus we have to
 * hack around and diddle pointers.
 */
/* static */
int
DEBUG_ProcessPDBFile(struct deferred_debug_info * deefer, char * full_filename)
{
  char			      * addr = (char *) 0xffffffff;
  unsigned int			blocksize;
  unsigned int			bufflen = 0;
  char			      * buffer = NULL;
  unsigned short	      * extent_table;
  int				fd = -1;
  struct file_ent	      * fent;
  char			        filename[MAX_PATHNAME_LEN];
  struct file_list	      * filelist = NULL;
  unsigned int			gsym_record = 0;
  char			      * gsymtab = NULL;
  struct filetab_hdr	      * hd;
  int				i;
  int				j;
  unsigned int			last_extent;
  struct codeview_linetab_hdr * linetab;
  unsigned int			nblocks;
  unsigned int			npair;
  unsigned int			offset;
  struct codeview_pdb_hdr     * pdbhdr;
  unsigned int		      * pnt;
  struct stat			statbuf;
  int				status;
  unsigned short	      * table;
  char			      * toc;
  unsigned int			toc_blocks;

  LocateDebugInfoFile(full_filename, filename);
  status = stat(filename, &statbuf);
  if( status == -1 )
    {
      fprintf(stderr, "-Unable to open .PDB file %s\n", filename);
      goto leave;
    }

  /*
   * Now open the file, so that we can mmap() it.
   */
  fd = open(filename, O_RDONLY);
  if( fd == -1 )
    {
      fprintf(stderr, "-Unable to open .DBG file %s\n", filename);
      goto leave;
    }


  /*
   * Now mmap() the file.
   */
  addr = mmap(0, statbuf.st_size, PROT_READ, 
	      MAP_PRIVATE, fd, 0);
  if( addr == (char *) 0xffffffff )
    {
      fprintf(stderr, "-Unable to mmap .DBG file %s\n", filename);
      goto leave;
    }

  /*
   * Now that we have the formalities over and done with, we need
   * to find the table of contents for the PDB file.
   */
  pdbhdr = (struct codeview_pdb_hdr *) addr;
  blocksize = pdbhdr->blocksize;
  last_extent = (statbuf.st_size + blocksize - 1) / blocksize;

  /*
   * The TOC itself isn't always contiguous, so we need to extract a few
   * extents from the file to form the TOC.
   */
  toc_blocks = (pdbhdr->toc_len + blocksize - 1) / blocksize;
  toc = (char *) DBG_alloc(toc_blocks * blocksize);
  table = pdbhdr->toc_ext;
  for(i=0; i < toc_blocks; i++)
    {
      memcpy(toc + blocksize*i, addr + table[i]*blocksize, blocksize);
    }

  /*
   * Next build our own table which will have the size and extent block
   * list for each record in the PDB file.
   *
   * The TOC starts out with the number of files.  Then it is followed by
   * (npair * 2*sizeof(int)) bytes of information, which are pairs of ints.
   * The first one is the size of the record (in bytes), and the second one
   * is something else which I haven't figured out yet.
   */
  pnt = (unsigned int *) toc;
  npair = *pnt++;
  extent_table = (unsigned short *) ((unsigned int) toc +
				     npair * 2 * sizeof(int) + sizeof(int));

  /*
   * Sanity check.
   */
  if( sizeof(int) + 2*sizeof(int)*npair > pdbhdr->toc_len )
    {
      goto leave;
    }
  
  filelist = (struct file_list *) DBG_alloc(npair * sizeof(*filelist));
  if( filelist == NULL )
    {
      goto leave;
    }
  memset(filelist, 0, npair * sizeof(*filelist));

  nblocks = 0;
  for(i=0; i < npair; i++)
    {
      filelist[i].record_len = pnt[i*2];
      filelist[i].nextents   = (filelist[i].record_len + blocksize - 1) 
	/ blocksize;
      filelist[i].extent_list = extent_table + nblocks;
      nblocks += filelist[i].nextents;

      /*
       * These get filled in later when we parse one of the records.
       */
      filelist[i].linetab_offset = 0;
      filelist[i].linetab_len = 0;
    }

  /*
   * OK, now walk through the various records and pick out the bits we
   * really want to see.  Some of the records are extra special, and
   * we need to handle these a little bit differently.
   */
  for(i=0; i < npair; i++)
    {
      if( filelist[i].record_len == 0xffffffff )
	{
	  continue;
	}

      /*
       * Make sure our buffer is large enough to hold the record.
       */
      if( bufflen < filelist[i].nextents * blocksize )
	{
	  bufflen = filelist[i].nextents * blocksize;
	  buffer = (char *) DBG_realloc(buffer, bufflen);
	}

      /*
       * Do this just for completeness.  It makes debugging easier
       * if we have a clean indication of where the record ends.
       */
      memset(buffer, 0, filelist[i].nextents * blocksize);

      /*
       * Next, build the record using the extent list.
       */
      for(j=0; j < filelist[i].nextents; j++)
	{
	  memcpy(buffer + j * blocksize,
		 addr + filelist[i].extent_list[j] * blocksize,
		 blocksize);
	}

      pnt = (unsigned int *) buffer;

      /*
       * OK, now figure out what to do with it.
       */

      /*
       * Always ignore the first entry.  It seems to contain a backup copy
       * of the TOC (the last time the file was modified??)
       */
      if( i == 0 )
	{
	  continue;
	}

      /* 
       * The second entry as a id block.  It contains a magic number
       * to identify the compiler, plus it also contains the timestamp
       * which must match the timestamp in the executable.  
       */
      if( i == 1 )
	{

	  if( ((*pnt != 19950623) && (*pnt != 19950814))
	      || (filelist[i].record_len != 0x24)
	      || (pnt[1] != ((struct CodeViewDebug *)(deefer->dbg_info))->cv_timestamp) )
	    {
	      goto leave;
	    }
	}

      /*
       * The third entry contains pointers to the global symbol table,
       * plus it also contains additional information about each record
       * in the PDB file.
       */
      if( i == 3 )
	{
	  hd = (struct filetab_hdr *) buffer;

	  gsym_record = hd->gsym_file;
	  gsymtab = (char *) DBG_alloc(filelist[gsym_record].nextents 
				      * blocksize);
	  memset(gsymtab, 0, filelist[gsym_record].nextents * blocksize);
	  
	  for(j=0; j < filelist[gsym_record].nextents; j++)
	    {
	      memcpy(gsymtab + j * blocksize,
		     addr + filelist[gsym_record].extent_list[j] * blocksize,
		     blocksize);
	    }

	  /*
	   * This record also contains information about where in the
	   * remaining records we will be able to find the start of the
	   * line number table.  We could locate that bit using heuristics,
	   * but since we have the info handy, we might as well use it.
	   */
	  offset = sizeof(*hd);
	  while(1==1)
	    {
	      fent = (struct file_ent *) (buffer + offset);
	      if( offset > hd->ftab_len )
		{
		  break;
		}

	      if( fent->file_number == 0 || fent->file_number >= npair )
		{
 		  break;
		}

	      filelist[fent->file_number].linetab_offset = 
		fent->linetab_offset;
	      filelist[fent->file_number].linetab_len = 
		fent->linetab_len;
	      /*
	       * Figure out the offset of the next entry.
	       * There is a fixed part of the record and a variable
	       * length filename which we must also skip past.
	       */
	      offset += ((unsigned int) &fent->filename - (unsigned int) fent)
		+ strlen(fent->filename) + 1;
	      offset += strlen(buffer+offset) + 1;
	      offset = (offset + 3) & ~3;
	    }
	}
      

      /*
       * Two different magic numbers used as dates.
       * These indicate the 'type' table.
       */
      if(       *pnt == 19950410
	     || *pnt == 19951122 )
	{
	  DEBUG_ParseTypeTable(buffer, filelist[i].record_len);
	  continue;
	}

      /*
       * This is something we really want to look at, since it contains
       * real debug info.  Anything that doesn't match this can be
       * ignored for now.
       */
      if( *pnt == 1 )
	{
	  /*
	   * First, snag the line table, if we have one.  This always
	   * occurs at the end of the record, so we take the linetab
	   * offset as the end of the normal part of the record.
	   */
	  linetab = NULL;
	  if( filelist[i].linetab_len != 0 )
	    {
	      linetab = DEBUG_SnarfLinetab(buffer + filelist[i].linetab_offset,
					   filelist[i].linetab_len);
	      DEBUG_SnarfCodeView(deefer, buffer,
				  filelist[i].linetab_offset,
				  linetab);
	    }
	  else
	    {
	      DEBUG_SnarfCodeView(deefer, buffer,
				  filelist[i].record_len,
				  linetab);
	    }
	  continue;
	}
    }

  /*
   * Finally, process the global symbol table itself.  There isn't
   * a line number component to this, so we just toss everything
   * into the mix and it all should work out.
   */
  if( gsym_record != 0 )
    {
      DEBUG_SnarfCodeView(deefer, gsymtab - sizeof(int), 
			  filelist[gsym_record].record_len,
			  NULL);
    }
  
leave:

  if( gsymtab != NULL )
    {
      DBG_free(gsymtab);
      gsymtab = NULL;
    }

  if( buffer != NULL )
    {
      DBG_free(buffer);
    }

  if( filelist != NULL )
    {
      DBG_free(filelist);
    }

  if( addr != (char *) 0xffffffff )
    {
      munmap(addr, statbuf.st_size);
    }

  if( fd != -1 )
    {
      close(fd);
    }

  return TRUE;
}

/*
 * Process DBG file which contains debug information.
 */
/* static */
int
DEBUG_ProcessDBGFile(struct deferred_debug_info * deefer, char * filename)
{
  char			      * addr = (char *) 0xffffffff;
  char			      * codeview;
  struct CV4_DirHead	      * codeview_dir;
  struct CV4_DirEnt	      * codeview_dent;
  PIMAGE_DEBUG_DIRECTORY	dbghdr;
  struct deferred_debug_info    deefer2;
  int				fd = -1;
  int				i;
  int				j;
  struct codeview_linetab_hdr * linetab;
  int				nsect;
  PIMAGE_SEPARATE_DEBUG_HEADER pdbg = NULL;
  IMAGE_SECTION_HEADER        * sectp;
  struct stat			statbuf;
  int				status;
  char				dbg_file[MAX_PATHNAME_LEN];

  LocateDebugInfoFile(filename, dbg_file);
  status = stat(dbg_file, &statbuf);
  if( status == -1 )
    {
      fprintf(stderr, "-Unable to open .DBG file %s\n", dbg_file);
      goto leave;
    }

  /*
   * Now open the file, so that we can mmap() it.
   */
  fd = open(dbg_file, O_RDONLY);
  if( fd == -1 )
    {
      fprintf(stderr, "Unable to open .DBG file %s\n", dbg_file);
      goto leave;
    }


  /*
   * Now mmap() the file.
   */
  addr = mmap(0, statbuf.st_size, PROT_READ, 
	      MAP_PRIVATE, fd, 0);
  if( addr == (char *) 0xffffffff )
    {
      fprintf(stderr, "Unable to mmap .DBG file %s\n", dbg_file);
      goto leave;
    }

  pdbg = (PIMAGE_SEPARATE_DEBUG_HEADER) addr;

  if( pdbg->TimeDateStamp != deefer->dbgdir->TimeDateStamp )
    {
      fprintf(stderr, "Warning - %s has incorrect internal timestamp\n",
	      dbg_file);
/*      goto leave; */
/*
   Well, sometimes this happens to DBG files which ARE REALLY the right .DBG
   files but nonetheless this check fails. Anyway, WINDBG (debugger for
   Windows by Microsoft) loads debug symbols which have incorrect timestamps.
*/
   }

  fprintf(stderr, "Processing symbols from %s...\n", dbg_file);

  dbghdr = (PIMAGE_DEBUG_DIRECTORY) (  addr + sizeof(*pdbg) 
		 + pdbg->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) 
		 + pdbg->ExportedNamesSize);

  sectp = (PIMAGE_SECTION_HEADER) ((char *) pdbg + sizeof(*pdbg));
  nsect = pdbg->NumberOfSections;

  for( i=0; i < pdbg->DebugDirectorySize / sizeof(*pdbg); i++, dbghdr++ )
    {
      switch(dbghdr->Type)
		{
		case IMAGE_DEBUG_TYPE_COFF:
		  /*
		   * Dummy up a deferred debug header to handle the
		   * COFF stuff embedded within the DBG file.
		   */
		  memset((char *) &deefer2, 0, sizeof(deefer2));
		  deefer2.dbg_info = (addr + dbghdr->PointerToRawData);
		  deefer2.dbg_size = dbghdr->SizeOfData;
		  deefer2.load_addr = deefer->load_addr;

		  DEBUG_ProcessCoff(&deefer2);
		  break;
		case IMAGE_DEBUG_TYPE_CODEVIEW:
		  /*
		   * This is the older format by which codeview stuff is 
		   * stored, known as the 'NB09' format.  Newer executables
		   * and dlls created by VC++ use PDB files instead, which
		   * have lots of internal similarities, but the overall
		   * format and structure is quite different.
		   */
		  codeview = (addr + dbghdr->PointerToRawData);

		  /*
		   * The first thing in the codeview section should be
		   * an 'NB09' identifier.  As a sanity check, make sure
		   * it is there.
		   */
		  if( *((unsigned int*) codeview) != 0x3930424e )
		    {
		      break;
		    }
		  
		  /*
		   * Next we need to find the directory.  This is easy too.
		   */
		  codeview_dir = (struct CV4_DirHead *) 
		    (codeview + ((unsigned int*) codeview)[1]);

		  /*
		   * Some more sanity checks.  Make sure that everything
		   * is as we expect it.
		   */
		  if( codeview_dir->next_offset != 0 
		      || codeview_dir->dhsize != sizeof(*codeview_dir)
		      || codeview_dir->desize != sizeof(*codeview_dent) )
		    {
		      break;
		    }
		  codeview_dent = (struct CV4_DirEnt *) (codeview_dir + 1);

		  for(j=0; j < codeview_dir->ndir; j++, codeview_dent++)
		    {
		      if( codeview_dent->subsect_number == sstAlignSym )
			{
			  /*
			   * Check the previous entry.  If it is a
			   * sstSrcModule, it contains the line number
			   * info for this file.
			   */
			  linetab = NULL;
			  if( codeview_dent[1].module_number == codeview_dent[0].module_number
			      && codeview_dent[1].subsect_number == sstSrcModule )
			    {
			      linetab = DEBUG_SnarfLinetab(
					   codeview + codeview_dent[1].offset,
					   codeview_dent[1].size);
			    }

			  if( codeview_dent[-1].module_number == codeview_dent[0].module_number
			      && codeview_dent[-1].subsect_number == sstSrcModule )
			    {
			      linetab = DEBUG_SnarfLinetab(
					   codeview + codeview_dent[-1].offset,
					   codeview_dent[-1].size);
			    }
			  /*
			   * Now process the CV stuff.
			   */
			  DEBUG_SnarfCodeView(deefer, 
					      codeview + codeview_dent->offset,
					      codeview_dent->size,
					      linetab);
			}
		    }

		  break;
		default:
		  break;
		}
    }
leave:

  if( addr != (char *) 0xffffffff )
    {
      munmap(addr, statbuf.st_size);
    }

  if( fd != -1 )
    {
      close(fd);
    }

  return TRUE;
}

int
DEBUG_ProcessDeferredDebug()
{
  struct deferred_debug_info * deefer;
  struct CodeViewDebug	     * cvd;
  struct MiscDebug	     * misc;
  char			     * filename;
  int			       last_proc = -1;
  int                          need_print =0;

  DEBUG_InitCVDataTypes();

  for(deefer = dbglist; deefer; deefer = deefer->next)
    {
      if( deefer->loaded )
	{
	  continue;
	}

      if( last_proc != deefer->dbg_index )
	{
	  if (!need_print)
	    {
	      fprintf(stderr, "DeferredDebug for:");
	      need_print=1;
	    }
	  fprintf(stderr, " %s",deefer->module_name);
	  last_proc = deefer->dbg_index;
	}

      switch(deefer->dbgdir->Type)
	{
	case IMAGE_DEBUG_TYPE_COFF:
	  /*
	   * Standard COFF debug information that VC++ adds when you
	   * use /debugtype:both with the linker.
	   */
#if 0
	  fprintf(stderr, "Processing COFF symbols...\n");
#endif
	  DEBUG_ProcessCoff(deefer);
	  break;
	case IMAGE_DEBUG_TYPE_CODEVIEW:
	  /*
	   * This is a pointer to a PDB file of some sort.
	   */
	  cvd = (struct CodeViewDebug *) deefer->dbg_info;

	  if( strcmp(cvd->cv_nbtype, "NB10") != 0 )
	    {
	      /*
	       * Whatever this is, we don't know how to deal with
	       * it yet.
	       */
	      break;
	    }
	  DEBUG_ProcessPDBFile(deefer, cvd->cv_name);
#if 0
	  fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name);
#endif
	  break;
	case IMAGE_DEBUG_TYPE_MISC:
	  /*
	   * A pointer to a .DBG file of some sort.  These files
	   * can contain either CV4 or COFF information.  Open
	   * the file, and try to do the right thing with it.
	   */
	  misc = (struct MiscDebug *) deefer->dbg_info;

	  filename = strrchr((char *) &misc->Data, '.');

	  /*
	   * Ignore the file if it doesn't have a .DBG extension.
	   */
	  if(    (filename == NULL)
	      || (    (strcmp(filename, ".dbg") != 0)
	           && (strcmp(filename, ".DBG") != 0)) )
	    {
	      break;
	    }

	  filename = (char *) &misc->Data;

	  /*
	   * Do the dirty deed...
	   */
	  DEBUG_ProcessDBGFile(deefer, filename);
      
	  break;
	default:
	  /*
	   * We should never get here...
	   */
	  break;
	}
    }
      if(need_print)
       fprintf(stderr, "\n");
  return TRUE;

}

/***********************************************************************
 *           DEBUG_InfoShare
 *
 * Display shared libarary information.
 */
void DEBUG_InfoShare(void)
{
  struct deferred_debug_info * deefer;

  fprintf(stderr,"Address\t\tModule\tName\n");

  for(deefer = dbglist; deefer; deefer = deefer->next)
  {
      fprintf(stderr,"0x%8.8x\t(%s)\t%s\n", (unsigned int) deefer->load_addr,
              deefer->module ? "Win32" : "ELF", deefer->module_name);
  }
}

