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//===----------------------------------------------------------------------===// 9affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/MC/MCLDInfo.h> 10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/MC/MCLDInput.h> 11affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/MC/InputTree.h> 12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/GNUArchiveReader.h> 13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/LD/ResolveInfo.h> 14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/LD/ELFObjectReader.h> 15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/FileSystem.h> 16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/Support/FileHandle.h> 17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryArea.h> 18affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryRegion.h> 19affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryAreaFactory.h> 20affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 21cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/Support/Path.h> 22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/ADT/SizeTraits.h> 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 24cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/ADT/StringRef.h> 25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h> 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 27cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <cstring> 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstdlib> 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 32cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoGNUArchiveReader::GNUArchiveReader(MCLDInfo& pLDInfo, 33cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryAreaFactory& pMemAreaFactory, 34cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao ELFObjectReader& pELFObjectReader) 35cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao : m_LDInfo(pLDInfo), 36cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_MemAreaFactory(pMemAreaFactory), 37cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_ELFObjectReader(pELFObjectReader) 38cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{ 39cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao} 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 41cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoGNUArchiveReader::~GNUArchiveReader() 42cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{ 43cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao} 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 45cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isMyFormat 46cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isMyFormat(Input& pInput) const 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 48cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(pInput.hasMemArea()); 49cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(), 50cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Archive::MAGIC_LEN); 51cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const char* str = reinterpret_cast<const char*>(region->getBuffer()); 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 53cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao bool result = false; 54cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(NULL != str); 55cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (isArchive(str) || isThinArchive(str)) 56cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao result = true; 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 58cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pInput.memArea()->release(region); 59cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return result; 60cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao} 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 62cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isArchive 63cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isArchive(const char* pStr) const 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 65cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return (0 == memcmp(pStr, Archive::MAGIC, Archive::MAGIC_LEN)); 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 68cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isThinArchive 69cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isThinArchive(const char* pStr) const 70cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{ 71cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return (0 == memcmp(pStr, Archive::THIN_MAGIC, Archive::MAGIC_LEN)); 72cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao} 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 74cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// isThinArchive 75cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::isThinArchive(Input& pInput) const 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(pInput.hasMemArea()); 78cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(), 79cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Archive::MAGIC_LEN); 80cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const char* str = reinterpret_cast<const char*>(region->getBuffer()); 81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 82cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao bool result = false; 83cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(NULL != str); 84cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (isThinArchive(str)) 85cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao result = true; 86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 87cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pInput.memArea()->release(region); 88cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return result; 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 91cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::readArchive(Archive& pArchive) 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 93cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // read the symtab of the archive 94cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao readSymbolTable(pArchive); 95cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 96cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // read the strtab of the archive 97cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao readStringTable(pArchive); 98cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 99cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // add root archive to ArchiveMemberMap 100cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.addArchiveMember(pArchive.getARFile().name(), 101cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.inputs().root(), 102cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao &InputTree::Downward); 103cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 104cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // include the needed members in the archive and build up the input tree 105cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao bool willSymResolved; 106cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao do { 107cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao willSymResolved = false; 108cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao for (size_t idx = 0; idx < pArchive.numOfSymbols(); ++idx) { 109cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // bypass if we already decided to include this symbol or not 110cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (Archive::Symbol::Unknown != pArchive.getSymbolStatus(idx)) 111cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao continue; 112cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 113cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // bypass if another symbol with the same object file offset is included 114cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (pArchive.hasObjectMember(pArchive.getObjFileOffset(idx))) { 115cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.setSymbolStatus(idx, Archive::Symbol::Include); 116cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao continue; 117cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 118cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 119cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // check if we should include this defined symbol 120cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Archive::Symbol::Status status = 121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao shouldIncludeSymbol(pArchive.getSymbolName(idx)); 122cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (Archive::Symbol::Unknown != status) 123cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.setSymbolStatus(idx, status); 124cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 125cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (Archive::Symbol::Include == status) { 126cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Input* cur_archive = &(pArchive.getARFile()); 127cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Input* member = cur_archive; 128cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao uint32_t file_offset = pArchive.getObjFileOffset(idx); 129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao while ((member != NULL) && (Input::Object != member->type())) { 130cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao uint32_t nested_offset = 0; 131cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // use the file offset in current archive to find out the member we 132cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // want to include 133cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member = readMemberHeader(pArchive, 134cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao *cur_archive, 135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao file_offset, 136cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao nested_offset); 137cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(member != NULL); 138cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // bypass if we get an archive that is already in the map 139cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (Input::Archive == member->type()) { 140cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao cur_archive = member; 141cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao file_offset = nested_offset; 142cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao continue; 143cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 144cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 145cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // insert a node into the subtree of current archive. 146cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Archive::ArchiveMember* parent = 147cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getArchiveMember(cur_archive->name()); 148cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 149cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(NULL != parent); 150cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.inputs().insert(parent->lastPos, *(parent->move), *member); 151cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 152cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // move the iterator to new created node, and also adjust the 153cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // direction to Afterward for next insertion in this subtree 154cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao parent->move->move(parent->lastPos); 155cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao parent->move = &InputTree::Afterward; 156cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 157cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (m_ELFObjectReader.isMyFormat(*member)) { 158cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member->setType(Input::Object); 159cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.addObjectMember(pArchive.getObjFileOffset(idx), 160cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao parent->lastPos); 161cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_ELFObjectReader.readObject(*member); 162cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_ELFObjectReader.readSections(*member); 163cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_ELFObjectReader.readSymbols(*member); 164cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 165cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao else if (isMyFormat(*member)) { 166cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member->setType(Input::Archive); 167cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // when adding a new archive node, set the iterator to archive 168cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // itself, and set the direction to Downward 169cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.addArchiveMember(member->name(), 170cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao parent->lastPos, 171cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao &InputTree::Downward); 172cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao cur_archive = member; 173cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao file_offset = nested_offset; 174cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 175cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } // end of while 176cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao willSymResolved = true; 177cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } // end of if 178cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } // end of for 179cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } while (willSymResolved); 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 181cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return true; 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 184cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readMemberHeader - read the header of a member in a archive file and then 185cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// return the corresponding archive member (it may be an input object or 186cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// another archive) 187cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pArchiveRoot - the archive root that holds the strtab (extended 188cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// name table) 189cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pArchiveFile - the archive that contains the needed object 190cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pFileOffset - file offset of the member header in the archive 191cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// @param pNestedOffset - used when we find a nested archive 192cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoInput* GNUArchiveReader::readMemberHeader(Archive& pArchiveRoot, 193cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Input& pArchiveFile, 194cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao uint32_t pFileOffset, 195cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao uint32_t& pNestedOffset) 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 197cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(pArchiveFile.hasMemArea()); 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 199cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryRegion* header_region = 200cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchiveFile.memArea()->request((pArchiveFile.fileOffset() + pFileOffset), 201cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sizeof(Archive::MemberHeader)); 202cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const Archive::MemberHeader* header = 203cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer()); 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 205cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2)); 206cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 207cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // int size = atoi(header->size); 208cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 209cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // parse the member name and nested offset if any 210cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao std::string member_name; 211cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao llvm::StringRef name_field(header->name, 16); 212cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if ('/' != header->name[0]) { 213cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // this is an object file in an archive 214cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao size_t pos = name_field.find_first_of('/'); 215cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member_name.assign(name_field.substr(0, pos).str()); 216cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 217cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao else { 218cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // this is an object/archive file in a thin archive 219cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao size_t begin = 1; 220cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao size_t end = name_field.find_first_of(" :"); 221cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao uint32_t name_offset = 0; 222cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // parse the name offset 223cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao name_field.substr(begin, end - begin).getAsInteger(10, name_offset); 224cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 225cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (':' == name_field[end]) { 226cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // there is a nested offset 227cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao begin = end + 1; 228cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao end = name_field.find_first_of(' ', begin); 229cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao name_field.substr(begin, end - begin).getAsInteger(10, pNestedOffset); 230cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 231cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 232cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // get the member name from the extended name table 233cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao begin = name_offset; 234cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao end = pArchiveRoot.getStrTable().find_first_of('\n', begin); 235cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member_name.assign(pArchiveRoot.getStrTable().substr(begin, end - begin -1)); 236cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 237affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 238cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Input* member = NULL; 239cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (!isThinArchive(pArchiveFile)) { 240cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // this is an object file in an archive 241cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member = 242cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_LDInfo.inputFactory().produce(member_name, 243cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchiveFile.path(), 244cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Input::Unknown, 245cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao (pFileOffset + 246cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sizeof(Archive::MemberHeader))); 247cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(member != NULL); 248cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member->setMemArea(pArchiveFile.memArea()); 249cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao LDContext *input_context = m_LDInfo.contextFactory().produce(); 250cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member->setContext(input_context); 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 252cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao else { 253cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // this is a member in a thin archive 254cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // try to find if this is a archive already in the map first 255cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Archive::ArchiveMember* ar_member = 256cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchiveRoot.getArchiveMember(member_name); 257cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (NULL != ar_member) { 258cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return ar_member->file; 259cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao } 2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 261cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // get nested file path, the nested file's member name is the relative 262cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // path to the archive containing it. 263cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sys::fs::Path input_path(pArchiveFile.path().parent_path()); 264cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (!input_path.empty()) 265cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao input_path.append(member_name); 2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 267cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao input_path.assign(member_name); 268cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member = 269cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_LDInfo.inputFactory().produce(member_name, input_path, Input::Unknown); 270cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 271cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(member != NULL); 272cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryArea* input_memory = 273cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao m_MemAreaFactory.produce(member->path(), FileHandle::ReadOnly); 274cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (input_memory->handler()->isGood()) { 275cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member->setMemArea(input_memory); 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 277cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao else { 278cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao error(diag::err_cannot_open_input) << member->name() << member->path(); 279cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return NULL; 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 281cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao LDContext *input_context = m_LDInfo.contextFactory().produce(input_path); 282cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao member->setContext(input_context); 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 284cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 285cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchiveFile.memArea()->release(header_region); 286cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return member; 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 289cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readSymbolTable - read the archive symbol map (armap) 290cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::readSymbolTable(Archive& pArchive) 291cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{ 292cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(pArchive.getARFile().hasMemArea()); 293cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 294cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryRegion* header_region = 295cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() + 296cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Archive::MAGIC_LEN), 297cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sizeof(Archive::MemberHeader)); 298cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const Archive::MemberHeader* header = 299cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer()); 300cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2)); 301cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 302cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao int symtab_size = atoi(header->size); 303cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.setSymTabSize(symtab_size); 304cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 305cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryRegion* symtab_region = 306cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() + 307cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Archive::MAGIC_LEN + 308cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sizeof(Archive::MemberHeader)), 309cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao symtab_size); 310cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const uint32_t* data = 311cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao reinterpret_cast<const uint32_t*>(symtab_region->getBuffer()); 312cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 313cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // read the number of symbols 314cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao uint32_t number = 0; 315cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (llvm::sys::isLittleEndianHost()) 316cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao number = bswap32(*data); 317cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao else 318cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao number = *data; 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 320cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // set up the pointers for file offset and name offset 321cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao ++data; 322cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const char* name = reinterpret_cast<const char*>(data + number); 3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 324cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // add the archive symbols 325cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao for (uint32_t i = 0; i < number; ++i) { 326cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (llvm::sys::isLittleEndianHost()) 327cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.addSymbol(name, bswap32(*data)); 328cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao else 329cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.addSymbol(name, *data); 330cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao name += strlen(name) + 1; 331cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao ++data; 3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 334cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->release(header_region); 335cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->release(symtab_region); 336cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return true; 337cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao} 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 339cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// readStringTable - read the strtab for long file name of the archive 340cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool GNUArchiveReader::readStringTable(Archive& pArchive) 341cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{ 342cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao size_t offset = Archive::MAGIC_LEN + 343cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sizeof(Archive::MemberHeader) + 344cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getSymTabSize(); 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 346cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (0x0 != (offset & 1)) 347cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao ++offset; 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 349cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(pArchive.getARFile().hasMemArea()); 350cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 351cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryRegion* header_region = 352cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() + 353cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao offset), 354cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sizeof(Archive::MemberHeader)); 355cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const Archive::MemberHeader* header = 356cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer()); 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 358cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2)); 359cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 360cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao int strtab_size = atoi(header->size); 361cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 362cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao MemoryRegion* strtab_region = 363cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() + 364cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao offset + 365cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao sizeof(Archive::MemberHeader)), 366cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao strtab_size); 367cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao const char* strtab = 368cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao reinterpret_cast<const char*>(strtab_region->getBuffer()); 369cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 370cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getStrTable().assign(strtab, strtab_size); 371cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 372cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->release(header_region); 373cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao pArchive.getARFile().memArea()->release(strtab_region); 374cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return true; 3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 377cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// shouldIncludeStatus - given a sym name from armap and check if including 378cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao/// the corresponding archive member, and then return the decision 379cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaoenum Archive::Symbol::Status 380cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoGNUArchiveReader::shouldIncludeSymbol(const llvm::StringRef& pSymName) const 3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 382cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // TODO: handle symbol version issue and user defined symbols 383cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pSymName); 384cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (NULL != info) { 385cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (!info->isUndef()) 386cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return Archive::Symbol::Exclude; 387cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao if (info->isWeak()) 388cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return Archive::Symbol::Unknown; 389cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return Archive::Symbol::Include; 3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 391cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao return Archive::Symbol::Unknown; 3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 393cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 394