ElfArchiveFile.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1998, The University of Queensland
00003  *
00004  * See the file "LICENSE.TERMS" for information on usage and
00005  * redistribution of this file, and for a DISCLAIMER OF ALL
00006  * WARRANTIES.
00007  *
00008  */
00009 
00010 /* File: ElfArchiveFile.cc
00011  * Desc: This file contains the implementation of the ElfArchiveFile class
00012  * Revisions: 
00013  * 98 - Mike: Created
00014 */
00015 
00016 #include "global.h"
00017 
00018 ElfArchiveFile::ElfArchiveFile()        // Constructor
00019 {
00020 }
00021 
00022 ElfArchiveFile::~ElfArchiveFile()       // Destructor
00023 {
00024 }
00025 
00026 bool ElfArchiveFile::Load(const char* pName)
00027 {
00028     // Load the elf file
00029     Elf* elf;
00030 
00031     m_filedes = open(pName, O_RDONLY);
00032     if (m_filedes == -1)
00033     {
00034         printf("Could not open %s\n", pName);
00035         return false;
00036     }
00037 
00038     elf_version(EV_CURRENT);
00039     m_arf = elf_begin(m_filedes, ELF_C_READ, (Elf*)0);
00040     if (elf_kind(m_arf) != ELF_K_AR)
00041     {
00042         printf("Error - %s is not an archive (.a) file\n", pName);
00043         return false;
00044     }
00045 
00046     // Load the symbol table. We assume that each member has at
00047     // least one symbol.
00048     // We want a map from symbol to index; to do this, we need to know
00049     // the current index and last offset seen
00050     int iLastOffset = 0;
00051     int iOffset = 0;
00052     unsigned int uNumSyms;
00053     int iIndex = -1;        // 0,1,2... for 1st,2nd,3rd... member
00054 
00055     Elf_Arsym* asym;
00056     asym = elf_getarsym(m_arf, &uNumSyms);
00057     uNumSyms--;
00058     if (asym == 0)
00059     {
00060         printf("Get archive symbol table failed\n");
00061         return false;
00062     }
00063 
00064     for (unsigned u=0; u < uNumSyms; u++)
00065     {
00066         iOffset = asym[u].as_off;
00067         // Last entry is null, but should never see it
00068         if (iOffset == 0) break;
00069         if (iOffset != iLastOffset)
00070         {
00071             // This is a new member. Use a new index
00072             iIndex++;
00073             iLastOffset = iOffset;
00074 
00075             // Seek to that member
00076             if (elf_rand(m_arf, iOffset) == 0)
00077             {
00078                 printf("Could not seek to offset %d\n", iOffset);
00079                 return false;
00080             }
00081             if ((elf = elf_begin(m_filedes, ELF_C_READ, m_arf)) == 0)
00082             {
00083                 printf("Could not begin member at offset %d\n", iOffset);
00084                 return false;
00085             }
00086             Elf_Arhdr* ahdr;
00087             ahdr = elf_getarhdr(elf);
00088             if (ahdr == 0)
00089             {
00090                 printf("Could not get header information "
00091                     "for member at offset %d\n", iOffset);
00092                 return false;
00093             }
00094             // Add the name to the map
00095             m_FileMap[ahdr->ar_name] = iIndex;
00096             // And to the vector of pointers to file names
00097             m_FileNames.push_back(ahdr->ar_name);
00098             // Also add the offset. These are supposed to be relatively
00099             // implementation independant
00100             m_Offsets.push_back(iOffset);
00101         }
00102         // Add an entry to the symbol->offset map
00103         m_SymMap[asym[u].as_name] = iIndex;
00104     }
00105 
00106     // Now we know the correct size for the vector of members.
00107     // Ugh - can't call constructor any more
00108     //m_Members.vector(GetNumMembers(), (BinaryFile*)0);
00109     m_Members.reserve(GetNumMembers());
00110 
00111     return true;
00112 }
00113 
00114 void ElfArchiveFile::UnLoad()
00115 {
00116     for (unsigned u=0; u < m_Members.size(); u++)
00117     {
00118         if (m_Members[u])           // Has this member been created?
00119         {
00120             // Free the object
00121             delete m_Members[u];
00122         }
00123         //m_Members.clear();        // Slack gcc is missing this function
00124         m_Members.erase(m_Members.begin(), m_Members.end());
00125     }
00126 }
00127 
00128 BinaryFile* ElfArchiveFile::GetMember(int i)
00129 {
00130     // Sanity checks on the index
00131     if (i < 0) return 0;
00132     if (i >= m_FileMap.size()) return 0;
00133 
00134     // Lazy creation. Check to see if already created
00135     if (i >= m_Members.size() || (m_Members[i] == 0))
00136     {
00137         // Now we have to create one. We set the constructor argument
00138         // bArchive to true, so it knows it's an archive member
00139         BinaryFile* pBF = new ElfBinaryFile(true);
00140         if (pBF == 0) return 0;
00141         // Load the file for the user. First find the offset
00142         int iOffset = m_Offsets[i];
00143         if (iOffset == 0) return 0;
00144         if (elf_rand(m_arf, iOffset) != iOffset)
00145         {
00146             return 0;
00147         }
00148         Elf* elf;               // Elf handle for the new member
00149         if ((elf = elf_begin(m_filedes, ELF_C_READ, m_arf)) == 0)
00150         {
00151             return 0;
00152         }
00153         // We have to get our father to load the file, since he is a
00154         // friend of class BinaryFile, but we aren't
00155         if (PostLoadMember(pBF, elf) == 0) return 0;
00156         m_Members[i] = pBF;
00157         return pBF;
00158     }
00159     // Else already seen
00160     return m_Members[i];
00161 }
00162 
00163 

Generated on Tue Sep 19 21:18:22 2006 for Boomerang by  doxygen 1.4.6