GNUArchiveReader.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- GNUArchiveReader.cpp -----------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/MC/MCLDInfo.h" 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/MC/MCLDInput.h" 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/MC/MCLDInputTree.h" 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "mcld/LD/GNUArchiveReader.h" 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/MemoryBuffer.h> 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/system_error.h> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sstream> 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string> 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <vector> 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstdlib> 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace std; 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotypedef size_t sectionSizeTy; 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotypedef uint32_t elfWord; 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Archive Header, Magic number, etc.. 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst unsigned archiveMagicSize = 8; 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst char archiveMagic[archiveMagicSize] = { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }; 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst char thinArchiveMagic[archiveMagicSize] = { '!', '<', 't', 'h', 'i', 'n', '>', '\n' }; 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst char archiveFinalMagic[2] = { '`', '\n' }; 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct GNUArchiveReader::ArchiveMemberHeader 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char name[16]; 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char date[12]; 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char uid[6]; 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char gid[6]; 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char mode[8]; 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char size[10]; 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char finalMagic[2]; 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostruct GNUArchiveReader::SymbolTableEntry 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t fileOffset; 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::string name; 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoinline void endian_swap(unsigned int& x) 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao x = (x>>24) | 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((x<<8) & 0x00FF0000) | 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((x>>8) & 0x0000FF00) | 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (x<<24); 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// convert string to size_t 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaotemplate<class Type> 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoType stringToType(const std::string &str) 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Type n; 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::stringstream ss(str); 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ss >> n; 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return n; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// GNUArchiveReader Operations 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Public API 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool GNUArchiveReader::isMyFormat(Input &pInput) const 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::OwningPtr<llvm::MemoryBuffer> mapFile; 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile); 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char* pFile = mapFile->getBufferStart(); 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// check archive format. 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(mapFile->getBufferSize() <= archiveMagicSize) 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0; 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0) 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return true; 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoLDReader::Endian GNUArchiveReader::endian(Input& pFile) const 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return m_endian; 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoInputTree *GNUArchiveReader::readArchive(Input &pInput) 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return setupNewArchive(pInput, 0); 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Read Input as archive. First create a null InputTree. 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Then Construct Input object for corresponding member of this archive 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// and insert the Input object into the InputTree. 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Finally, return the InputTree. 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoInputTree *GNUArchiveReader::setupNewArchive(Input &pInput, 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t off) 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::OwningPtr<llvm::MemoryBuffer> mapFile; 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile)) 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "GNUArchiveReader:can't map a file to MemoryBuffer\n"); 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao InputTree *resultTree = new InputTree(m_pLDInfo.inputFactory()); 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::vector<SymbolTableEntry> symbolTable; 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::string archiveMemberName; 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::string extendedName; 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool isThinArchive; 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char *pFile = mapFile->getBufferStart(); 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// check archive format. 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(mapFile->getBufferSize() <= archiveMagicSize) 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0; 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0) 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off += archiveMagicSize ; 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t symbolTableSize = parseMemberHeader(mapFile, off, &archiveMemberName, 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao NULL, extendedName); 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// read archive symbol table 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(archiveMemberName.empty()) 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao readSymbolTable(mapFile, symbolTable, 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off+sizeof(GNUArchiveReader::ArchiveMemberHeader), symbolTableSize); 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off = off + sizeof(GNUArchiveReader::ArchiveMemberHeader) + symbolTableSize; 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "fatal error : need symbol table\n"); 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if((off&1) != 0) 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++off; 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t extendedSize = parseMemberHeader(mapFile, off, &archiveMemberName, 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao NULL, extendedName); 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// read long Name table if exist 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(archiveMemberName == "/") 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off += sizeof(GNUArchiveReader::ArchiveMemberHeader); 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pFile += off; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao extendedName.assign(pFile,extendedSize); 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// traverse all the archive members 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao InputTree::iterator node = resultTree->root(); 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao set<string> haveSeen; 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for(unsigned i=0 ; i<symbolTable.size() ; ++i) 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// We shall get each member at this archive. 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// Construct a corresponding mcld::Input, and insert it into 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// the original InputTree, resultTree. 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t nestedOff = 0; 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao parseMemberHeader(mapFile, symbolTable[i].fileOffset, &archiveMemberName, 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao &nestedOff, extendedName); 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(haveSeen.find(archiveMemberName)==haveSeen.end()) 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao haveSeen.insert(archiveMemberName); 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao continue; 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(!isThinArchive) 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// New a Input object and assign fileOffset in MCLDFile. 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// Insert the object to resultTree and move ahead. 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t fileOffset = symbolTable[i].fileOffset + sizeof(ArchiveMemberHeader); 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Input *insertObjectFile = m_pLDInfo.inputFactory().produce(archiveMemberName, 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pInput.path(), 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MCLDFile::Object, 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao fileOffset); 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao resultTree->insert<InputTree::Positional>(node, *insertObjectFile); 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(i==0) 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao node.move<InputTree::Inclusive>(); 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao node.move<InputTree::Positional>(); 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao continue; 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// create the real path 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao sys::fs::RealPath realPath(archiveMemberName); 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(nestedOff > 0) 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// This is a member of a nested archive. 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// Create an Input for this archive ,and recursive call setupNewArchive 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// Finally, merge the new InputTree with the old one 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Input *newArchive = m_pLDInfo.inputFactory().produce(archiveMemberName, 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao realPath, 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MCLDFile::Archive, 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 0); 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao resultTree->insert<InputTree::Positional>(node, *newArchive); 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(i==0) 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao node.move<InputTree::Inclusive>(); 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao node.move<InputTree::Positional>(); 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao InputTree *newArchiveTree = setupNewArchive(*newArchive, 0); 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao resultTree->merge<InputTree::Inclusive>(node, *newArchiveTree); 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao continue; 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// External member , open it as normal object file 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// add new Input to InputTree 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Input *insertObjectFile = m_pLDInfo.inputFactory().produce(archiveMemberName, 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao realPath, 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MCLDFile::Object, 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 0); 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao resultTree->insert<InputTree::Positional>(node, *insertObjectFile); 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(i==0) 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao node.move<InputTree::Inclusive>(); 2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao node.move<InputTree::Positional>(); 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return resultTree; 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Parse the member header and return the size of member 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Archive member names in System 5 style : 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "/ " - symbol table, must be the first member 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "// " - long name table 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "filename.o/ " - regular file with short name 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// "/5566 " - name at offset 5566 at long name table 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaosize_t GNUArchiveReader::parseMemberHeader(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile, 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t off, 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::string *p_Name, 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t *p_NestedOff, 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::string &p_ExtendedName) 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char *pFile = mapFile->getBufferStart(); 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pFile += off; 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ArchiveMemberHeader *header = reinterpret_cast<const ArchiveMemberHeader *>(pFile); 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// check magic number of member header 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(memcmp(header->finalMagic, archiveFinalMagic, sizeof archiveFinalMagic)) 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "archive member header magic number false"); 2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0; 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// evaluate member size 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::string sizeString(header->size, sizeof(header->size)+1); 2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t memberSize = stringToType<size_t>(sizeString); 2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(memberSize == 0) 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "member Size Error"); 2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0; 2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(header->name[0] != '/') 2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// This is a regular file with short name 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char* nameEnd = strchr(header->name, '/'); 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t nameLen = ((nameEnd == NULL) ? 0 : (nameEnd - header->name)); 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if((nameLen <= 0) || (nameLen >= sizeof(header->name))) 2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "header name format error\n"); 2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0; 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao p_Name->assign(header->name, nameLen); 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(!p_NestedOff) 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao p_NestedOff = 0; 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else if(header->name[1] == ' ') 2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// This is symbol table 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(!p_Name->empty()) 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao p_Name->clear(); 2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else if(header->name[1] == '/') 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// This is long name table 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao p_Name->assign(1,'/'); 2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// This is regular file with long name 2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao char *end; 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao long extendedNameOff = strtol(header->name+1, &end, 10); 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao long nestedOff = 0; 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(*end == ':') 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao nestedOff = strtol(end+1, &end, 10); 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(*end != ' ' 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao || extendedNameOff < 0 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao || static_cast<size_t>(extendedNameOff) >= p_ExtendedName.size()) 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "extended name"); 3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0; 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char *name = p_ExtendedName.data() + extendedNameOff; 3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char *nameEnd = strchr(name, '\n'); 3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(nameEnd[-1] != '/' 3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao || static_cast<size_t>(nameEnd-name) > p_ExtendedName.size()) 3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "p_ExtendedName substring is not end with / \n"); 3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0; 3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao p_Name->assign(name, nameEnd-name-1); 3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(p_NestedOff) 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *p_NestedOff = nestedOff; 3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return memberSize; 3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid GNUArchiveReader::readSymbolTable(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile, 3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao std::vector<SymbolTableEntry> &pSymbolTable, 3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t start, 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t size) 3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char *startPtr = mapFile->getBufferStart() + start; 3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const elfWord *p_Word = reinterpret_cast<const elfWord *>(startPtr); 3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int symbolNum = *p_Word; 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// Portable Issue on Sparc platform 3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// Intel, ARM and Mips are littel-endian , Sparc is little-endian after verion 9 3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// symbolNum in symbol table is always big-endian 3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if(m_endian == LDReader::LittleEndian) 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao endian_swap(symbolNum); 3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++p_Word; 3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char *p_Name = reinterpret_cast<const char *>(p_Word + symbolNum); 3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSymbolTable.resize(symbolNum); 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for(unsigned int i=0 ; i<symbolNum ; ++i) 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// assign member offset 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int memberOffset = *p_Word; 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao endian_swap(memberOffset); 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSymbolTable[i].fileOffset = static_cast<off_t>(memberOffset); 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++p_Word; 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// assign member name 3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao off_t nameEnd = strlen(p_Name) + 1; 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSymbolTable[i].name.assign(p_Name, nameEnd); 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao p_Name += nameEnd; 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 357