Consistent usage of Address type.
[dyninst.git] / pdutil / h / Object-nt.h
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /************************************************************************
43  * Windows NT/2000 object files.
44  * $Id: Object-nt.h,v 1.4 1998/12/25 21:49:43 wylie Exp $
45 ************************************************************************/
46
47
48 \f
49
50
51 #if !defined(_Object_nt_h_)
52 #define _Object_nt_h_
53
54 \f
55
56
57 /************************************************************************
58  * header files.
59 ************************************************************************/
60
61 #include "util/h/Dictionary.h"
62 #include "util/h/String.h"
63 #include "util/h/Symbol.h"
64 #include "util/h/Types.h"
65 #include "util/h/Vector.h"
66
67 #include <stdlib.h>
68 #include <winnt.h>
69
70
71 \f
72
73
74 /************************************************************************
75  * class Object
76 ************************************************************************/
77
78 class Object : public AObject {
79 public:
80              Object (const string, void (*)(const char *) = log_msg);
81              Object (const Object &);
82              Object (const string, const Address baseAddr,
83                 void (*)(const char *) = log_msg);
84
85     virtual ~Object ();
86
87     Object&   operator= (const Object &);
88
89     //void *getFPOtable() const; // returns a pointer to the FPO table
90     //void *getFPOtableEntry(unsigned offset) const;
91
92 private:
93     void    load_object ();
94     
95
96     HANDLE fileHandle; // handle for file
97     HANDLE mapHandle;  // handle for mapping
98     char *baseAddr;    // base address of mapping
99
100     //DWORD ptr_to_rdata;
101      
102 };
103
104
105 /* break fullName into name and path parts */
106 static void getFileNameAndPath(const string fullName, string &name, string &path) {
107   unsigned long size = GetFullPathName(fullName.string_of(), 0, 0, 0);
108   char *buffer = new char[size];
109   char *fptr;
110   GetFullPathName(fullName.string_of(), size, buffer, &fptr);
111   name = fptr;
112   *fptr = 0;
113   path = buffer;
114   delete buffer;
115 }
116
117 /* get the value of environment variable varName */
118 static void getEnvVar(const string varName, string &value) {
119   unsigned long pathLen = GetEnvironmentVariable(varName.string_of(), 0, 0);
120   char *buffer = new char[pathLen];
121   GetEnvironmentVariable(varName.string_of(), buffer, pathLen);
122   value = buffer;
123   delete buffer;
124 }
125
126 /* find a .dbg file for the .exe or .dll file */
127 static bool findDbgFile(const string exeFile, DWORD exeTimeStamp,
128                         HANDLE &dbgFile, 
129                         HANDLE &dbgMapping, const char * &dbgAddr,
130                         IMAGE_SYMBOL * &syms, unsigned long &nsyms,
131                         char * &strs) {
132   string fileName;
133   string filePath;
134   getFileNameAndPath(exeFile, fileName, filePath);
135
136   /*
137      kludge: we only read a .dbg file if it is for kernel32.dll.
138      There seem to be some problems with some files - the symbols
139      don't match the code, even though the timestamps in the
140      files match, so we will not read them for now.
141   */
142   if (fileName != "kernel32.dll" && fileName != "KERNEL32.dll") {
143     return false;
144   }
145
146   string dbgName = string(fileName.string_of(), fileName.length()-3) + "dbg";
147
148   // first, look in the same directory of the .exe file
149   string dbgPath = filePath + dbgName;
150   dbgFile = CreateFile(dbgPath.string_of(), GENERIC_READ, FILE_SHARE_READ, 
151                        NULL, OPEN_EXISTING, NULL, NULL);
152   if (dbgFile != INVALID_HANDLE_VALUE) {
153     dbgMapping = CreateFileMapping(dbgFile, NULL, PAGE_READONLY,0,0,NULL);
154     if (dbgMapping == INVALID_HANDLE_VALUE) {
155       CloseHandle(dbgFile);
156       return false;
157     }
158     dbgAddr = (char *)MapViewOfFile(dbgMapping, FILE_MAP_READ, 0, 0, 0);
159     if (dbgAddr == NULL) {
160       CloseHandle(dbgMapping);
161       CloseHandle(dbgFile);
162       return false;
163     }
164   } else {
165     // now look in %SystemRoot%\SYMBOLS\DLL
166     string sysRootDir;
167     getEnvVar("SystemRoot", sysRootDir);
168     dbgPath = sysRootDir + "\\SYMBOLS\\DLL\\" + dbgName;
169     dbgFile = CreateFile(dbgPath.string_of(), GENERIC_READ, FILE_SHARE_READ, 
170                          NULL, OPEN_EXISTING, NULL, NULL);
171     if (dbgFile == INVALID_HANDLE_VALUE)
172       return false;
173     dbgMapping = CreateFileMapping(dbgFile, NULL, PAGE_READONLY,0,0,NULL);
174     if (dbgMapping == INVALID_HANDLE_VALUE) {
175       CloseHandle(dbgFile);
176       return false;
177     }
178     dbgAddr = (char *)MapViewOfFile(dbgMapping, FILE_MAP_READ, 0, 0, 0);
179     if (dbgAddr == NULL) {
180       CloseHandle(dbgMapping);
181       CloseHandle(dbgFile);
182       return false;
183     }
184   }
185
186   // read the header
187   IMAGE_SEPARATE_DEBUG_HEADER *dbgHeader =
188        (IMAGE_SEPARATE_DEBUG_HEADER *)dbgAddr;
189   IMAGE_DEBUG_DIRECTORY *dbgDir;
190
191   if (dbgHeader->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE
192       && dbgHeader->TimeDateStamp == exeTimeStamp) {
193     //printf("dgbHeader->TimeDateStamp %x %x %x %x %d\n", dbgHeader->TimeDateStamp,
194     //       exeTimeStamp, dbgHeader->CheckSum, dbgHeader->ImageBase,
195     //       dbgHeader->SizeOfImage);
196     dbgDir = (IMAGE_DEBUG_DIRECTORY *)
197                &dbgAddr[sizeof(IMAGE_SEPARATE_DEBUG_HEADER) +
198                         dbgHeader->NumberOfSections*
199                        sizeof(IMAGE_SECTION_HEADER) + 
200                        dbgHeader->ExportedNamesSize];
201
202     if (dbgDir->Type == IMAGE_DEBUG_TYPE_COFF) {
203       IMAGE_COFF_SYMBOLS_HEADER *coffHdr = 
204         (IMAGE_COFF_SYMBOLS_HEADER *)&dbgAddr[dbgDir->PointerToRawData];
205       nsyms = coffHdr->NumberOfSymbols;
206       syms = (IMAGE_SYMBOL *) &dbgAddr[dbgDir->PointerToRawData+
207                                        coffHdr->LvaToFirstSymbol];
208       strs = (char *) &dbgAddr[dbgDir->PointerToRawData+
209                                coffHdr->LvaToFirstSymbol+
210                                nsyms*sizeof(IMAGE_SYMBOL)];
211       return true;
212     }
213   }
214
215   // generate error message -- TODO
216   if (dbgHeader->Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE) {
217     fprintf(stderr,"Unable to read debug file %s: invalid signature\n", dbgPath.string_of());
218   } else if (dbgHeader->TimeDateStamp != exeTimeStamp) {
219     fprintf(stderr,"Unable to read debug file %s: wrong date/timestamp\n",
220            dbgPath.string_of());
221   } else {
222     fprintf(stderr,"Unable to process debug file %s: file is not in COFF format\n",
223            dbgPath.string_of());
224   }
225   
226   UnmapViewOfFile(dbgAddr);
227   CloseHandle(dbgMapping);
228   CloseHandle(dbgFile);
229   return false;
230
231 }
232
233
234 inline
235 void
236 Object::load_object() {
237     // Set these to invalid values in case we fail along the way
238     baseAddr = NULL;
239     mapHandle = NULL;
240     fileHandle = INVALID_HANDLE_VALUE;
241
242     //
243     const char* file = file_.string_of();
244     bool        did_open = false;
245
246     IMAGE_DOS_HEADER * dosHdr;
247     IMAGE_NT_HEADERS * ntHdrs;
248     IMAGE_FILE_HEADER * header;
249     IMAGE_SECTION_HEADER * sections;
250     IMAGE_SYMBOL * syms;
251     unsigned long nsyms;
252     char *strs;
253
254     string        module = "DEFAULT_MODULE";
255     string        name   = "DEFAULT_SYMBOL";
256     vector<Symbol> allSymbols;
257     Address       addr;
258     Address       imageBase;
259     bool isDll = false;
260
261     bool useDbgFile = false;
262     HANDLE dbgFile;     // handle to .dbg file
263     HANDLE dbgMapping;  // handle to mapping of .dbg file
264     char * dbgAddr;     // base address of mapping
265
266     /* try */ {
267
268         fileHandle = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, 
269                         NULL, OPEN_EXISTING, NULL, NULL);
270         if (fileHandle == INVALID_HANDLE_VALUE) {
271             log_perror(err_func_, "CreateFile");
272             /* throw exception */ goto cleanup;
273         }
274         did_open = true;
275
276         mapHandle = CreateFileMapping(fileHandle, NULL, PAGE_READONLY,0,0,NULL);
277         if (mapHandle == INVALID_HANDLE_VALUE) {
278             log_perror(err_func_, "CreateFileMapping");
279             /* throw exception */ goto cleanup;
280         }
281         baseAddr = (char *)MapViewOfFile(mapHandle, FILE_MAP_READ, 0, 0, 0);
282         if (baseAddr == NULL) {
283             log_perror(err_func_, "MapViewOfFile");
284             /* throw exception */ goto cleanup;
285         }
286
287         /* read the DOS header */
288         dosHdr = (IMAGE_DOS_HEADER *)baseAddr;
289         if (dosHdr->e_magic != IMAGE_DOS_SIGNATURE) {
290             log_perror(err_func_, "Bad magic number");
291             /* throw exception */ goto cleanup;
292         }
293
294         /* read NT headers */
295         ntHdrs = (IMAGE_NT_HEADERS *)(&baseAddr[dosHdr->e_lfanew]);
296         if (ntHdrs->Signature != IMAGE_NT_SIGNATURE) {
297             log_perror(err_func_, "Bad magic number");
298             /* throw exception */ goto cleanup;
299         }
300
301         header = &ntHdrs->FileHeader;
302
303 #ifdef DEBUG_LOAD_OBJECT
304         printf("Machine = %x\n", header->Machine);
305         printf("Num sections = %d\n", header->NumberOfSections);
306         printf("Time/date = %x\n", header->TimeDateStamp);
307         printf("symbol table = %x\n", header->PointerToSymbolTable);
308         printf("Num syms = %d\n", header->NumberOfSymbols);
309         printf("Optional = %d\n", header->SizeOfOptionalHeader);
310         printf("Chararc = %x\n", header->Characteristics);
311         printf("BC: %x\n", ntHdrs->OptionalHeader.BaseOfCode);
312         printf("BD: %x\n", ntHdrs->OptionalHeader.BaseOfData);
313 #endif
314
315         isDll = (header->Characteristics & IMAGE_FILE_DLL)!=0;
316
317 #ifdef DEBUG_LOAD_OBJECT
318         if (isDll) printf("Object is a dll.\n");
319         else printf("Object is not a dll.\n");
320 #endif
321
322         imageBase = ntHdrs->OptionalHeader.ImageBase;
323 #ifdef DEBUG_LOAD_OBJECT
324         printf("Image base: 0x%lx\n", (unsigned long)imageBase);
325 #endif
326
327         /* read the sections */
328         sections = (IMAGE_SECTION_HEADER *) (&baseAddr[dosHdr->e_lfanew +
329                                                  +sizeof(DWORD)
330           + sizeof(IMAGE_FILE_HEADER) + header->SizeOfOptionalHeader]);
331         
332         for (unsigned u1 = 0; u1 < header->NumberOfSections; u1++) {
333           char sname[9];
334           strncpy(sname, (const char *) &sections[u1].Name[0], 8);
335           sname[8] = 0;
336 #ifdef DEBUG_LOAD_OBJECT
337           printf("Section name: %s\n", sname);
338           printf("  VirtualAddress = %x\n",
339                   (unsigned)sections[u1].VirtualAddress);
340           printf("  SizeOfRawData = %d\n",
341                   (unsigned)sections[u1].SizeOfRawData);
342           printf("  PointerToRawData = %x\n",
343                   (unsigned)sections[u1].PointerToRawData);
344           printf(  "PointerToRelocations = %x\n",
345                   (unsigned)sections[u1].PointerToRelocations);
346           printf("  PointerToLinenumbers = %x\n",
347                   (unsigned)sections[u1].PointerToLinenumbers);
348           printf("  NumberOfRelocations = %d\n",
349                   (unsigned)sections[u1].NumberOfRelocations);
350           printf("  NumberOfLinenumbers = %d\n",
351                   sections[u1].NumberOfLinenumbers);
352           printf("  Characteristics = %x\n", sections[u1].Characteristics);
353 #endif
354           if (strcmp(sname, ".text") == 0) {
355             code_ptr_ = (Word*)&baseAddr[sections[u1].PointerToRawData];
356             code_off_ = (Word)(imageBase +
357                         ntHdrs->OptionalHeader.BaseOfCode);
358             code_len_ = (unsigned)(sections[u1].Misc.VirtualSize/sizeof(Word));
359 #ifdef DEBUG_LOAD_OBJECT
360             printf("codeoff = imageBase(%x) + ntHdrs->Optionalheader.BaseOfCode(%x)\n", (unsigned)imageBase, (unsigned)ntHdrs->OptionalHeader.BaseOfCode);
361             printf("codeoff: %x, codelen: %d (to %x)\n",
362                     code_off_, code_len_, code_off_ + (code_len_ << 2));
363 #endif
364           }
365           if (strcmp(sname, ".data") == 0) {
366             data_ptr_ = (Word*)&baseAddr[sections[u1].PointerToRawData];
367             data_off_ = (Word)(imageBase +
368                                sections[u1].VirtualAddress
369                                /*ntHdrs->OptionalHeader.BaseOfData*/);
370             data_len_ = (unsigned)(sections[u1].Misc.VirtualSize/sizeof(Word));
371 #ifdef DEBUG_LOAD_OBJECT
372             printf("dataoff: %x, datalen: %d\n", data_off_, data_len_);
373 #endif
374           }
375
376           //if (strcmp(sname, ".rdata") == 0) {
377           //  ptr_to_rdata = sections[u1].PointerToRawData;
378           //}
379
380         }
381
382         if (ntHdrs->FileHeader.PointerToSymbolTable) {
383           syms = (IMAGE_SYMBOL *)
384                       (&baseAddr[ntHdrs->FileHeader.PointerToSymbolTable]);
385           nsyms = ntHdrs->FileHeader.NumberOfSymbols;
386           strs = (char *)(&baseAddr[ntHdrs->FileHeader.PointerToSymbolTable
387                             + nsyms * sizeof(IMAGE_SYMBOL)]);
388 #ifdef DEBUG_LOAD_OBJECT
389           printf("Found symbol table in file.\n");
390 #endif
391         } else {
392           // no symbol table
393           if (findDbgFile(file, header->TimeDateStamp, dbgFile, dbgMapping,
394                           dbgAddr, syms, nsyms, strs)) {
395             useDbgFile = true;
396 #ifdef DEBUG_LOAD_OBJECT
397             printf("Found symbol table in separate dbg file.\n");
398 #endif
399           }
400           else {
401 #ifdef DEBUG_LOAD_OBJECT
402             printf("File %s has no symbol table\n", file);
403 #endif
404             nsyms = 0;
405           }
406         }
407
408 #ifdef notdef
409         // We could use the imagehlp library to read symbols that are in
410         // CodeView format. However, the image help library symbol handler
411         // does not give some information we need. In particular,
412         // it does not give the type of symbols, so we don't known
413         // which symbols are functions and which are not.
414       
415         if (nsyms == 0) {
416           // object file has no COFF debug info. We use the imagehelp
417           // library to read symbol table in other formats
418           // This is a kludge, we should improve this code later
419           extern HANDLE kludgeProcHandle;
420           if (kludgeProcHandle) {
421
422             IMAGEHLP_MODULE mod;
423             unsigned numSyms = 0;
424
425             mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
426             if (SymGetModuleInfo(kludgeProcHandle, imageBase, &mod)) {
427               numSyms = mod.NumSyms;
428               //fprintf(stderr,"#### numSyms=%d, type=%d\n", numSyms, mod.SymType);
429             }
430
431             if (numSyms > 0 && (mod.SymType==SymCoff || mod.SymType==SymCv
432                                 || mod.SymType==SymPdb)) {
433               
434               char buffer[1024+sizeof(IMAGEHLP_SYMBOL)];
435               IMAGEHLP_SYMBOL *sym = (IMAGEHLP_SYMBOL *)&buffer;
436
437               sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
438               sym->Address = code_off_;
439               sym->MaxNameLength = 1024;
440
441               // SymGetSymNext doesn't always find a symbol if we
442               // set the initial address as the code offset,
443               // so we keep trying successive addresses 
444               // to make sure we get the first symbol
445               while (!SymGetSymNext(kludgeProcHandle, sym)
446                      && sym->Address <= code_off_ + code_len_*sizeof(Word))
447                 sym->Address++;
448               
449               do {
450                 //printf(">> %s %x %d\n", sym->Name, sym->Address, sym->Size);
451                 if (sym->Address > code_off_ + code_len_*sizeof(Word))
452                   continue;
453                 allSymbols += Symbol(sym->Name, "", Symbol::PDST_FUNCTION,
454                                      Symbol::SL_GLOBAL,
455                                      sym->Address, false, sym->Size);
456               } while (SymGetSymNext(kludgeProcHandle, sym));
457             }
458           }
459         }
460 #endif
461
462         bool cygwin_dll = false;
463         if (isDll) {
464           // for dynamic linked libraries, we have a single module, with
465           // the same name as the library
466           string fileName;
467           string filePath;
468           getFileNameAndPath(file, fileName, filePath);
469           allSymbols += Symbol(fileName, "", Symbol::PDST_MODULE,
470                                 Symbol::SL_GLOBAL, imageBase, false);
471         }
472
473         /* 
474          * We need this flag (which is set if the object was compiled with
475          * gcc) because we need it to know how to interpret the addresses in
476          * the symbols table.  Gcc stores absolute addresses for symbols,
477          * whereas Microsoft compilers store addresses relative to imageBase.
478          */
479         bool gcc_compiled = false;
480         for (unsigned v = 0; v < nsyms; v++) {
481          
482           if (syms[v].N.Name.Short != 0) {
483               char sname[9];
484               strncpy(sname, (char *)(&syms[v].N.ShortName), 8);
485               sname[8] = 0;
486               name = sname;
487           } else {
488               name = &strs[syms[v].N.Name.Long];
489           }
490
491 #ifdef DEBUG_LOAD_OBJECT
492           printf("syms[%d] name = <%s>\n", v, name.string_of());
493           printf(" syms[%d].Value = %u\n", v, (unsigned int)syms[v].Value);
494           printf(" syms[%d].SectionNumber = %d\n", v,
495                   (int)syms[v].SectionNumber);
496           printf(" syms[%d].Type = %d\n", v, (int)syms[v].Type);
497           printf(" syms[%d].StorageClass = %u\n", v,
498                   (unsigned int)syms[v].StorageClass);
499           printf(" syms[%d].NumberOfAuxSymbols = %d\n", v,
500                   (int)syms[v].NumberOfAuxSymbols);
501 #endif
502
503
504           if (name.prefixed_by("_$$$") || name.prefixed_by("$$$")) {
505             v += syms[v].NumberOfAuxSymbols;
506           } else if (syms[v].StorageClass == IMAGE_SYM_CLASS_LABEL &&
507               (name == "gcc2_compiled." || name == "___gnu_compiled_c")) {
508             gcc_compiled = true;
509 #ifdef DEBUG_LOAD_OBJECT
510             printf("This module is gcc_compiled.\n");
511 #endif
512           } else if (syms[v].StorageClass == IMAGE_SYM_CLASS_FILE) {
513             // a file name. The name of the file is a zero terminated
514             // string in one or more auxiliar entries following this one
515             name = (char *) (&syms[v+1]);
516             // skip the auxiliary entries
517             v += (strlen(name.string_of()) / sizeof(IMAGE_SYMBOL)) + 1;
518
519             // there may be a .text entry following the file name
520             // this entry has the starting address for this file
521             if (syms[v+1].N.Name.Short != 0 &&
522                 strncmp((char *)(&syms[v+1].N.ShortName), ".text", 5)==0) {
523               addr = syms[v+1].Value;
524               v++;
525             } else {
526               addr = 0;
527             }
528             if (!isDll)
529               allSymbols += Symbol(name, "", Symbol::PDST_MODULE,
530                                 Symbol::SL_GLOBAL, imageBase+addr, false);
531
532           /* XXX Checking for "exit" below is hack to make things work for gcc
533              for the time being.  We need to be able to instrument exit, but
534              we don't parse the dll cygwin32.dll (which contains exit)
535              correctly and we can't tell what's a function and what's not.
536              So, we make exit a funtion no matter what it seems to be. */
537           } else if ((syms[v].StorageClass != IMAGE_SYM_CLASS_TYPE_DEFINITION
538                       && ISFCN(syms[v].Type))
539                      || (gcc_compiled &&
540                          (name == "__exit" || name == "_exit"
541                          || name == "exit"))) {
542             if (syms[v].N.Name.Short != 0) {
543               char sname[9];
544               strncpy(sname, (char *)(&syms[v].N.ShortName), 8);
545               sname[8] = 0;
546               name = sname;
547             } else {
548               name = &strs[syms[v].N.Name.Long];
549             }
550
551             Address fcn_addr;
552             if (gcc_compiled)
553                 fcn_addr = syms[v].Value;
554             else
555                 fcn_addr = imageBase+syms[v].Value;
556 #ifdef DEBUG_LOAD_OBJECT
557             if (gcc_compiled)
558                 printf("Got function, address is %x\n", fcn_addr);
559             else
560                 printf("Got function, address is %x + %x = %x\n",
561                     imageBase, syms[v].Value, fcn_addr);
562 #endif
563             if (syms[v].StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
564               allSymbols += Symbol(name, "", Symbol::PDST_FUNCTION,
565                                    Symbol::SL_GLOBAL, fcn_addr, false);
566             else
567               allSymbols += Symbol(name, "", Symbol::PDST_FUNCTION,
568                                    Symbol::SL_LOCAL, fcn_addr, false);
569
570             v += syms[v].NumberOfAuxSymbols;
571           } else if (syms[v].SectionNumber > 0) {
572             if (syms[v].N.Name.Short != 0) {
573               char sname[9];
574               strncpy(sname, (char *)(&syms[v].N.ShortName), 8);
575               sname[8] = 0;
576               name = sname;
577             } else {
578               name = &strs[syms[v].N.Name.Long];
579             }
580             Address sym_addr;
581             if (gcc_compiled)
582               sym_addr = syms[v].Value;
583             else
584               sym_addr = imageBase+syms[v].Value;
585 #ifdef DEBUG_LOAD_OBJECT
586               printf( "%s: gcc_compiled = %d, imageBase = %lx, syms[v].Value = %lx, sym_addr = %lx\n",
587                 name.string_of(),
588                 (int)gcc_compiled,
589                 (unsigned long)imageBase,
590                 (unsigned long)syms[v].Value, (unsigned long)sym_addr);
591 #endif
592             if (name == ".text") {
593
594             }
595             else if (syms[v].StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
596               allSymbols += Symbol(name, "", Symbol::PDST_OBJECT,
597                                    Symbol::SL_GLOBAL,
598                                    sym_addr, false);
599             else
600               allSymbols += Symbol(name, "", Symbol::PDST_OBJECT,
601                                    Symbol::SL_LOCAL,
602                                    sym_addr, false);
603             v += syms[v].NumberOfAuxSymbols;
604           } else {
605             v += syms[v].NumberOfAuxSymbols;
606           }
607
608         }
609
610 #ifdef DEBUG_LOAD_OBJECT
611         printf("All symbols found.\n");
612 #endif
613
614         const string emptyStr = "";
615         // add an extra symbol to mark the end of the text segment
616         allSymbols += Symbol("", "", Symbol::PDST_OBJECT, Symbol::SL_GLOBAL, 
617                              code_off_+code_len_*sizeof(Word), false);
618
619         // Sort the symbols on address to find the function boundaries
620         allSymbols.sort(symbol_compare);
621
622
623 #ifdef XXX_GENERATE_MODULES
624 static unsigned int modnumber = 0;
625 static unsigned numfuncs = 0;
626 static const unsigned funcspermod = 500;
627 #endif
628
629         // find the function boundaries
630         unsigned nsymbols = allSymbols.size();
631         string modName = "";
632         for (unsigned u = 0; u < nsymbols; u++) {
633
634 #ifdef XXX_GENERATE_MODULES
635           if (!isDll && ++numfuncs % 500 == 0) {
636             modName = string("Mod") + string(++modnumber);
637             symbols_[modName] = Symbol(modName, "", Symbol::PDST_MODULE,
638                          Symbol::SL_GLOBAL, allSymbols[u].addr(), false);
639           }
640 #endif
641             unsigned size = 0;
642             if (allSymbols[u].type() == Symbol::PDST_FUNCTION) {
643                 unsigned v = u+1;
644                 while (v < nsymbols) {
645                   // The .ef below is a special symbol that gcc puts in to
646                   // mark the end of a function.
647                   if (allSymbols[v].addr() != allSymbols[u].addr() &&
648                       (allSymbols[v].type() == Symbol::PDST_FUNCTION ||
649                        allSymbols[v].name() == ".ef"))
650                     break;
651                   v++;
652                 }
653                 if (v < nsymbols)
654                   size = (unsigned)allSymbols[v].addr() 
655                          - (unsigned)allSymbols[u].addr();
656                 else
657                   size = (unsigned)(code_off_+code_len_*sizeof(Word))
658                          - (unsigned)allSymbols[u].addr();
659             }
660
661             if (allSymbols[u].name() != "")
662               symbols_[allSymbols[u].name()] =
663                 Symbol(allSymbols[u].name(), 
664                        isDll ? allSymbols[u].module(): modName, 
665                        allSymbols[u].type(), allSymbols[u].linkage(),
666                        allSymbols[u].addr(), allSymbols[u].kludge(),
667                        size);
668         }      
669
670       if (useDbgFile) {
671         UnmapViewOfFile(dbgAddr);
672         CloseHandle(dbgMapping);
673         CloseHandle(dbgFile);
674       }
675     }
676     /* catch */
677 cleanup: {
678       /*
679         if (did_open && (close(fd) == -1)) {
680             log_perror(err_func_, "close");
681         }
682         */
683     }
684 }
685
686
687 inline
688 Object::Object(const string file, void (*err_func)(const char *))
689     : AObject(file, err_func) {
690     load_object();
691 }
692
693 // for shared object files
694 inline
695 Object::Object(const string file, const Address /*baseAddr*/,
696         void (*err_func)(const char *))
697     : AObject(file, err_func) {
698    load_object();
699 }
700
701 inline
702 Object::Object(const Object& obj)
703     : AObject(obj) {
704     load_object();
705 }
706
707
708 inline
709 Object::~Object() {
710     if (baseAddr != NULL)
711         UnmapViewOfFile(baseAddr);
712     if (mapHandle != NULL)
713         CloseHandle(mapHandle);
714     if (fileHandle != INVALID_HANDLE_VALUE)
715         CloseHandle(fileHandle);
716 }
717
718 inline
719 Object&
720 Object::operator=(const Object& obj) {
721     (void) AObject::operator=(obj);
722     return *this;
723 }
724
725
726 #endif /* !defined(_Object_nt_h_) */