summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Bytecode/Archive.h24
-rw-r--r--lib/Archive/ArchiveWriter.cpp207
-rw-r--r--lib/Bytecode/Archive/ArchiveWriter.cpp207
-rw-r--r--tools/llvm-ar/llvm-ar.cpp16
-rw-r--r--tools/llvm-ranlib/llvm-ranlib.cpp3
5 files changed, 250 insertions, 207 deletions
diff --git a/include/llvm/Bytecode/Archive.h b/include/llvm/Bytecode/Archive.h
index dfc31261f6..93ec254a6f 100644
--- a/include/llvm/Bytecode/Archive.h
+++ b/include/llvm/Bytecode/Archive.h
@@ -438,12 +438,14 @@ class Archive {
/// name will be truncated at 15 characters. If \p Compress is specified,
/// all archive members will be compressed before being written. If
/// \p PrintSymTab is true, the symbol table will be printed to std::cout.
- /// @throws std::string if an error occurs
+ /// @returns false if an error occurred, \p error set to error message
+ /// @returns true if the writing succeeded.
/// @brief Write (possibly modified) archive contents to disk
- void writeToDisk(
+ bool writeToDisk(
bool CreateSymbolTable=false, ///< Create Symbol table
bool TruncateNames=false, ///< Truncate the filename to 15 chars
- bool Compress=false ///< Compress files
+ bool Compress=false, ///< Compress files
+ std::string* error = 0 ///< If non-null, where error msg is set
);
/// This method adds a new file to the archive. The \p filename is examined
@@ -481,9 +483,19 @@ class Archive {
/// @brief Write the symbol table to an ofstream.
void writeSymbolTable(std::ofstream& ARFile);
- /// @brief Write one ArchiveMember to an ofstream.
- void writeMember(const ArchiveMember& member, std::ofstream& ARFile,
- bool CreateSymbolTable, bool TruncateNames, bool ShouldCompress);
+ /// Writes one ArchiveMember to an ofstream. If an error occurs, returns
+ /// false, otherwise true. If an error occurs and error is non-null then
+ /// it will be set to an error message.
+ /// @returns true Writing member succeeded
+ /// @returns false Writing member failed, \p error set to error message
+ bool writeMember(
+ const ArchiveMember& member, ///< The member to be written
+ std::ofstream& ARFile, ///< The file to write member onto
+ 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
+ );
/// @brief Fill in an ArchiveMemberHeader from ArchiveMember.
bool fillHeader(const ArchiveMember&mbr,
diff --git a/lib/Archive/ArchiveWriter.cpp b/lib/Archive/ArchiveWriter.cpp
index be34356a56..87816651d7 100644
--- a/lib/Archive/ArchiveWriter.cpp
+++ b/lib/Archive/ArchiveWriter.cpp
@@ -184,13 +184,14 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where) {
}
// Write one member out to the file.
-void
+bool
Archive::writeMember(
const ArchiveMember& member,
std::ofstream& ARFile,
bool CreateSymbolTable,
bool TruncateNames,
- bool ShouldCompress
+ bool ShouldCompress,
+ std::string* error
) {
unsigned filepos = ARFile.tellp();
@@ -235,8 +236,12 @@ Archive::writeMember(
// We don't need this module any more.
delete MP;
} else {
- throw std::string("Can't parse bytecode member: ") +
- member.getPath().toString();
+ if (mFile != 0) {
+ mFile->close();
+ delete mFile;
+ }
+ if (error)
+ *error = "Can't parse bytecode member: " + member.getPath().toString();
}
}
@@ -263,7 +268,9 @@ Archive::writeMember(
data +=4;
fSize -= 4;
}
- fSize = Compressor::compressToNewBuffer(data,fSize,output);
+ fSize = Compressor::compressToNewBuffer(data,fSize,output,error);
+ if (fSize == 0)
+ return false;
data = output;
if (member.isBytecode())
hdrSize = -fSize-4;
@@ -307,6 +314,7 @@ Archive::writeMember(
mFile->close();
delete mFile;
}
+ return true;
}
// Write out the LLVM symbol table as an archive member to the file.
@@ -364,9 +372,10 @@ Archive::writeSymbolTable(std::ofstream& ARFile) {
// This writes to a temporary file first. Options are for creating a symbol
// table, flattening the file names (no directories, 15 chars max) and
// compressing each archive member.
-void
-Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){
-
+bool
+Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
+ std::string* error)
+{
// Make sure they haven't opened up the file, not loaded it,
// but are now trying to write it which would wipe out the file.
assert(!(members.empty() && mapfile->size() > 8) &&
@@ -379,104 +388,106 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){
// Make sure the temporary gets removed if we crash
sys::RemoveFileOnSignal(TmpArchive);
- // Ensure we can remove the temporary even in the face of an exception
- try {
- // Create archive file for output.
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode);
+ // Create archive file for output.
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode);
+
+ // Check for errors opening or creating archive file.
+ if ( !ArchiveFile.is_open() || ArchiveFile.bad() ) {
+ if (TmpArchive.exists())
+ TmpArchive.eraseFromDisk();
+ if (error)
+ *error = "Error opening archive file: " + archPath.toString();
+ return false;
+ }
+
+ // If we're creating a symbol table, reset it now
+ if (CreateSymbolTable) {
+ symTabSize = 0;
+ symTab.clear();
+ }
- // Check for errors opening or creating archive file.
- if ( !ArchiveFile.is_open() || ArchiveFile.bad() ) {
- throw std::string("Error opening archive file: ") + archPath.toString();
+ // Write magic string to archive.
+ ArchiveFile << ARFILE_MAGIC;
+
+ // Loop over all member files, and write them out. Note that this also
+ // builds the symbol table, symTab.
+ for ( MembersList::iterator I = begin(), E = end(); I != E; ++I) {
+ if (!writeMember(*I,ArchiveFile,CreateSymbolTable,
+ TruncateNames,Compress,error))
+ {
+ if (TmpArchive.exists())
+ TmpArchive.eraseFromDisk();
+ ArchiveFile.close();
+ return false;
}
+ }
- // If we're creating a symbol table, reset it now
- if (CreateSymbolTable) {
- symTabSize = 0;
- symTab.clear();
+ // Close archive file.
+ ArchiveFile.close();
+
+ // Write the symbol table
+ if (CreateSymbolTable) {
+ // At this point we have written a file that is a legal archive but it
+ // doesn't have a symbol table in it. To aid in faster reading and to
+ // ensure compatibility with other archivers we need to put the symbol
+ // table first in the file. Unfortunately, this means mapping the file
+ // we just wrote back in and copying it to the destination file.
+
+ // Map in the archive we just wrote.
+ sys::MappedFile arch(TmpArchive);
+ const char* base = (const char*) arch.map();
+
+ // Open another temporary file in order to avoid invalidating the
+ // mmapped data
+ sys::Path FinalFilePath = archPath;
+ FinalFilePath.createTemporaryFileOnDisk();
+ sys::RemoveFileOnSignal(FinalFilePath);
+
+ std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
+ if ( !FinalFile.is_open() || FinalFile.bad() ) {
+ if (TmpArchive.exists())
+ TmpArchive.eraseFromDisk();
+ if (error)
+ *error = "Error opening archive file: " + FinalFilePath.toString();
+ return false;
}
- // Write magic string to archive.
- ArchiveFile << ARFILE_MAGIC;
+ // Write the file magic number
+ FinalFile << ARFILE_MAGIC;
- // Loop over all member files, and write them out. Note that this also
- // builds the symbol table, symTab.
- for ( MembersList::iterator I = begin(), E = end(); I != E; ++I) {
- writeMember(*I,ArchiveFile,CreateSymbolTable,TruncateNames,Compress);
+ // If there is a foreign symbol table, put it into the file now. Most
+ // ar(1) implementations require the symbol table to be first but llvm-ar
+ // can deal with it being after a foreign symbol table. This ensures
+ // 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);
}
- // Close archive file.
- ArchiveFile.close();
-
- // Write the symbol table
- if (CreateSymbolTable) {
- // At this point we have written a file that is a legal archive but it
- // doesn't have a symbol table in it. To aid in faster reading and to
- // ensure compatibility with other archivers we need to put the symbol
- // table first in the file. Unfortunately, this means mapping the file
- // we just wrote back in and copying it to the destination file.
-
- // Map in the archive we just wrote.
- sys::MappedFile arch(TmpArchive);
- const char* base = (const char*) arch.map();
-
- // Open another temporary file in order to avoid invalidating the mmapped data
- sys::Path FinalFilePath = archPath;
- FinalFilePath.createTemporaryFileOnDisk();
- sys::RemoveFileOnSignal(FinalFilePath);
- try {
-
-
- std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
- if ( !FinalFile.is_open() || FinalFile.bad() ) {
- throw std::string("Error opening archive file: ") + FinalFilePath.toString();
- }
-
- // Write the file magic number
- FinalFile << ARFILE_MAGIC;
-
- // If there is a foreign symbol table, put it into the file now. Most
- // ar(1) implementations require the symbol table to be first but llvm-ar
- // can deal with it being after a foreign symbol table. This ensures
- // 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);
- }
-
- // Put out the LLVM symbol table now.
- writeSymbolTable(FinalFile);
-
- // Copy the temporary file contents being sure to skip the file's magic
- // number.
- FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
- arch.size()-sizeof(ARFILE_MAGIC)+1);
-
- // Close up shop
- FinalFile.close();
- arch.close();
-
- // Move the final file over top of TmpArchive
- FinalFilePath.renamePathOnDisk(TmpArchive);
- } catch (...) {
- // Make sure we clean up.
- if (FinalFilePath.exists())
- FinalFilePath.eraseFromDisk();
- throw;
- }
- }
-
- // Before we replace the actual archive, we need to forget all the
- // members, since they point to data in that old archive. We need to do
- // we cannot replace an open file on Windows.
- cleanUpMemory();
+ // Put out the LLVM symbol table now.
+ writeSymbolTable(FinalFile);
+
+ // Copy the temporary file contents being sure to skip the file's magic
+ // number.
+ FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
+ arch.size()-sizeof(ARFILE_MAGIC)+1);
+
+ // Close up shop
+ FinalFile.close();
+ arch.close();
- TmpArchive.renamePathOnDisk(archPath);
- } catch (...) {
- // Make sure we clean up.
- if (TmpArchive.exists())
- TmpArchive.eraseFromDisk();
- throw;
+ // Move the final file over top of TmpArchive
+ FinalFilePath.renamePathOnDisk(TmpArchive);
}
+
+ // Before we replace the actual archive, we need to forget all the
+ // members, since they point to data in that old archive. We need to do
+ // this because we cannot replace an open file on Windows.
+ cleanUpMemory();
+
+ TmpArchive.renamePathOnDisk(archPath);
+
+ return true;
}
diff --git a/lib/Bytecode/Archive/ArchiveWriter.cpp b/lib/Bytecode/Archive/ArchiveWriter.cpp
index be34356a56..87816651d7 100644
--- a/lib/Bytecode/Archive/ArchiveWriter.cpp
+++ b/lib/Bytecode/Archive/ArchiveWriter.cpp
@@ -184,13 +184,14 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where) {
}
// Write one member out to the file.
-void
+bool
Archive::writeMember(
const ArchiveMember& member,
std::ofstream& ARFile,
bool CreateSymbolTable,
bool TruncateNames,
- bool ShouldCompress
+ bool ShouldCompress,
+ std::string* error
) {
unsigned filepos = ARFile.tellp();
@@ -235,8 +236,12 @@ Archive::writeMember(
// We don't need this module any more.
delete MP;
} else {
- throw std::string("Can't parse bytecode member: ") +
- member.getPath().toString();
+ if (mFile != 0) {
+ mFile->close();
+ delete mFile;
+ }
+ if (error)
+ *error = "Can't parse bytecode member: " + member.getPath().toString();
}
}
@@ -263,7 +268,9 @@ Archive::writeMember(
data +=4;
fSize -= 4;
}
- fSize = Compressor::compressToNewBuffer(data,fSize,output);
+ fSize = Compressor::compressToNewBuffer(data,fSize,output,error);
+ if (fSize == 0)
+ return false;
data = output;
if (member.isBytecode())
hdrSize = -fSize-4;
@@ -307,6 +314,7 @@ Archive::writeMember(
mFile->close();
delete mFile;
}
+ return true;
}
// Write out the LLVM symbol table as an archive member to the file.
@@ -364,9 +372,10 @@ Archive::writeSymbolTable(std::ofstream& ARFile) {
// This writes to a temporary file first. Options are for creating a symbol
// table, flattening the file names (no directories, 15 chars max) and
// compressing each archive member.
-void
-Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){
-
+bool
+Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
+ std::string* error)
+{
// Make sure they haven't opened up the file, not loaded it,
// but are now trying to write it which would wipe out the file.
assert(!(members.empty() && mapfile->size() > 8) &&
@@ -379,104 +388,106 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){
// Make sure the temporary gets removed if we crash
sys::RemoveFileOnSignal(TmpArchive);
- // Ensure we can remove the temporary even in the face of an exception
- try {
- // Create archive file for output.
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode);
+ // Create archive file for output.
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode);
+
+ // Check for errors opening or creating archive file.
+ if ( !ArchiveFile.is_open() || ArchiveFile.bad() ) {
+ if (TmpArchive.exists())
+ TmpArchive.eraseFromDisk();
+ if (error)
+ *error = "Error opening archive file: " + archPath.toString();
+ return false;
+ }
+
+ // If we're creating a symbol table, reset it now
+ if (CreateSymbolTable) {
+ symTabSize = 0;
+ symTab.clear();
+ }
- // Check for errors opening or creating archive file.
- if ( !ArchiveFile.is_open() || ArchiveFile.bad() ) {
- throw std::string("Error opening archive file: ") + archPath.toString();
+ // Write magic string to archive.
+ ArchiveFile << ARFILE_MAGIC;
+
+ // Loop over all member files, and write them out. Note that this also
+ // builds the symbol table, symTab.
+ for ( MembersList::iterator I = begin(), E = end(); I != E; ++I) {
+ if (!writeMember(*I,ArchiveFile,CreateSymbolTable,
+ TruncateNames,Compress,error))
+ {
+ if (TmpArchive.exists())
+ TmpArchive.eraseFromDisk();
+ ArchiveFile.close();
+ return false;
}
+ }
- // If we're creating a symbol table, reset it now
- if (CreateSymbolTable) {
- symTabSize = 0;
- symTab.clear();
+ // Close archive file.
+ ArchiveFile.close();
+
+ // Write the symbol table
+ if (CreateSymbolTable) {
+ // At this point we have written a file that is a legal archive but it
+ // doesn't have a symbol table in it. To aid in faster reading and to
+ // ensure compatibility with other archivers we need to put the symbol
+ // table first in the file. Unfortunately, this means mapping the file
+ // we just wrote back in and copying it to the destination file.
+
+ // Map in the archive we just wrote.
+ sys::MappedFile arch(TmpArchive);
+ const char* base = (const char*) arch.map();
+
+ // Open another temporary file in order to avoid invalidating the
+ // mmapped data
+ sys::Path FinalFilePath = archPath;
+ FinalFilePath.createTemporaryFileOnDisk();
+ sys::RemoveFileOnSignal(FinalFilePath);
+
+ std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
+ if ( !FinalFile.is_open() || FinalFile.bad() ) {
+ if (TmpArchive.exists())
+ TmpArchive.eraseFromDisk();
+ if (error)
+ *error = "Error opening archive file: " + FinalFilePath.toString();
+ return false;
}
- // Write magic string to archive.
- ArchiveFile << ARFILE_MAGIC;
+ // Write the file magic number
+ FinalFile << ARFILE_MAGIC;
- // Loop over all member files, and write them out. Note that this also
- // builds the symbol table, symTab.
- for ( MembersList::iterator I = begin(), E = end(); I != E; ++I) {
- writeMember(*I,ArchiveFile,CreateSymbolTable,TruncateNames,Compress);
+ // If there is a foreign symbol table, put it into the file now. Most
+ // ar(1) implementations require the symbol table to be first but llvm-ar
+ // can deal with it being after a foreign symbol table. This ensures
+ // 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);
}
- // Close archive file.
- ArchiveFile.close();
-
- // Write the symbol table
- if (CreateSymbolTable) {
- // At this point we have written a file that is a legal archive but it
- // doesn't have a symbol table in it. To aid in faster reading and to
- // ensure compatibility with other archivers we need to put the symbol
- // table first in the file. Unfortunately, this means mapping the file
- // we just wrote back in and copying it to the destination file.
-
- // Map in the archive we just wrote.
- sys::MappedFile arch(TmpArchive);
- const char* base = (const char*) arch.map();
-
- // Open another temporary file in order to avoid invalidating the mmapped data
- sys::Path FinalFilePath = archPath;
- FinalFilePath.createTemporaryFileOnDisk();
- sys::RemoveFileOnSignal(FinalFilePath);
- try {
-
-
- std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
- if ( !FinalFile.is_open() || FinalFile.bad() ) {
- throw std::string("Error opening archive file: ") + FinalFilePath.toString();
- }
-
- // Write the file magic number
- FinalFile << ARFILE_MAGIC;
-
- // If there is a foreign symbol table, put it into the file now. Most
- // ar(1) implementations require the symbol table to be first but llvm-ar
- // can deal with it being after a foreign symbol table. This ensures
- // 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);
- }
-
- // Put out the LLVM symbol table now.
- writeSymbolTable(FinalFile);
-
- // Copy the temporary file contents being sure to skip the file's magic
- // number.
- FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
- arch.size()-sizeof(ARFILE_MAGIC)+1);
-
- // Close up shop
- FinalFile.close();
- arch.close();
-
- // Move the final file over top of TmpArchive
- FinalFilePath.renamePathOnDisk(TmpArchive);
- } catch (...) {
- // Make sure we clean up.
- if (FinalFilePath.exists())
- FinalFilePath.eraseFromDisk();
- throw;
- }
- }
-
- // Before we replace the actual archive, we need to forget all the
- // members, since they point to data in that old archive. We need to do
- // we cannot replace an open file on Windows.
- cleanUpMemory();
+ // Put out the LLVM symbol table now.
+ writeSymbolTable(FinalFile);
+
+ // Copy the temporary file contents being sure to skip the file's magic
+ // number.
+ FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
+ arch.size()-sizeof(ARFILE_MAGIC)+1);
+
+ // Close up shop
+ FinalFile.close();
+ arch.close();
- TmpArchive.renamePathOnDisk(archPath);
- } catch (...) {
- // Make sure we clean up.
- if (TmpArchive.exists())
- TmpArchive.eraseFromDisk();
- throw;
+ // Move the final file over top of TmpArchive
+ FinalFilePath.renamePathOnDisk(TmpArchive);
}
+
+ // Before we replace the actual archive, we need to forget all the
+ // members, since they point to data in that old archive. We need to do
+ // this because we cannot replace an open file on Windows.
+ cleanUpMemory();
+
+ TmpArchive.renamePathOnDisk(archPath);
+
+ return true;
}
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index fdcc9e6404..8bc9e048da 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -484,7 +484,9 @@ void doDelete() {
}
// We're done editting, reconstruct the archive.
- TheArchive->writeToDisk(SymTable,TruncateNames,Compression);
+ std::string errmsg;
+ if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
+ throw errmsg;
if (ReallyVerbose)
printSymbolTable();
}
@@ -536,7 +538,9 @@ void doMove() {
}
// We're done editting, reconstruct the archive.
- TheArchive->writeToDisk(SymTable,TruncateNames,Compression);
+ std::string errmsg;
+ if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
+ throw errmsg;
if (ReallyVerbose)
printSymbolTable();
}
@@ -555,7 +559,9 @@ void doQuickAppend() {
}
// We're done editting, reconstruct the archive.
- TheArchive->writeToDisk(SymTable,TruncateNames,Compression);
+ std::string errmsg;
+ if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
+ throw errmsg;
if (ReallyVerbose)
printSymbolTable();
}
@@ -642,7 +648,9 @@ void doReplaceOrInsert() {
}
// We're done editting, reconstruct the archive.
- TheArchive->writeToDisk(SymTable,TruncateNames,Compression);
+ std::string errmsg;
+ if (!TheArchive->writeToDisk(SymTable,TruncateNames,Compression,&errmsg))
+ throw errmsg;
if (ReallyVerbose)
printSymbolTable();
}
diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp
index 1c372d5f7d..a3cdc4119d 100644
--- a/tools/llvm-ranlib/llvm-ranlib.cpp
+++ b/tools/llvm-ranlib/llvm-ranlib.cpp
@@ -74,7 +74,8 @@ int main(int argc, char **argv) {
if (!TheArchive)
throw err_msg;
- TheArchive->writeToDisk(true, false, false );
+ if (!TheArchive->writeToDisk(true, false, false, &err_msg ))
+ throw err_msg;
if (Verbose)
printSymbolTable(TheArchive);