- Updates to extract type info from executables in Coff format
[dyninst.git] / pdutil / src / Object-coff.C
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 // $Id: Object-coff.C,v 1.4 2000/01/11 21:57:16 altinel Exp $
43
44 #include "util/h/Object.h"
45 #include "util/h/Object-coff.h"
46 #include "util/src/Dictionary.C"
47
48 char *ScName(int sc) {
49 static char scBuf[20];
50
51         switch(sc) {
52         case scNil:
53                 strcpy(scBuf, "scNil");
54                 break;
55         case scText:
56                 strcpy(scBuf, "scText");
57                 break;
58         case scData:
59                 strcpy(scBuf, "scData");
60                 break;
61         case scBss:
62                 strcpy(scBuf, "scBss");
63                 break;
64         case scRegister:
65                 strcpy(scBuf, "scRegister");
66                 break;
67         case scAbs:
68                 strcpy(scBuf, "scAbs");
69                 break;
70         case scUndefined:
71                 strcpy(scBuf, "scUndefined");
72                 break;
73         case scUnallocated:
74                 strcpy(scBuf, "scUnallocated");
75                 break;
76         case scBits:
77                 strcpy(scBuf, "scBits");
78                 break;
79         case scTlsUndefined:
80                 strcpy(scBuf, "scTlsUndefined");
81                 break;
82         case scRegImage:
83                 strcpy(scBuf, "scRegImage");
84                 break;
85         case scInfo:
86                 strcpy(scBuf, "scInfo");
87                 break;
88         case scUserStruct:
89                 strcpy(scBuf, "scUserStruct");
90                 break;
91         case scSData:
92                 strcpy(scBuf, "scSData");
93                 break;
94         case scSBss:
95                 strcpy(scBuf, "scSBss");
96                 break;
97         case scRData:
98                 strcpy(scBuf, "scRData");
99                 break;
100         case scVar:
101                 strcpy(scBuf, "scVar");
102                 break;
103         case scCommon:
104                 strcpy(scBuf, "scCommon");
105                 break;
106         case scSCommon:
107                 strcpy(scBuf, "scSCommon");
108                 break;
109         case scVarRegister:
110                 strcpy(scBuf, "scVarRegister");
111                 break;
112         case scVariant:
113                 strcpy(scBuf, "scVariant");
114                 break;
115         case scSUndefined:
116                 strcpy(scBuf, "scSUndefined");
117                 break;
118         case scInit:
119                 strcpy(scBuf, "scInit");
120                 break;
121         case scBasedVar:
122                 strcpy(scBuf, "scBasedVar");
123                 break;
124         case scXData:
125                 strcpy(scBuf, "scXData");
126                 break;
127         case scPData:
128                 strcpy(scBuf, "scPData");
129                 break;
130         case scFini:
131                 strcpy(scBuf, "scFini");
132                 break;
133         case scRConst:
134                 strcpy(scBuf, "scRConst");
135                 break;
136         case scSymRef:
137                 strcpy(scBuf, "scSymRef");
138                 break;
139         case scTlsCommon:
140                 strcpy(scBuf, "scTlsCommon");
141                 break;
142         case scTlsData:
143                 strcpy(scBuf, "scTlsData");
144                 break;
145         case scTlsBss:
146                 strcpy(scBuf, "scTlsBss");
147                 break;
148         default:
149                 strcpy(scBuf,"Wrong Sc");
150                 break;
151         }
152
153         return scBuf;
154 }
155
156 char *StName(int st) {
157 static char stBuf[20];
158
159         switch(st) {
160         case stNil:
161                 strcpy(stBuf, "stNil");
162                 break;
163         case stGlobal:
164                 strcpy(stBuf, "stGlobal");
165                 break;
166         case stStatic:
167                 strcpy(stBuf, "stStatic");
168                 break;
169         case stParam:
170                 strcpy(stBuf, "stParam");
171                 break;
172         case stLocal:
173                 strcpy(stBuf, "stLocal");
174                 break;
175         case stLabel:
176                 strcpy(stBuf, "stLabel");
177                 break;
178         case stProc:
179                 strcpy(stBuf, "stProc");
180                 break;
181         case stBlock:
182                 strcpy(stBuf, "stBlock");
183                 break;
184         case stEnd:
185                 strcpy(stBuf, "stEnd");
186                 break;
187         case stMember:
188                 strcpy(stBuf, "stMember");
189                 break;
190         case stTypedef:
191                 strcpy(stBuf, "stTypedef");
192                 break;
193         case stFile:
194                 strcpy(stBuf, "stFile");
195                 break;
196         case stRegReloc:
197                 strcpy(stBuf, "stRegReloc");
198                 break;
199         case stForward:
200                 strcpy(stBuf, "stForward");
201                 break;
202         case stStaticProc:
203                 strcpy(stBuf, "stStaticProc");
204                 break;
205         case stConstant:
206                 strcpy(stBuf, "stConstant");
207                 break;
208         case stStaParam:
209                 strcpy(stBuf, "stStaParam");
210                 break;
211         case stBase:
212                 strcpy(stBuf, "stBase");
213                 break;
214         case stVirtBase:
215                 strcpy(stBuf, "stVirtBase");
216                 break;
217         case stTag:
218                 strcpy(stBuf, "stTag");
219                 break;
220         case stInter:
221                 strcpy(stBuf, "stInter");
222                 break;
223         case stSplit:
224                 strcpy(stBuf, "stSplit");
225                 break;
226         case stModule:
227                 strcpy(stBuf, "stModule");
228                 break;
229         case stModview:
230                 strcpy(stBuf, "stModview");
231                 break;
232         case stAlias:
233                 strcpy(stBuf, "stAlias");
234                 break;
235         case stStr:
236                 strcpy(stBuf, "stStr");
237                 break;
238         case stNumber:
239                 strcpy(stBuf, "stNumber");
240                 break;
241         case stExpr:
242                 strcpy(stBuf, "stExpr");
243                 break;
244         case stType:
245                 strcpy(stBuf, "stType");
246                 break;
247         default:
248                 strcpy(stBuf, "Wrong st");
249                 break;
250         }
251
252         return stBuf;
253 }
254
255
256 static inline bool obj_read_section(SCNHDR& secthead, LDFILE *ldptr,
257                                     Word *buffer) {
258   if (!secthead.s_scnptr) return false;
259   if (ldfseek(ldptr, secthead.s_scnptr, SEEK_SET) == -1) return false;
260
261   if (ldfread((void*) buffer, 1, secthead.s_size, ldptr) != secthead.s_size)
262     return false;
263   else
264     return true;
265 }
266
267 // The possible data sections
268 // These should only be used locally
269 #define K_D_INDEX    0
270 #define K_XD_INDEX   1
271 #define K_PD_INDEX   2
272 #define K_SD_INDEX   3
273 #define K_RD_INDEX   4
274 #define K_RC_INDEX   5 
275 #define K_L4_INDEX   6
276 #define K_L8_INDEX   7
277 #define K_LA_INDEX   8
278
279 // Attempt to find the largest contiguous (in virtual address space) region.
280 // This region must include ".data", and may include the other data like regions
281 static inline bool find_data_region(vector<Address>& all_addr,
282                                     vector<long>& all_size,
283                                     vector<long>& all_disk,
284                                     unsigned long& data_len, Address& data_off) {
285   // Start at data and work back
286   assert(all_addr[K_D_INDEX]); assert(all_size[K_D_INDEX]);
287   assert(all_addr.size() == all_size.size());
288
289   Address current = all_addr[K_D_INDEX];
290   Address min_adr = current;
291   Address max_adr = current + all_size[K_D_INDEX];
292
293   unsigned index, max=all_addr.size();
294
295   bool updated=true;
296   while (updated) {
297     updated = false;
298     for (index=0; index<max; index++) {
299       if (all_addr[index] && all_size[index] && all_disk[index] &&
300           ((all_addr[index] + all_size[index]) == current)) {
301         current = all_addr[index];
302         updated = true;
303       }
304     }
305   }
306   min_adr = current;
307
308   // Start at data and work forward
309   current = max_adr;
310   updated=true;
311   while (updated) {
312     updated = false;
313     for (index=0; index<max; index++) {
314       if (all_addr[index] && all_size[index] && all_disk[index] && 
315           (all_addr[index] == current)) {
316         current = all_addr[index] + all_size[index];
317         updated = true;
318       }
319     }
320   }
321
322   max_adr = current;
323   
324   data_len = (max_adr - min_adr) / sizeof(Word);
325   data_off = min_adr;
326   assert(min_adr <= all_addr[K_D_INDEX]);
327   assert(max_adr >= all_addr[K_D_INDEX] + all_size[K_D_INDEX]);
328   return true;
329 }
330
331 // Read in from the contiguous data regions, put the data in 'buffer'
332 static inline bool read_data_region(vector<Address>& all_addr,
333                                     vector<long>& all_size,
334                                     vector<long>& all_disk,
335                                     unsigned long& data_len, Address& data_off,
336                                     Word *buffer, LDFILE *ldptr) {
337   unsigned index, max = all_disk.size();
338   Address max_adr = data_off + data_len * sizeof(Word);
339   assert(all_size.size() == all_addr.size());
340   assert(all_disk.size() == all_addr.size());
341   for (index=0; index<max; index++) {
342     if ((all_addr[index] >= data_off) &&
343         ((all_addr[index] + all_size[index]) <= max_adr)) {
344       if (ldfseek(ldptr, all_disk[index], SEEK_SET) == -1) return false;
345       Word *buf_temp = buffer + ((all_addr[index] - data_off) / sizeof(Word));
346       if (ldfread((void*) buf_temp, 1, all_size[index], ldptr) != all_size[index])
347         return false;
348     }
349   }
350   return true;
351 }
352
353 void Object::load_object(bool sharedLibrary) {
354     char* file = strdup(file_.string_of());
355     bool        did_open = false, success=true, text_read=false;
356     LDFILE      *ldptr = NULL;
357     HDRR        sym_hdr;
358     pCHDRR      sym_tab_ptr = NULL;
359     long        index=0;
360     SYMR        symbol;
361     unsigned short sectindex=1;
362     SCNHDR      secthead;
363     filehdr     fhdr;
364     unsigned    nsymbols;
365     vector<Symbol> allSymbols;
366     vector<Address> all_addr(9, 0);
367     vector<long> all_size(9, 0);
368     vector<bool> all_dex(9, false);
369     vector<long> all_disk(9, 0);
370
371         if (!(ldptr = ldopen(file, ldptr))) {
372             log_perror(err_func_, file);
373             success = false;
374             printf("failed open\n");
375             free(file);
376             return;
377         }
378         did_open = true;
379
380         if (TYPE(ldptr) != ALPHAMAGIC) {
381             log_printf(err_func_, "%s is not an alpha executable\n", file);
382             success = false;
383             printf("failed magic region\n");
384             ldclose(ldptr);
385             free(file);
386             return;
387         }
388
389         // Read the text and data sections
390         fhdr = HEADER(ldptr);
391         unsigned short fmax = fhdr.f_nscns;
392
393         dynamicallyLinked = false;
394
395         // Life would be so much easier if there were a guaranteed order for
396         // these sections.  But the man page makes no mention of it.
397         while (sectindex < fmax) {
398           if (ldshread(ldptr, sectindex, &secthead) == SUCCESS) {
399             // cout << "Section: " << secthead.s_name << "\tStart: " << secthead.s_vaddr 
400             // << "\tEnd: " << secthead.s_vaddr + secthead.s_size << endl;
401
402             if (!P_strcmp(secthead.s_name, ".text")) {
403               code_len_ = Word(secthead.s_size >> LOG_WORD);
404               Word *buffer = new Word[code_len_+1];
405               code_ptr_ = buffer;
406               code_off_ = (Address) secthead.s_vaddr;
407               if (!obj_read_section(secthead, ldptr, buffer)) {
408                 success = false;
409                 printf("failed text region\n");
410                 ldclose(ldptr);
411                 free(file);
412                 return;
413               }
414               text_read = true;
415             } else if (!P_strcmp(secthead.s_name, ".data")) {
416               if (secthead.s_vaddr && secthead.s_scnptr) {
417                 all_addr[K_D_INDEX] = secthead.s_vaddr;
418                 all_size[K_D_INDEX] = secthead.s_size;
419                 all_dex[K_D_INDEX] = true;
420                 all_disk[K_D_INDEX] = secthead.s_scnptr;
421               } else {
422                 printf("failed data region\n");
423                 success = false;
424                 ldclose(ldptr);
425                 free(file);
426                 return;
427               }
428             } else if (!P_strcmp(secthead.s_name, ".xdata")) {
429               if (secthead.s_vaddr && secthead.s_scnptr) {
430                 all_addr[K_XD_INDEX] = secthead.s_vaddr;
431                 all_size[K_XD_INDEX] = secthead.s_size;
432                 all_dex[K_XD_INDEX] = true;
433                 all_disk[K_XD_INDEX] = secthead.s_scnptr;
434               }
435             } else if (!P_strcmp(secthead.s_name, ".sdata")) {
436               if (secthead.s_vaddr && secthead.s_scnptr) {
437                 all_addr[K_SD_INDEX] = secthead.s_vaddr;
438                 all_size[K_SD_INDEX] = secthead.s_size;
439                 all_dex[K_SD_INDEX] = true;
440                 all_disk[K_SD_INDEX] = secthead.s_scnptr;
441               }
442             } else if (!P_strcmp(secthead.s_name, ".rdata")) {
443               if (secthead.s_vaddr && secthead.s_scnptr) {
444                 all_addr[K_RD_INDEX] = secthead.s_vaddr;
445                 all_size[K_RD_INDEX] = secthead.s_size;
446                 all_dex[K_RD_INDEX] = true;
447                 all_disk[K_RD_INDEX] = secthead.s_scnptr;
448               }
449             } else if (!P_strcmp(secthead.s_name, ".lit4")) {
450               if (secthead.s_vaddr && secthead.s_scnptr) {
451                 all_addr[K_L4_INDEX] = secthead.s_vaddr;
452                 all_size[K_L4_INDEX] = secthead.s_size;
453                 all_dex[K_L4_INDEX] = true;
454                 all_disk[K_L4_INDEX] = secthead.s_scnptr;
455               }
456             } else if (!P_strcmp(secthead.s_name, ".lita")) {
457               if (secthead.s_vaddr && secthead.s_scnptr) {
458                 all_addr[K_LA_INDEX] = secthead.s_vaddr;
459                 all_size[K_LA_INDEX] = secthead.s_size;
460                 all_dex[K_LA_INDEX] = true;
461                 all_disk[K_LA_INDEX] = secthead.s_scnptr;
462               }
463             } else if (!P_strcmp(secthead.s_name, ".rconst")) {
464               if (secthead.s_vaddr && secthead.s_scnptr) {
465                 all_addr[K_RC_INDEX] = secthead.s_vaddr;
466                 all_size[K_RC_INDEX] = secthead.s_size;
467                 all_dex[K_RC_INDEX] = true;
468                 all_disk[K_RC_INDEX] = secthead.s_scnptr;
469               }
470             } else if (!P_strcmp(secthead.s_name, ".lit8")) {
471               if (secthead.s_vaddr && secthead.s_scnptr) {
472                 all_addr[K_L8_INDEX] = secthead.s_vaddr;
473                 all_size[K_L8_INDEX] = secthead.s_size;
474                 all_dex[K_L8_INDEX] = true;
475                 all_disk[K_L8_INDEX] = secthead.s_scnptr;
476               }
477             } else if (!P_strncmp(secthead.s_name, ".dynamic", 8)) {
478               // a section .dynamic implies the program is dynamically linked
479               dynamicallyLinked = true; 
480             }
481           } else {
482             success = false;
483             printf("failed header region\n");
484             ldclose(ldptr);
485             free(file);
486             return;
487           }
488           sectindex++;
489         }
490
491         if (!text_read) { 
492           success = false;
493           printf("failed text region\n");
494           ldclose(ldptr);
495           free(file);
496           return;
497         }
498
499         // I am assuming that .data comes before all other data sections
500         // I will include all other contiguous data sections
501         // Determine the size of the data section(s)
502         if (all_disk[K_D_INDEX]) {
503             if (!find_data_region(all_addr, all_size, all_disk,data_len_,data_off_)) {
504               success = false;
505               printf("failed find data region\n");
506               ldclose(ldptr);
507               free(file);
508               return;
509             }
510         }
511
512         // Now read in the data from the assorted data regions
513         Word *buffer = new Word[data_len_+1];
514         data_ptr_ = buffer;
515         if (!read_data_region(all_addr, all_size, all_disk,
516                               data_len_, data_off_, buffer, ldptr)) {
517           success = false;
518           ldclose(ldptr);
519           free(file);
520           return;
521         }
522
523         // Read the symbol table
524         sym_hdr = SYMHEADER(ldptr);
525         if (sym_hdr.magic != magicSym) {
526             success = false;
527             ldclose(ldptr);
528             free(file);
529             return;
530         }
531         if (!(sym_tab_ptr = SYMTAB(ldptr))) {
532             success = false;
533             ldclose(ldptr);
534             free(file);
535             return;
536         }
537         if (LDSWAP(ldptr)) {
538           // These bytes are swapped
539           // supposedly libsex.a will unswap them
540           assert(0);
541         }
542
543         string module = "DEFAULT_MODULE";
544         if (sharedLibrary) {
545             module = file_;
546             allSymbols += Symbol(module, module, Symbol::PDST_MODULE, 
547                 Symbol::SL_GLOBAL, (Address) 0, false);
548         } else {
549             module = "DEFAULT_MODULE";
550         }
551
552         string        name   = "DEFAULT_SYMBOL";
553         int moduleEndIdx = -1;
554         dictionary_hash<string, int> fcnNames(string::hash);
555
556         while (ldtbread(ldptr, index, &symbol) == SUCCESS) {
557           // TODO -- when global?
558           Symbol::SymbolLinkage linkage = Symbol::SL_GLOBAL;
559           Symbol::SymbolType type = Symbol::PDST_UNKNOWN;
560           bool st_kludge = false;
561           bool sym_use = true;
562           char *name = ldgetname(ldptr, &symbol);
563
564         switch(symbol.st) {
565         case stProc:
566         case stStaticProc:
567                 if (symbol.sc == scText && !fcnNames.defines(name)) {
568                         type = Symbol::PDST_FUNCTION;
569                         fcnNames[name] = 1;
570                 }
571                 else 
572                         sym_use = false;
573                 break;
574
575         case stGlobal:
576         case stConstant:
577         case stStatic:
578                 switch(symbol.sc) {
579                 case scData:
580                 case scSData:
581                 case scBss:
582                 case scSBss:
583                 case scRData:
584                 case scRConst:
585                 case scTlsData:
586                 case scTlsBss:
587                         type = Symbol::PDST_OBJECT;
588                         break;
589                 default:
590                         sym_use = false;
591                 }
592                 break;
593
594         case stLocal:
595         case stParam:
596                 linkage = Symbol::SL_LOCAL;
597
598                 switch(symbol.sc) {
599                 case scAbs:
600                 case scRegister:
601                 case scVar:
602                 case scVarRegister:
603                 case scUnallocated:
604                         type = Symbol::PDST_OBJECT;
605                         break;
606
607                 case scData:
608                 case scSData:
609                 case scBss:
610                 case scSBss:
611                 case scRConst:
612                 case scRData:
613                          //Parameter is static var. Don't know what to do
614                         if (symbol.st == stParam)
615                                 type = Symbol::PDST_OBJECT;
616                         else
617                                 sym_use = false;
618                         break;
619
620                 default:
621                         sym_use = false;
622                 }
623                 break;
624
625         case stTypedef:
626         case stBase: //Base class
627         case stTag: //C++ class, structure or union
628                 if (symbol.sc == scInfo)
629                         type = Symbol::PDST_OBJECT;
630                 else
631                         sym_use = false;
632                 break;
633
634         case stFile:
635                 if (!sharedLibrary) {
636                         module = ldgetname(ldptr, &symbol); assert(module.length());
637                         type   = Symbol::PDST_MODULE;
638                         moduleEndIdx = symbol.index - 1;
639                 }
640                 break;
641
642         case stEnd:
643                 if (index == moduleEndIdx)
644                         module = "DEFAULT_MODULE";
645                 sym_use = false;
646                 break;
647
648         default:
649                 sym_use = false;
650         }
651
652 /* Old type handling !
653
654           switch (symbol.sc) {
655           case scText:
656
657             switch (symbol.st) {
658             case stProc:
659             case stStaticProc:
660               type = Symbol::PDST_FUNCTION;
661               break;
662             case stGlobal:
663             case stStatic:
664             case stLocal:
665             case stConstant:
666             case stParam:
667               type = Symbol::PDST_OBJECT;
668               break;
669             case stFile:
670               if (!sharedLibrary) {
671                   module = ldgetname(ldptr, &symbol); assert(module.length());
672                   type   = Symbol::PDST_MODULE;
673               }
674               break;
675             default:
676               sym_use = false;
677             }
678             break;
679           case scData:
680           case scSData:
681           case scRData:
682           case scRConst:
683           case scXData:
684           case scBss:
685           case scSBss:
686             // cout << "Data: " << sym_name << "\tType:" << symbol.st 
687             // << "\tValue: " << symbol.value << endl;
688             type = Symbol::PDST_OBJECT;
689             switch (symbol.st) {
690             case stGlobal:
691             case stStatic:
692             case stLocal:
693             case stConstant:
694             case stParam:
695               break;
696             default:
697               sym_use = false;
698             }
699             break;
700           default:
701             switch (symbol.st) {
702             case stFile:
703               if (!sharedLibrary) {
704                   module = ldgetname(ldptr, &symbol); assert(module.length());
705                   type   = Symbol::PDST_MODULE;
706               }
707               break;
708             default:
709               sym_use = false;
710             }
711             break;
712           }
713 */
714
715           // cout << index << "\t" << name << "\t" << StName(symbol.st) << "\t" << ScName(symbol.sc) << "\t" << symbol.value << "\n";
716
717           index++;
718
719           if (sym_use) {
720             // cout << index << "\t" << module << "\t" << name << "\t" << type << "\t" << symbol.value << "\n";
721             allSymbols += Symbol(name, module, type, linkage,
722                                       (Address) symbol.value, st_kludge);
723           }
724
725     } //while
726
727     allSymbols.sort(symbol_compare);
728     // find the function boundaries
729     nsymbols = allSymbols.size();
730
731     //Insert global symbols
732     for (unsigned u = 0; u < nsymbols; u++) {
733         unsigned size = 0;
734         if (allSymbols[u].type() == Symbol::PDST_FUNCTION) {
735             unsigned v = u+1;
736             while (v < nsymbols) {
737                 // The .ef below is a special symbol that gcc puts in to
738                 // mark the end of a function.
739                 if (allSymbols[v].addr() != allSymbols[u].addr() &&
740                       (allSymbols[v].type() == Symbol::PDST_FUNCTION ||
741                        allSymbols[v].name() == ".ef"))
742                 break;
743                 v++;
744             }
745             if (v < nsymbols) {
746                   size = (unsigned)allSymbols[v].addr()
747                          - (unsigned)allSymbols[u].addr();
748             } else {
749                   size = (unsigned)(code_off_+code_len_*sizeof(Word))
750                          - (unsigned)allSymbols[u].addr();
751             }
752         }
753         
754         if (allSymbols[u].linkage() != Symbol::SL_LOCAL) {
755                 symbols_[allSymbols[u].name()] =
756                         Symbol(allSymbols[u].name(), allSymbols[u].module(), 
757                         allSymbols[u].type(), allSymbols[u].linkage(), 
758                         allSymbols[u].addr(), allSymbols[u].kludge(), size);
759         }
760     }
761
762     //Insert local symbols (Do we need this?)
763     for (unsigned u = 0; u < nsymbols; u++) {
764         if ( (allSymbols[u].linkage() == Symbol::SL_LOCAL) &&
765                 (!symbols_.defines(allSymbols[u].name())) ) {
766                 symbols_[allSymbols[u].name()] =
767                         Symbol(allSymbols[u].name(), allSymbols[u].module(), 
768                         allSymbols[u].type(), allSymbols[u].linkage(), 
769                         allSymbols[u].addr(), allSymbols[u].kludge(), 0);
770         }
771     }
772                 
773     if (did_open && (ldclose(ldptr) == FAILURE)) {
774         log_perror(err_func_, "close");
775     }
776     free(file);
777 }
778
779
780 Object::Object(const string file, void (*err_func)(const char *))
781     : AObject(file, err_func) {
782     load_object(false);
783 }
784
785 /* 
786  * Called to init a shared library.
787  */
788 Object::Object (const string fileName, const Address /*BaseAddr*/,
789         void (*err_func)(const char *) = log_msg)
790   :AObject(fileName,err_func)
791 {
792
793   load_object(true);
794
795 }
796
797 inline
798 Object::Object(const Object& obj)
799     : AObject(obj) {
800     load_object(false);
801 }
802