From 8d8a7ffe580c622e7e43f1426bca64e517de0d06 Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Fri, 7 Jul 2006 20:56:50 +0000 Subject: [PATCH] Finish removal of EH usage from the Archive library. The REQUIRES_EH flag in lib/Bytecode/Archive/Makefile is now removed. One small step closer to a smaller LLVM. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29067 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bytecode/Archive.h | 39 +++-- lib/Archive/ArchiveReader.cpp | 199 ++++++++++++++++--------- lib/Archive/ArchiveWriter.cpp | 7 +- lib/Archive/Makefile | 1 - lib/Bytecode/Archive/ArchiveReader.cpp | 199 ++++++++++++++++--------- lib/Bytecode/Archive/ArchiveWriter.cpp | 7 +- lib/Bytecode/Archive/Makefile | 1 - lib/Linker/LinkArchives.cpp | 4 +- tools/llvm-nm/llvm-nm.cpp | 3 +- 9 files changed, 306 insertions(+), 154 deletions(-) diff --git a/include/llvm/Bytecode/Archive.h b/include/llvm/Bytecode/Archive.h index 93ec254a6fb..bd971cab7d0 100644 --- a/include/llvm/Bytecode/Archive.h +++ b/include/llvm/Bytecode/Archive.h @@ -307,8 +307,8 @@ class Archive { /// printing). /// @brief Open and load an archive file static Archive* OpenAndLoad( - const sys::Path& filePath, ///< The file path to open and load - std::string* ErrorMessage = 0 ///< An optional error string + const sys::Path& filePath, ///< The file path to open and load + std::string* ErrorMessage ///< An optional error string ); /// This method opens an existing archive file from \p Filename and reads in @@ -398,7 +398,8 @@ class Archive { /// contain a module that defines the \p symbol. /// @brief Look up a module by symbol name. ModuleProvider* findModuleDefiningSymbol( - const std::string& symbol ///< Symbol to be sought + const std::string& symbol, ///< Symbol to be sought + std::string* ErrMessage ///< Error message storage, if non-zero ); /// This method is similar to findModuleDefiningSymbol but allows lookup of @@ -410,9 +411,10 @@ class Archive { /// symbols to ensure they are not re-searched on a subsequent call. If /// you need to retain the list of symbols, make a copy. /// @brief Look up multiple symbols in the archive. - void findModulesDefiningSymbols( + bool findModulesDefiningSymbols( std::set& symbols, ///< Symbols to be sought - std::set& modules ///< The modules matching \p symbols + std::set& modules, ///< The modules matching \p symbols + std::string* ErrMessage ///< Error msg storage, if non-zero ); /// This method determines whether the archive is a properly formed llvm @@ -445,7 +447,7 @@ class Archive { bool CreateSymbolTable=false, ///< Create Symbol table bool TruncateNames=false, ///< Truncate the filename to 15 chars bool Compress=false, ///< Compress files - std::string* error = 0 ///< If non-null, where error msg is set + std::string* ErrMessage=0 ///< If non-null, where error msg is set ); /// This method adds a new file to the archive. The \p filename is examined @@ -465,20 +467,33 @@ class Archive { /// into memory. Archive(const sys::Path& filename, bool map = false ); + /// @param error Set to address of a std::string to get error messages + /// @returns false on error /// @brief Parse the symbol table at \p data. - void parseSymbolTable(const void* data,unsigned len); + bool parseSymbolTable(const void* data,unsigned len,std::string* error); + /// @returns A fully populated ArchiveMember or 0 if an error occurred. /// @brief Parse the header of a member starting at \p At - ArchiveMember* parseMemberHeader(const char*&At,const char*End); + ArchiveMember* parseMemberHeader( + const char*&At, ///< The pointer to the location we're parsing + const char*End, ///< The pointer to the end of the archive + std::string* error ///< Optional error message catcher + ); + /// @param error Set to address of a std::string to get error messages + /// @returns false on error /// @brief Check that the archive signature is correct - void checkSignature(); + bool checkSignature(std::string* ErrMessage); + /// @param error Set to address of a std::string to get error messages + /// @returns false on error /// @brief Load the entire archive. - void loadArchive(); + bool loadArchive(std::string* ErrMessage); + /// @param error Set to address of a std::string to get error messages + /// @returns false on error /// @brief Load just the symbol table. - void loadSymbolTable(); + bool loadSymbolTable(std::string* ErrMessage); /// @brief Write the symbol table to an ofstream. void writeSymbolTable(std::ofstream& ARFile); @@ -494,7 +509,7 @@ class Archive { bool CreateSymbolTable, ///< Should symbol table be created? bool TruncateNames, ///< Should names be truncated to 11 chars? bool ShouldCompress, ///< Should the member be compressed? - std::string* error = 0 ///< If non-null, place were error msg is set + std::string* ErrMessage ///< If non-null, place were error msg is set ); /// @brief Fill in an ArchiveMemberHeader from ArchiveMember. diff --git a/lib/Archive/ArchiveReader.cpp b/lib/Archive/ArchiveReader.cpp index f238f59882e..c8dd17c8f11 100644 --- a/lib/Archive/ArchiveReader.cpp +++ b/lib/Archive/ArchiveReader.cpp @@ -18,13 +18,13 @@ using namespace llvm; /// Read a variable-bit-rate encoded unsigned integer -inline unsigned readInteger(const char*&At, const char*End) { +inline unsigned readInteger(const char*&At, const char*End){ unsigned Shift = 0; unsigned Result = 0; do { if (At == End) - throw std::string("Ran out of data reading vbr_uint!"); + return Result; Result |= (unsigned)((*At++) & 0x7F) << Shift; Shift += 7; } while (At[-1] & 0x80); @@ -32,36 +32,48 @@ inline unsigned readInteger(const char*&At, const char*End) { } // Completely parse the Archive's symbol table and populate symTab member var. -void -Archive::parseSymbolTable(const void* data, unsigned size) { +bool +Archive::parseSymbolTable(const void* data, unsigned size, std::string* error) { const char* At = (const char*) data; const char* End = At + size; while (At < End) { unsigned offset = readInteger(At, End); + if (At == End) { + if (error) + *error = "Ran out of data reading vbr_uint for symtab offset!"; + return false; + } unsigned length = readInteger(At, End); - if (At + length > End) - throw std::string("malformed symbol table"); + if (At == End) { + if (error) + *error = "Ran out of data reading vbr_uint for symtab length!"; + return false; + } + if (At + length > End) { + if (error) + *error = "Malformed symbol table: length not consistent with size"; + return false; + } // we don't care if it can't be inserted (duplicate entry) symTab.insert(std::make_pair(std::string(At, length), offset)); At += length; } symTabSize = size; + return true; } // This member parses an ArchiveMemberHeader that is presumed to be pointed to // by At. The At pointer is updated to the byte just after the header, which // can be variable in size. ArchiveMember* -Archive::parseMemberHeader(const char*& At, const char* End) { +Archive::parseMemberHeader(const char*& At, const char* End, std::string* error) +{ assert(At + sizeof(ArchiveMemberHeader) < End && "Not enough data"); // Cast archive member header ArchiveMemberHeader* Hdr = (ArchiveMemberHeader*)At; At += sizeof(ArchiveMemberHeader); - // Instantiate the ArchiveMember to be filled - ArchiveMember* member = new ArchiveMember(this); - // Extract the size and determine if the file is // compressed or not (negative length). int flags = 0; @@ -72,12 +84,18 @@ Archive::parseMemberHeader(const char*& At, const char* End) { } // Check the size of the member for sanity - if (At + MemberSize > End) - throw std::string("invalid member length in archive file"); + if (At + MemberSize > End) { + if (error) + *error = "invalid member length in archive file"; + return 0; + } // Check the member signature - if (!Hdr->checkSignature()) - throw std::string("invalid file member signature"); + if (!Hdr->checkSignature()) { + if (error) + *error = "invalid file member signature"; + return 0; + } // Convert and check the member name // The empty name ( '/' and 15 blanks) is for a foreign (non-LLVM) symbol @@ -100,8 +118,11 @@ Archive::parseMemberHeader(const char*& At, const char* End) { At += len; MemberSize -= len; flags |= ArchiveMember::HasLongFilenameFlag; - } else - throw std::string("invalid long filename"); + } else { + if (error) + *error = "invalid long filename"; + return 0; + } } else if (Hdr->name[1] == '_' && (0 == memcmp(Hdr->name, ARFILE_LLVM_SYMTAB_NAME, 16))) { // The member is using a long file name (>15 chars) format. @@ -120,14 +141,18 @@ Archive::parseMemberHeader(const char*& At, const char* End) { pathname.assign(ARFILE_STRTAB_NAME); flags |= ArchiveMember::StringTableFlag; } else { - throw std::string("invalid string table name"); + if (error) + *error = "invalid string table name"; + return 0; } } else if (Hdr->name[1] == ' ') { if (0 == memcmp(Hdr->name, ARFILE_SVR4_SYMTAB_NAME, 16)) { pathname.assign(ARFILE_SVR4_SYMTAB_NAME); flags |= ArchiveMember::SVR4SymbolTableFlag; } else { - throw std::string("invalid SVR4 symbol table name"); + if (error) + *error = "invalid SVR4 symbol table name"; + return 0; } } else if (isdigit(Hdr->name[1])) { unsigned index = atoi(&Hdr->name[1]); @@ -145,10 +170,15 @@ Archive::parseMemberHeader(const char*& At, const char* End) { last_p = p; p++; } - if (p >= endp) - throw std::string("missing name termiantor in string table"); + if (p >= endp) { + if (error) + *error = "missing name termiantor in string table"; + return 0; + } } else { - throw std::string("name index beyond string table"); + if (error) + *error = "name index beyond string table"; + return 0; } } break; @@ -184,6 +214,9 @@ Archive::parseMemberHeader(const char*& At, const char* End) { break; } + // Instantiate the ArchiveMember to be filled + ArchiveMember* member = new ArchiveMember(this); + // Fill in fields of the ArchiveMember member->next = 0; member->prev = 0; @@ -202,18 +235,22 @@ Archive::parseMemberHeader(const char*& At, const char* End) { return member; } -void -Archive::checkSignature() { +bool +Archive::checkSignature(std::string* error) { // Check the magic string at file's header - if (mapfile->size() < 8 || memcmp(base, ARFILE_MAGIC, 8)) - throw std::string("invalid signature for an archive file"); + if (mapfile->size() < 8 || memcmp(base, ARFILE_MAGIC, 8)) { + if (error) + *error = "invalid signature for an archive file"; + return false; + } + return true; } // This function loads the entire archive and fully populates its ilist with // the members of the archive file. This is typically used in preparation for // editing the contents of the archive. -void -Archive::loadArchive() { +bool +Archive::loadArchive(std::string* error) { // Set up parsing members.clear(); @@ -221,7 +258,9 @@ Archive::loadArchive() { const char *At = base; const char *End = base + mapfile->size(); - checkSignature(); + if (!checkSignature(error)) + return false; + At += 8; // Skip the magic string. bool seenSymbolTable = false; @@ -229,7 +268,9 @@ Archive::loadArchive() { while (At < End) { // parse the member header const char* Save = At; - ArchiveMember* mbr = parseMemberHeader(At, End); + ArchiveMember* mbr = parseMemberHeader(At, End, error); + if (!mbr) + return false; // check if this is the foreign symbol table if (mbr->isSVR4SymbolTable() || mbr->isBSD4SymbolTable()) { @@ -257,9 +298,13 @@ Archive::loadArchive() { } else if (mbr->isLLVMSymbolTable()) { // This is the LLVM symbol table for the archive. If we've seen it // already, its an error. Otherwise, parse the symbol table and move on. - if (seenSymbolTable) - throw std::string("invalid archive: multiple symbol tables"); - parseSymbolTable(mbr->getData(), mbr->getSize()); + if (seenSymbolTable) { + if (error) + *error = "invalid archive: multiple symbol tables"; + return false; + } + if (!parseSymbolTable(mbr->getData(), mbr->getSize(), error)) + return false; seenSymbolTable = true; At += mbr->getSize(); if ((intptr_t(At) & 1) == 1) @@ -278,21 +323,17 @@ Archive::loadArchive() { At++; } } + return true; } // Open and completely load the archive file. Archive* -Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage) { - try { - std::auto_ptr result ( new Archive(file, true)); - result->loadArchive(); - return result.release(); - } catch (const std::string& msg) { - if (ErrorMessage) { - *ErrorMessage = msg; - } +Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage) +{ + std::auto_ptr result ( new Archive(file, true)); + if (!result->loadArchive(ErrorMessage)) return 0; - } + return result.release(); } // Get all the bytecode modules from the archive @@ -315,8 +356,8 @@ Archive::getAllModules(std::vector& Modules, std::string* ErrMessage) { } // Load just the symbol table from the archive file -void -Archive::loadSymbolTable() { +bool +Archive::loadSymbolTable(std::string* ErrorMsg) { // Set up parsing members.clear(); @@ -325,13 +366,16 @@ Archive::loadSymbolTable() { const char *End = base + mapfile->size(); // Make sure we're dealing with an archive - checkSignature(); + if (!checkSignature(ErrorMsg)) + return false; At += 8; // Skip signature // Parse the first file member header const char* FirstFile = At; - ArchiveMember* mbr = parseMemberHeader(At, End); + ArchiveMember* mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) + return false; if (mbr->isSVR4SymbolTable() || mbr->isBSD4SymbolTable()) { // Skip the foreign symbol table, we don't do anything with it @@ -342,7 +386,11 @@ Archive::loadSymbolTable() { // Read the next one FirstFile = At; - mbr = parseMemberHeader(At, End); + mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) { + delete mbr; + return false; + } } if (mbr->isStringTable()) { @@ -354,12 +402,20 @@ Archive::loadSymbolTable() { delete mbr; // Get the next one FirstFile = At; - mbr = parseMemberHeader(At, End); + mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) { + delete mbr; + return false; + } } // See if its the symbol table if (mbr->isLLVMSymbolTable()) { - parseSymbolTable(mbr->getData(), mbr->getSize()); + if (!parseSymbolTable(mbr->getData(), mbr->getSize(), ErrorMsg)) { + delete mbr; + return false; + } + At += mbr->getSize(); if ((intptr_t(At) & 1) == 1) At++; @@ -375,27 +431,23 @@ Archive::loadSymbolTable() { } firstFileOffset = FirstFile - base; + return true; } // Open the archive and load just the symbol tables Archive* Archive::OpenAndLoadSymbols(const sys::Path& file, std::string* ErrorMessage) { - try { - std::auto_ptr result ( new Archive(file, true) ); - result->loadSymbolTable(); - return result.release(); - } catch (const std::string& msg) { - if (ErrorMessage) { - *ErrorMessage = msg; - } + std::auto_ptr result ( new Archive(file, true) ); + if (!result->loadSymbolTable(ErrorMessage)) return 0; - } + return result.release(); } // Look up one symbol in the symbol table and return a ModuleProvider for the // module that defines that symbol. ModuleProvider* -Archive::findModuleDefiningSymbol(const std::string& symbol) { +Archive::findModuleDefiningSymbol(const std::string& symbol, + std::string* ErrMsg) { SymTabType::iterator SI = symTab.find(symbol); if (SI == symTab.end()) return 0; @@ -417,7 +469,9 @@ Archive::findModuleDefiningSymbol(const std::string& symbol) { // Module hasn't been loaded yet, we need to load it const char* modptr = base + fileOffset; - ArchiveMember* mbr = parseMemberHeader(modptr, base + mapfile->size()); + ArchiveMember* mbr = parseMemberHeader(modptr, base + mapfile->size(),ErrMsg); + if (!mbr) + return false; // Now, load the bytecode module to get the ModuleProvider std::string FullMemberName = archPath.toString() + "(" + @@ -433,9 +487,10 @@ Archive::findModuleDefiningSymbol(const std::string& symbol) { // Look up multiple symbols in the symbol table and return a set of // ModuleProviders that define those symbols. -void +bool Archive::findModulesDefiningSymbols(std::set& symbols, - std::set& result) + std::set& result, + std::string* error) { assert(mapfile && base && "Can't findModulesDefiningSymbols on new archive"); if (symTab.empty()) { @@ -453,7 +508,9 @@ Archive::findModulesDefiningSymbols(std::set& symbols, unsigned offset = At - base - firstFileOffset; // Parse the file's header - ArchiveMember* mbr = parseMemberHeader(At, End); + ArchiveMember* mbr = parseMemberHeader(At, End, error); + if (!mbr) + return false; // If it contains symbols if (mbr->isBytecode() || mbr->isCompressedBytecode()) { @@ -474,8 +531,11 @@ Archive::findModulesDefiningSymbols(std::set& symbols, // modules. modules.insert(std::make_pair(offset, std::make_pair(MP, mbr))); } else { - throw std::string("Can't parse bytecode member: ") + - mbr->getPath().toString(); + if (error) + *error = "Can't parse bytecode member: " + + mbr->getPath().toString(); + delete mbr; + return false; } } @@ -492,7 +552,7 @@ Archive::findModulesDefiningSymbols(std::set& symbols, for (std::set::iterator I=symbols.begin(), E=symbols.end(); I != E;) { // See if this symbol exists - ModuleProvider* mp = findModuleDefiningSymbol(*I); + ModuleProvider* mp = findModuleDefiningSymbol(*I,error); if (mp) { // The symbol exists, insert the ModuleProvider into our result, // duplicates wil be ignored @@ -505,20 +565,23 @@ Archive::findModulesDefiningSymbols(std::set& symbols, ++I; } } + return true; } bool Archive::isBytecodeArchive() { // Make sure the symTab has been loaded. In most cases this should have been // done when the archive was constructed, but still, this is just in case. if (!symTab.size()) - loadSymbolTable(); + if (!loadSymbolTable(0)) + return false; // Now that we know it's been loaded, return true // if it has a size if (symTab.size()) return true; //We still can't be sure it isn't a bytecode archive - loadArchive(); + if (!loadArchive(0)) + return false; std::vector Modules; std::string ErrorMessage; diff --git a/lib/Archive/ArchiveWriter.cpp b/lib/Archive/ArchiveWriter.cpp index 87816651d73..390fd128512 100644 --- a/lib/Archive/ArchiveWriter.cpp +++ b/lib/Archive/ArchiveWriter.cpp @@ -463,7 +463,12 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // compatibility with other ar(1) implementations as well as allowing the // archive to store both native .o and LLVM .bc files, both indexed. if (foreignST) { - writeMember(*foreignST, FinalFile, false, false, false); + if (!writeMember(*foreignST, FinalFile, false, false, false, error)) { + FinalFile.close(); + if (TmpArchive.exists()) + TmpArchive.eraseFromDisk(); + return false; + } } // Put out the LLVM symbol table now. diff --git a/lib/Archive/Makefile b/lib/Archive/Makefile index 37e67ca4fb1..0ecf38b93f0 100644 --- a/lib/Archive/Makefile +++ b/lib/Archive/Makefile @@ -13,6 +13,5 @@ LIBRARYNAME = LLVMArchive # We only want an archive so only those modules actually used by a tool are # included. BUILD_ARCHIVE := 1 -REQUIRES_EH := 1 include $(LEVEL)/Makefile.common diff --git a/lib/Bytecode/Archive/ArchiveReader.cpp b/lib/Bytecode/Archive/ArchiveReader.cpp index f238f59882e..c8dd17c8f11 100644 --- a/lib/Bytecode/Archive/ArchiveReader.cpp +++ b/lib/Bytecode/Archive/ArchiveReader.cpp @@ -18,13 +18,13 @@ using namespace llvm; /// Read a variable-bit-rate encoded unsigned integer -inline unsigned readInteger(const char*&At, const char*End) { +inline unsigned readInteger(const char*&At, const char*End){ unsigned Shift = 0; unsigned Result = 0; do { if (At == End) - throw std::string("Ran out of data reading vbr_uint!"); + return Result; Result |= (unsigned)((*At++) & 0x7F) << Shift; Shift += 7; } while (At[-1] & 0x80); @@ -32,36 +32,48 @@ inline unsigned readInteger(const char*&At, const char*End) { } // Completely parse the Archive's symbol table and populate symTab member var. -void -Archive::parseSymbolTable(const void* data, unsigned size) { +bool +Archive::parseSymbolTable(const void* data, unsigned size, std::string* error) { const char* At = (const char*) data; const char* End = At + size; while (At < End) { unsigned offset = readInteger(At, End); + if (At == End) { + if (error) + *error = "Ran out of data reading vbr_uint for symtab offset!"; + return false; + } unsigned length = readInteger(At, End); - if (At + length > End) - throw std::string("malformed symbol table"); + if (At == End) { + if (error) + *error = "Ran out of data reading vbr_uint for symtab length!"; + return false; + } + if (At + length > End) { + if (error) + *error = "Malformed symbol table: length not consistent with size"; + return false; + } // we don't care if it can't be inserted (duplicate entry) symTab.insert(std::make_pair(std::string(At, length), offset)); At += length; } symTabSize = size; + return true; } // This member parses an ArchiveMemberHeader that is presumed to be pointed to // by At. The At pointer is updated to the byte just after the header, which // can be variable in size. ArchiveMember* -Archive::parseMemberHeader(const char*& At, const char* End) { +Archive::parseMemberHeader(const char*& At, const char* End, std::string* error) +{ assert(At + sizeof(ArchiveMemberHeader) < End && "Not enough data"); // Cast archive member header ArchiveMemberHeader* Hdr = (ArchiveMemberHeader*)At; At += sizeof(ArchiveMemberHeader); - // Instantiate the ArchiveMember to be filled - ArchiveMember* member = new ArchiveMember(this); - // Extract the size and determine if the file is // compressed or not (negative length). int flags = 0; @@ -72,12 +84,18 @@ Archive::parseMemberHeader(const char*& At, const char* End) { } // Check the size of the member for sanity - if (At + MemberSize > End) - throw std::string("invalid member length in archive file"); + if (At + MemberSize > End) { + if (error) + *error = "invalid member length in archive file"; + return 0; + } // Check the member signature - if (!Hdr->checkSignature()) - throw std::string("invalid file member signature"); + if (!Hdr->checkSignature()) { + if (error) + *error = "invalid file member signature"; + return 0; + } // Convert and check the member name // The empty name ( '/' and 15 blanks) is for a foreign (non-LLVM) symbol @@ -100,8 +118,11 @@ Archive::parseMemberHeader(const char*& At, const char* End) { At += len; MemberSize -= len; flags |= ArchiveMember::HasLongFilenameFlag; - } else - throw std::string("invalid long filename"); + } else { + if (error) + *error = "invalid long filename"; + return 0; + } } else if (Hdr->name[1] == '_' && (0 == memcmp(Hdr->name, ARFILE_LLVM_SYMTAB_NAME, 16))) { // The member is using a long file name (>15 chars) format. @@ -120,14 +141,18 @@ Archive::parseMemberHeader(const char*& At, const char* End) { pathname.assign(ARFILE_STRTAB_NAME); flags |= ArchiveMember::StringTableFlag; } else { - throw std::string("invalid string table name"); + if (error) + *error = "invalid string table name"; + return 0; } } else if (Hdr->name[1] == ' ') { if (0 == memcmp(Hdr->name, ARFILE_SVR4_SYMTAB_NAME, 16)) { pathname.assign(ARFILE_SVR4_SYMTAB_NAME); flags |= ArchiveMember::SVR4SymbolTableFlag; } else { - throw std::string("invalid SVR4 symbol table name"); + if (error) + *error = "invalid SVR4 symbol table name"; + return 0; } } else if (isdigit(Hdr->name[1])) { unsigned index = atoi(&Hdr->name[1]); @@ -145,10 +170,15 @@ Archive::parseMemberHeader(const char*& At, const char* End) { last_p = p; p++; } - if (p >= endp) - throw std::string("missing name termiantor in string table"); + if (p >= endp) { + if (error) + *error = "missing name termiantor in string table"; + return 0; + } } else { - throw std::string("name index beyond string table"); + if (error) + *error = "name index beyond string table"; + return 0; } } break; @@ -184,6 +214,9 @@ Archive::parseMemberHeader(const char*& At, const char* End) { break; } + // Instantiate the ArchiveMember to be filled + ArchiveMember* member = new ArchiveMember(this); + // Fill in fields of the ArchiveMember member->next = 0; member->prev = 0; @@ -202,18 +235,22 @@ Archive::parseMemberHeader(const char*& At, const char* End) { return member; } -void -Archive::checkSignature() { +bool +Archive::checkSignature(std::string* error) { // Check the magic string at file's header - if (mapfile->size() < 8 || memcmp(base, ARFILE_MAGIC, 8)) - throw std::string("invalid signature for an archive file"); + if (mapfile->size() < 8 || memcmp(base, ARFILE_MAGIC, 8)) { + if (error) + *error = "invalid signature for an archive file"; + return false; + } + return true; } // This function loads the entire archive and fully populates its ilist with // the members of the archive file. This is typically used in preparation for // editing the contents of the archive. -void -Archive::loadArchive() { +bool +Archive::loadArchive(std::string* error) { // Set up parsing members.clear(); @@ -221,7 +258,9 @@ Archive::loadArchive() { const char *At = base; const char *End = base + mapfile->size(); - checkSignature(); + if (!checkSignature(error)) + return false; + At += 8; // Skip the magic string. bool seenSymbolTable = false; @@ -229,7 +268,9 @@ Archive::loadArchive() { while (At < End) { // parse the member header const char* Save = At; - ArchiveMember* mbr = parseMemberHeader(At, End); + ArchiveMember* mbr = parseMemberHeader(At, End, error); + if (!mbr) + return false; // check if this is the foreign symbol table if (mbr->isSVR4SymbolTable() || mbr->isBSD4SymbolTable()) { @@ -257,9 +298,13 @@ Archive::loadArchive() { } else if (mbr->isLLVMSymbolTable()) { // This is the LLVM symbol table for the archive. If we've seen it // already, its an error. Otherwise, parse the symbol table and move on. - if (seenSymbolTable) - throw std::string("invalid archive: multiple symbol tables"); - parseSymbolTable(mbr->getData(), mbr->getSize()); + if (seenSymbolTable) { + if (error) + *error = "invalid archive: multiple symbol tables"; + return false; + } + if (!parseSymbolTable(mbr->getData(), mbr->getSize(), error)) + return false; seenSymbolTable = true; At += mbr->getSize(); if ((intptr_t(At) & 1) == 1) @@ -278,21 +323,17 @@ Archive::loadArchive() { At++; } } + return true; } // Open and completely load the archive file. Archive* -Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage) { - try { - std::auto_ptr result ( new Archive(file, true)); - result->loadArchive(); - return result.release(); - } catch (const std::string& msg) { - if (ErrorMessage) { - *ErrorMessage = msg; - } +Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage) +{ + std::auto_ptr result ( new Archive(file, true)); + if (!result->loadArchive(ErrorMessage)) return 0; - } + return result.release(); } // Get all the bytecode modules from the archive @@ -315,8 +356,8 @@ Archive::getAllModules(std::vector& Modules, std::string* ErrMessage) { } // Load just the symbol table from the archive file -void -Archive::loadSymbolTable() { +bool +Archive::loadSymbolTable(std::string* ErrorMsg) { // Set up parsing members.clear(); @@ -325,13 +366,16 @@ Archive::loadSymbolTable() { const char *End = base + mapfile->size(); // Make sure we're dealing with an archive - checkSignature(); + if (!checkSignature(ErrorMsg)) + return false; At += 8; // Skip signature // Parse the first file member header const char* FirstFile = At; - ArchiveMember* mbr = parseMemberHeader(At, End); + ArchiveMember* mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) + return false; if (mbr->isSVR4SymbolTable() || mbr->isBSD4SymbolTable()) { // Skip the foreign symbol table, we don't do anything with it @@ -342,7 +386,11 @@ Archive::loadSymbolTable() { // Read the next one FirstFile = At; - mbr = parseMemberHeader(At, End); + mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) { + delete mbr; + return false; + } } if (mbr->isStringTable()) { @@ -354,12 +402,20 @@ Archive::loadSymbolTable() { delete mbr; // Get the next one FirstFile = At; - mbr = parseMemberHeader(At, End); + mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) { + delete mbr; + return false; + } } // See if its the symbol table if (mbr->isLLVMSymbolTable()) { - parseSymbolTable(mbr->getData(), mbr->getSize()); + if (!parseSymbolTable(mbr->getData(), mbr->getSize(), ErrorMsg)) { + delete mbr; + return false; + } + At += mbr->getSize(); if ((intptr_t(At) & 1) == 1) At++; @@ -375,27 +431,23 @@ Archive::loadSymbolTable() { } firstFileOffset = FirstFile - base; + return true; } // Open the archive and load just the symbol tables Archive* Archive::OpenAndLoadSymbols(const sys::Path& file, std::string* ErrorMessage) { - try { - std::auto_ptr result ( new Archive(file, true) ); - result->loadSymbolTable(); - return result.release(); - } catch (const std::string& msg) { - if (ErrorMessage) { - *ErrorMessage = msg; - } + std::auto_ptr result ( new Archive(file, true) ); + if (!result->loadSymbolTable(ErrorMessage)) return 0; - } + return result.release(); } // Look up one symbol in the symbol table and return a ModuleProvider for the // module that defines that symbol. ModuleProvider* -Archive::findModuleDefiningSymbol(const std::string& symbol) { +Archive::findModuleDefiningSymbol(const std::string& symbol, + std::string* ErrMsg) { SymTabType::iterator SI = symTab.find(symbol); if (SI == symTab.end()) return 0; @@ -417,7 +469,9 @@ Archive::findModuleDefiningSymbol(const std::string& symbol) { // Module hasn't been loaded yet, we need to load it const char* modptr = base + fileOffset; - ArchiveMember* mbr = parseMemberHeader(modptr, base + mapfile->size()); + ArchiveMember* mbr = parseMemberHeader(modptr, base + mapfile->size(),ErrMsg); + if (!mbr) + return false; // Now, load the bytecode module to get the ModuleProvider std::string FullMemberName = archPath.toString() + "(" + @@ -433,9 +487,10 @@ Archive::findModuleDefiningSymbol(const std::string& symbol) { // Look up multiple symbols in the symbol table and return a set of // ModuleProviders that define those symbols. -void +bool Archive::findModulesDefiningSymbols(std::set& symbols, - std::set& result) + std::set& result, + std::string* error) { assert(mapfile && base && "Can't findModulesDefiningSymbols on new archive"); if (symTab.empty()) { @@ -453,7 +508,9 @@ Archive::findModulesDefiningSymbols(std::set& symbols, unsigned offset = At - base - firstFileOffset; // Parse the file's header - ArchiveMember* mbr = parseMemberHeader(At, End); + ArchiveMember* mbr = parseMemberHeader(At, End, error); + if (!mbr) + return false; // If it contains symbols if (mbr->isBytecode() || mbr->isCompressedBytecode()) { @@ -474,8 +531,11 @@ Archive::findModulesDefiningSymbols(std::set& symbols, // modules. modules.insert(std::make_pair(offset, std::make_pair(MP, mbr))); } else { - throw std::string("Can't parse bytecode member: ") + - mbr->getPath().toString(); + if (error) + *error = "Can't parse bytecode member: " + + mbr->getPath().toString(); + delete mbr; + return false; } } @@ -492,7 +552,7 @@ Archive::findModulesDefiningSymbols(std::set& symbols, for (std::set::iterator I=symbols.begin(), E=symbols.end(); I != E;) { // See if this symbol exists - ModuleProvider* mp = findModuleDefiningSymbol(*I); + ModuleProvider* mp = findModuleDefiningSymbol(*I,error); if (mp) { // The symbol exists, insert the ModuleProvider into our result, // duplicates wil be ignored @@ -505,20 +565,23 @@ Archive::findModulesDefiningSymbols(std::set& symbols, ++I; } } + return true; } bool Archive::isBytecodeArchive() { // Make sure the symTab has been loaded. In most cases this should have been // done when the archive was constructed, but still, this is just in case. if (!symTab.size()) - loadSymbolTable(); + if (!loadSymbolTable(0)) + return false; // Now that we know it's been loaded, return true // if it has a size if (symTab.size()) return true; //We still can't be sure it isn't a bytecode archive - loadArchive(); + if (!loadArchive(0)) + return false; std::vector Modules; std::string ErrorMessage; diff --git a/lib/Bytecode/Archive/ArchiveWriter.cpp b/lib/Bytecode/Archive/ArchiveWriter.cpp index 87816651d73..390fd128512 100644 --- a/lib/Bytecode/Archive/ArchiveWriter.cpp +++ b/lib/Bytecode/Archive/ArchiveWriter.cpp @@ -463,7 +463,12 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // compatibility with other ar(1) implementations as well as allowing the // archive to store both native .o and LLVM .bc files, both indexed. if (foreignST) { - writeMember(*foreignST, FinalFile, false, false, false); + if (!writeMember(*foreignST, FinalFile, false, false, false, error)) { + FinalFile.close(); + if (TmpArchive.exists()) + TmpArchive.eraseFromDisk(); + return false; + } } // Put out the LLVM symbol table now. diff --git a/lib/Bytecode/Archive/Makefile b/lib/Bytecode/Archive/Makefile index 37e67ca4fb1..0ecf38b93f0 100644 --- a/lib/Bytecode/Archive/Makefile +++ b/lib/Bytecode/Archive/Makefile @@ -13,6 +13,5 @@ LIBRARYNAME = LLVMArchive # We only want an archive so only those modules actually used by a tool are # included. BUILD_ARCHIVE := 1 -REQUIRES_EH := 1 include $(LEVEL)/Makefile.common diff --git a/lib/Linker/LinkArchives.cpp b/lib/Linker/LinkArchives.cpp index 5165bad1991..e115b93ad28 100644 --- a/lib/Linker/LinkArchives.cpp +++ b/lib/Linker/LinkArchives.cpp @@ -137,7 +137,9 @@ Linker::LinkInArchive(const sys::Path &Filename) { // Find the modules we need to link into the target module std::set Modules; - arch->findModulesDefiningSymbols(UndefinedSymbols, Modules); + if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg)) + return error("Cannot find symbols in '" + Filename.toString() + + "': " + ErrMsg); // If we didn't find any more modules to link this time, we are done // searching this archive. diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index dae8f95f85e..420c9eac2f6 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -134,7 +134,8 @@ void DumpSymbolNamesFromFile (std::string &Filename) { return; } } else if (aPath.isArchive()) { - Archive* archive = Archive::OpenAndLoad(sys::Path(Filename)); + std::string ErrMsg; + Archive* archive = Archive::OpenAndLoad(sys::Path(Filename),&ErrorMessage); if (!archive) std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; std::vector Modules; -- 2.34.1