Update copyright to LGPL on all files
[dyninst.git] / symtabAPI / src / Archive-xcoff.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32
33 #include "symtabAPI/h/Symtab.h"
34 #include "symtabAPI/h/Archive.h"
35 #include "symtabAPI/src/Object.h"
36
37 using namespace Dyninst;
38 using namespace Dyninst::SymtabAPI;
39
40 extern char errorLine[];
41
42 static SymtabError serr;
43 static std::string errMsg;
44
45 SymtabError Archive::getLastError()
46 {
47     return serr;
48 }
49
50 std::string Archive::printError(SymtabError serr)
51 {
52    switch (serr){
53       case Obj_Parsing:
54          return "Failed to parse the Archive"+errMsg;
55       case No_Such_Member:
56                 return "Member not found" + errMsg;
57       case Not_An_Archive:
58                 return "File is not an archive";
59       default:
60          return "Unknown Error";
61         }       
62 }               
63                        
64 Archive::Archive(std::string &filename, bool &ok) :
65    basePtr(NULL)
66 {
67    mf  = MappedFile::createMappedFile(filename);
68    fileOpener *fo_ = fileOpener::openFile(mf->base_addr(), mf->size());
69    fo_->set_file(mf->filename());
70
71
72         assert(fo_);
73         unsigned char magic_number[2];
74     
75    if (!fo_->set(0)) 
76         {
77       sprintf(errorLine, "Error reading file %s\n", 
78               filename.c_str());
79                 serr = Obj_Parsing;
80                 errMsg = errorLine;
81                 ok = false;
82       fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
83       //MappedFile::closeMappedFile(mf);
84       return;
85    }
86    if (!fo_->read((void *)magic_number, 2)) 
87         {
88       sprintf(errorLine, "Error reading file %s\n", 
89               filename.c_str());
90                 serr = Obj_Parsing;
91                 errMsg = errorLine;
92                 ok = false;
93       fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
94       //MappedFile::closeMappedFile(mf);
95       return;
96    }
97
98    // a.out file: magic number = 0x01df
99    // archive file: magic number = 0x3c62 "<b", actually "<bigaf>"
100    // or magic number = "<a", actually "<aiaff>"
101    if (magic_number[0] == 0x01)
102         {
103                 serr = Not_An_Archive;
104       sprintf(errorLine, "Not an Archive. Call Symtab::openFile"); 
105                 errMsg = errorLine;
106                 ok = false;
107       //fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
108       //MappedFile::closeMappedFile(mf);
109                 return;
110         }
111    else if ( magic_number[0] != '<')
112         {
113       sprintf(errorLine, "Bad magic number in file %s\n",
114               filename.c_str());
115                 serr = Obj_Parsing;
116                 errMsg = errorLine;
117                 ok = false;
118       fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
119      // MappedFile::closeMappedFile(mf);
120                 return;
121    }
122         xcoffArchive *archive = NULL;
123     
124    // Determine archive type
125    // Start at the beginning...
126    if (!fo_->set(0))
127         {
128       sprintf(errorLine, "Error parsing a.out file %s: %s \n",
129               filename.c_str(), "Seeking to file start" );      
130                 serr = Obj_Parsing;
131                 errMsg = errorLine;
132       fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
133                 ok = false;
134         }                                            
135
136    char magicNumber[SAIAMAG];
137    if (!fo_->read(magicNumber, SAIAMAG))
138         {
139                 sprintf(errorLine, "Error parsing a.out file %s: %s \n",
140               filename.c_str(), "Reading magic number" );
141                 serr = Obj_Parsing;
142                 errMsg = errorLine;
143       fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
144                 ok = false;
145         }       
146
147    if (!strncmp(magicNumber, AIAMAG, SAIAMAG))
148       archive = (xcoffArchive *) new xcoffArchive_32(fo_);
149    else if (!strncmp(magicNumber, AIAMAGBIG, SAIAMAG))
150       archive = (xcoffArchive *) new xcoffArchive_64(fo_);
151    else
152         {
153                 sprintf(errorLine, "Error parsing a.out file %s: %s \n",
154               filename.c_str(), "Unknown Magic number" );
155                 serr = Obj_Parsing;
156                 errMsg = errorLine;
157       fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
158                 ok = false;
159         }       
160     
161    if (archive->read_arhdr())
162         {
163                 sprintf(errorLine, "Error parsing a.out file %s: %s \n",
164               filename.c_str(), "Reading file header" );
165                 serr = Obj_Parsing;
166                 errMsg = errorLine;
167       fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
168                 ok = false;
169         }       
170     
171    while (archive->next_offset !=0)
172    {
173       if (archive->read_mbrhdr())
174       {
175          sprintf(errorLine, "Error parsing a.out file %s: %s \n",
176                filename.c_str(), "Reading Member Header" );
177          serr = Obj_Parsing;
178          errMsg = errorLine;
179          fprintf(stderr, "%s[%d]:  error in Archive ctor\n", FILE__, __LINE__);
180          ok = false;
181       } 
182
183       std::string member_name = archive->member_name;
184       std::string::size_type len = member_name.length();
185       if ((len >= 4)&&(member_name.substr(len-4,4) == ".imp" || 
186                member_name.substr(len-4,4) == ".exp"))
187          continue;
188       memberToOffsetMapping[member_name] = archive->aout_offset;
189       //Do it lazily
190       membersByName[member_name] = NULL;
191       /*        
192                 Symtab *memImg = new Symtab(filename ,member_name, archive->aout_offset, err);
193                 membersByName[member_name] = memImg;
194        */
195    }    
196
197    //  why do we close the file mapping??  I must be missing something
198 #if 0 
199    if (mf)
200       MappedFile::closeMappedFile(mf);
201    delete archive;
202    mf = NULL;
203 #endif
204
205    ok = true;
206 }
207
208 #if 0
209 Archive::Archive(char *mem_image, size_t size, bool &err)
210 {
211     mf  = MappedFile::createMappedFile(mem_image, size);
212     fileOpener *fo_ = fileOpener::openFile(mf->base_addr(), mf->size());
213
214     assert(fo_);
215     unsigned char magic_number[2];
216
217     if (!fo_->set(0)) 
218     {
219         sprintf(errorLine, "Error reading memory image 0x%x with size %u\n", 
220                 mem_image, size);
221         serr = Obj_Parsing;
222         errMsg = errorLine;
223         err = false;
224         return;
225     }
226     if (!fo_->read((void *)magic_number, 2)) 
227     {
228         sprintf(errorLine, "Error reading memory image 0x%x with size %u\n", 
229                 mem_image, size);
230         serr = Obj_Parsing;
231         errMsg = errorLine;
232         err = false;
233         return;
234     }
235
236     // a.out file: magic number = 0x01df
237     // archive file: magic number = 0x3c62 "<b", actually "<bigaf>"
238     // or magic number = "<a", actually "<aiaff>"
239     if (magic_number[0] == 0x01)
240     {
241         serr = Not_An_Archive;
242         sprintf(errorLine, "Not an Archive. Call Symtab::openFile"); 
243         errMsg = errorLine;
244         err = false;
245         return;
246     }
247     else if ( magic_number[0] != '<')
248     {
249         sprintf(errorLine, "Error reading memory image 0x%x with size %u\n", 
250                 mem_image, size);
251         serr = Obj_Parsing;
252         errMsg = errorLine;
253         err = false;
254         return;
255     }
256     xcoffArchive *archive = NULL;
257
258     // Determine archive type
259     // Start at the beginning...
260     if (!fo_->set(0))
261     {
262         sprintf(errorLine, "Error parsing memory image 0x%x with size %u : %s\n", 
263                 mem_image, size, "Seeking to file start");
264         serr = Obj_Parsing;
265         errMsg = errorLine;
266         err = false;
267     }
268
269     char magicNumber[SAIAMAG];
270     if (!fo_->read(magicNumber, SAIAMAG))
271     {
272         sprintf(errorLine, "Error parsing memory image 0x%x with size %u : %s\n", 
273                 mem_image, size, "Reading magic number");
274         serr = Obj_Parsing;
275         errMsg = errorLine;
276         err = false;
277     }   
278
279     if (!strncmp(magicNumber, AIAMAG, SAIAMAG))
280         archive = (xcoffArchive *) new xcoffArchive_32(fo_);
281     else if (!strncmp(magicNumber, AIAMAGBIG, SAIAMAG))
282         archive = (xcoffArchive *) new xcoffArchive_64(fo_);
283     else
284     {
285         sprintf(errorLine, "Error parsing memory image 0x%x with size %u : %s\n", 
286                 mem_image, size, "Unknown magic number");
287         serr = Obj_Parsing;
288         errMsg = errorLine;
289         err = false;
290     }    
291     if (archive->read_arhdr())
292     {
293         sprintf(errorLine, "Error parsing memory image 0x%x with size %u : %s\n", 
294                 mem_image, size, "Reading file header");
295         serr = Obj_Parsing;
296         errMsg = errorLine;
297         err = false;
298     }
299
300     while (archive->next_offset !=0)
301     {
302         if (archive->read_mbrhdr())
303         {
304             sprintf(errorLine, "Error parsing memory image 0x%x with size %u : %s\n", 
305                     mem_image, size, "Reading memory header");
306             serr = Obj_Parsing;
307             errMsg = errorLine;
308             err = false;
309         }       
310         std::string member_name = archive->member_name;
311         bool err;
312         std::string::size_type len = member_name.length();
313         if((len >= 4)&&(member_name.substr(len-4,4) == ".imp" || member_name.substr(len-4,4) == ".exp"))
314             continue;
315         memberToOffsetMapping[member_name] = archive->aout_offset;
316         //Do it lazily
317                 membersByName[member_name] = NULL;
318 /*        
319         Symtab *memImg = new Symtab(mem_image, size,member_name, archive->aout_offset, err);
320         membersByName[member_name] = memImg;
321 */        
322     }   
323     fprintf(stderr, "%s[%d]:  deleting archive\n", FILE__, __LINE__);
324     delete archive;
325     err = true;
326 }
327 #endif
328
329 Archive::~Archive()
330 {
331    dyn_hash_map <std::string, Symtab *>::iterator iter = membersByName.begin();
332    for (; iter!=membersByName.end();iter++) {
333       if (iter->second)
334          delete (iter->second);
335    }
336    memberToOffsetMapping.clear();
337    for (unsigned i = 0; i < allArchives.size(); i++) {
338       if (allArchives[i] == this)
339          allArchives.erase(allArchives.begin()+i);
340    }
341
342    if (mf) 
343    {
344       MappedFile::closeMappedFile(mf);
345    }
346 }