Remove the LLVM specific archive index.

Archive files (.a) can have a symbol table indicating which object
files in them define which symbols. The purpose of this symbol table
is to speed up linking by allowing the linker the read only the .o
files it is actually going to use instead of having to parse every
object's symbol table.

LLVM's archive library currently supports a LLVM specific format for
such table. It is hard to see any value in that now that llvm-ld is
gone:

* System linkers don't use it: GNU ar uses the same plugin as the
linker to create archive files with a regular index. The OS X ar
creates no symbol table for IL files, I assume the linker just parses
all IL files.

* It doesn't interact well with archives having both IL and native objects.

* We probably don't want to be responsible for yet another archive
format variant.

This patch then:

* Removes support for creating and reading such index from lib/Archive.
* Remove llvm-ranlib, since there is nothing left for it to do.

We should in the future add support for regular indexes to llvm-ar for
both native and IL objects. When we do that, llvm-ranlib should be
reimplemented as a symlink to llvm-ar, as it is equivalent to "ar s".

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184019 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2013-06-14 23:25:53 +00:00
parent d6055262d2
commit 250bfb1745
19 changed files with 19 additions and 391 deletions

View File

@ -21,7 +21,6 @@ Basic Commands
lli
llvm-link
llvm-ar
llvm-ranlib
llvm-nm
llvm-prof
llvm-config

View File

@ -283,8 +283,7 @@ The modifiers below may be applied to any operation.
This modifier requests that an archive index (or symbol table) be added to the
archive. This is the default mode of operation. The symbol table will contain
all the externally visible functions and global variables defined by all the
bitcode files in the archive. Using this modifier is more efficient that using
llvm-ranlib|llvm-ranlib which also creates the symbol table.
bitcode files in the archive.
@ -401,14 +400,6 @@ fmag - char[2]
utility in identifying archive files that have been corrupted.
The LLVM symbol table has the special name "#_LLVM_SYM_TAB_#". It is presumed
that no regular archive member file will want this name. The LLVM symbol table
is simply composed of a sequence of triplets: byte offset, length of symbol,
and the symbol itself. Symbols are not null or newline terminated. Here are
the details on each of these items:
offset - vbr encoded 32-bit integer
The offset item provides the offset into the archive file where the bitcode
@ -455,4 +446,4 @@ SEE ALSO
--------
llvm-ranlib|llvm-ranlib, ar(1)
ar(1)

View File

@ -1,61 +0,0 @@
llvm-ranlib - Generate index for LLVM archive
=============================================
SYNOPSIS
--------
**llvm-ranlib** [--version] [-help] <archive-file>
DESCRIPTION
-----------
The **llvm-ranlib** command is similar to the common Unix utility, ``ranlib``. It
adds or updates the symbol table in an LLVM archive file. Note that using the
**llvm-ar** modifier *s* is usually more efficient than running **llvm-ranlib**
which is only provided only for completness and compatibility. Unlike other
implementations of ``ranlib``, **llvm-ranlib** indexes LLVM bitcode files, not
native object modules. You can list the contents of the symbol table with the
``llvm-nm -s`` command.
OPTIONS
-------
*archive-file*
Specifies the archive-file to which the symbol table is added or updated.
*--version*
Print the version of **llvm-ranlib** and exit without building a symbol table.
*-help*
Print usage help for **llvm-ranlib** and exit without building a symbol table.
EXIT STATUS
-----------
If **llvm-ranlib** succeeds, it will exit with 0. If an error occurs, a non-zero
exit code will be returned.
SEE ALSO
--------
llvm-ar|llvm-ar, ranlib(1)

View File

@ -50,11 +50,10 @@ class ArchiveMember : public ilist_node<ArchiveMember> {
enum Flags {
SVR4SymbolTableFlag = 1, ///< Member is a SVR4 symbol table
BSD4SymbolTableFlag = 2, ///< Member is a BSD4 symbol table
LLVMSymbolTableFlag = 4, ///< Member is an LLVM symbol table
BitcodeFlag = 8, ///< Member is bitcode
HasPathFlag = 16, ///< Member has a full or partial path
HasLongFilenameFlag = 32, ///< Member uses the long filename syntax
StringTableFlag = 64 ///< Member is an ar(1) format string table
BitcodeFlag = 4, ///< Member is bitcode
HasPathFlag = 8, ///< Member has a full or partial path
HasLongFilenameFlag = 16, ///< Member uses the long filename syntax
StringTableFlag = 32 ///< Member is an ar(1) format string table
};
/// @}
@ -117,10 +116,6 @@ class ArchiveMember : public ilist_node<ArchiveMember> {
/// @brief Determine if this member is a BSD4.4 symbol table.
bool isBSD4SymbolTable() const { return flags&BSD4SymbolTableFlag; }
/// @returns true iff the archive member is the LLVM symbol table
/// @brief Determine if this member is the LLVM symbol table.
bool isLLVMSymbolTable() const { return flags&LLVMSymbolTableFlag; }
/// @returns true iff the archive member is the ar(1) string table
/// @brief Determine if this member is the ar(1) string table.
bool isStringTable() const { return flags&StringTableFlag; }
@ -445,13 +440,6 @@ class Archive {
/// into memory.
explicit Archive(const sys::Path& filename, LLVMContext& C);
/// @param data The symbol table data to be parsed
/// @param len The length of the symbol table data
/// @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.
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(
@ -475,9 +463,6 @@ class Archive {
/// @brief Load just the symbol table.
bool loadSymbolTable(std::string* ErrMessage);
/// @brief Write the symbol table to an ofstream.
void writeSymbolTable(std::ofstream& ARFile);
/// 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.

View File

@ -90,12 +90,6 @@ bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) {
else
flags &= ~BSD4SymbolTableFlag;
// LLVM symbol tables have a very specific name
if (path.str() == ARFILE_LLVM_SYMTAB_NAME)
flags |= LLVMSymbolTableFlag;
else
flags &= ~LLVMSymbolTableFlag;
// String table name
if (path.str() == ARFILE_STRTAB_NAME)
flags |= StringTableFlag;

View File

@ -22,7 +22,6 @@
#define ARFILE_MAGIC "!<arch>\n" ///< magic string
#define ARFILE_MAGIC_LEN (sizeof(ARFILE_MAGIC)-1) ///< length of magic string
#define ARFILE_SVR4_SYMTAB_NAME "/ " ///< SVR4 symtab entry name
#define ARFILE_LLVM_SYMTAB_NAME "#_LLVM_SYM_TAB_#" ///< LLVM symtab entry name
#define ARFILE_BSD4_SYMTAB_NAME "__.SYMDEF SORTED" ///< BSD4 symtab entry name
#define ARFILE_STRTAB_NAME "// " ///< Name of string table
#define ARFILE_PAD "\n" ///< inter-file align padding

View File

@ -37,37 +37,6 @@ static inline unsigned readInteger(const char*&At, const char*End) {
return Result;
}
// Completely parse the Archive's symbol table and populate symTab member var.
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 == 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.
@ -108,10 +77,8 @@ Archive::parseMemberHeader(const char*& At, const char* End, std::string* error)
// for long file names. This library doesn't generate either of those but
// it will accept them. If the name starts with #1/ and the remainder is
// digits, then those digits specify the length of the name that is
// stored immediately following the header. The special name
// __LLVM_SYM_TAB__ identifies the symbol table for LLVM bitcode.
// Anything else is a regular, short filename that is terminated with
// a '/' and blanks.
// stored immediately following the header. Anything else is a regular, short
// filename that is terminated with a '/' and blanks.
std::string pathname;
switch (Hdr->name[0]) {
@ -129,16 +96,6 @@ Archive::parseMemberHeader(const char*& At, const char* End, std::string* 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.
// This format is standard for 4.4BSD and Mac OSX operating
// systems. LLVM uses it similarly. In this format, the
// remainder of the name field (after #1/) specifies the
// length of the file name which occupy the first bytes of
// the member's data. The pathname already has the #1/ stripped.
pathname.assign(ARFILE_LLVM_SYMTAB_NAME);
flags |= ArchiveMember::LLVMSymbolTableFlag;
}
break;
case '/':
@ -259,7 +216,6 @@ Archive::loadArchive(std::string* error) {
At += 8; // Skip the magic string.
bool seenSymbolTable = false;
bool foundFirstFile = false;
while (At < End) {
// parse the member header
@ -291,21 +247,6 @@ Archive::loadArchive(std::string* error) {
if ((intptr_t(At) & 1) == 1)
At++;
delete mbr;
} 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) {
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)
At++;
delete mbr; // We don't need this member in the list of members.
} else {
// This is just a regular file. If its the first one, save its offset.
// Otherwise just push it on the list and move on to the next file.
@ -412,26 +353,11 @@ Archive::loadSymbolTable(std::string* ErrorMsg) {
}
}
// See if its the symbol table
if (mbr->isLLVMSymbolTable()) {
if (!parseSymbolTable(mbr->getData(), mbr->getSize(), ErrorMsg)) {
delete mbr;
return false;
}
At += mbr->getSize();
if ((intptr_t(At) & 1) == 1)
At++;
delete mbr;
// Can't be any more symtab headers so just advance
FirstFile = At;
} else {
// There's no symbol table in the file. We have to rebuild it from scratch
// because the intent of this method is to get the symbol table loaded so
// it can be searched efficiently.
// Add the member to the members list
members.push_back(mbr);
}
// There's no symbol table in the file. We have to rebuild it from scratch
// because the intent of this method is to get the symbol table loaded so
// it can be searched efficiently.
// Add the member to the members list
members.push_back(mbr);
firstFileOffset = FirstFile - base;
return true;

View File

@ -113,8 +113,6 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr,
memcpy(hdr.name,ARFILE_SVR4_SYMTAB_NAME,16);
} else if (mbr.isBSD4SymbolTable()) {
memcpy(hdr.name,ARFILE_BSD4_SYMTAB_NAME,16);
} else if (mbr.isLLVMSymbolTable()) {
memcpy(hdr.name,ARFILE_LLVM_SYMTAB_NAME,16);
} else if (TruncateNames) {
const char* nm = mbrPath.c_str();
unsigned len = mbrPath.length();
@ -289,61 +287,6 @@ Archive::writeMember(
return false;
}
// Write out the LLVM symbol table as an archive member to the file.
void
Archive::writeSymbolTable(std::ofstream& ARFile) {
// Construct the symbol table's header
ArchiveMemberHeader Hdr;
Hdr.init();
memcpy(Hdr.name,ARFILE_LLVM_SYMTAB_NAME,16);
uint64_t secondsSinceEpoch = sys::TimeValue::now().toEpochTime();
char buffer[32];
sprintf(buffer, "%-8o", 0644);
memcpy(Hdr.mode,buffer,8);
sprintf(buffer, "%-6u", sys::Process::GetCurrentUserId());
memcpy(Hdr.uid,buffer,6);
sprintf(buffer, "%-6u", sys::Process::GetCurrentGroupId());
memcpy(Hdr.gid,buffer,6);
sprintf(buffer,"%-12u", unsigned(secondsSinceEpoch));
memcpy(Hdr.date,buffer,12);
sprintf(buffer,"%-10u",symTabSize);
memcpy(Hdr.size,buffer,10);
// Write the header
ARFile.write((char*)&Hdr, sizeof(Hdr));
#ifndef NDEBUG
// Save the starting position of the symbol tables data content.
unsigned startpos = ARFile.tellp();
#endif
// Write out the symbols sequentially
for ( Archive::SymTabType::iterator I = symTab.begin(), E = symTab.end();
I != E; ++I)
{
// Write out the file index
writeInteger(I->second, ARFile);
// Write out the length of the symbol
writeInteger(I->first.length(), ARFile);
// Write out the symbol
ARFile.write(I->first.data(), I->first.length());
}
#ifndef NDEBUG
// Now that we're done with the symbol table, get the ending file position
unsigned endpos = ARFile.tellp();
#endif
// Make sure that the amount we wrote is what we pre-computed. This is
// critical for file integrity purposes.
assert(endpos - startpos == symTabSize && "Invalid symTabSize computation");
// Make sure the symbol table is even sized
if (symTabSize % 2 != 0 )
ARFile << ARFILE_PAD;
}
// Write the entire archive to the file specified when the archive was created.
// This writes to a temporary file first. Options are for creating a symbol
// table, flattening the file names (no directories, 15 chars max) and
@ -453,9 +396,6 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames,
}
}
// 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,

View File

@ -24,8 +24,7 @@ static const char *Magic = "!<arch>\n";
static bool isInternalMember(const ArchiveMemberHeader &amh) {
static const char *const internals[] = {
"/",
"//",
"#_LLVM_SYM_TAB_#"
"//"
};
StringRef name = amh.getName();

View File

@ -1,7 +1,7 @@
test/Regression/Archive
=======================
This directory contains various tests of llvm-ar and llvm-ranlib to ensure
This directory contains various tests of llvm-ar and to ensure
compatibility reading other ar(1) formats. It also provides a basic
functionality test for these tools.

View File

@ -216,9 +216,8 @@ for pattern in [r"\bbugpoint\b(?!-)", r"(?<!/|-)\bclang\b(?!-)",
r"\bllvm-extract\b", r"\bllvm-jistlistener\b",
r"\bllvm-link\b", r"\bllvm-mc\b",
r"\bllvm-nm\b", r"\bllvm-objdump\b",
r"\bllvm-prof\b", r"\bllvm-ranlib\b",
r"\bllvm-prof\b", r"\bllvm-size\b",
r"\bllvm-rtdyld\b", r"\bllvm-shlib\b",
r"\bllvm-size\b",
# Match llvmc but not -llvmc
NOHYPHEN + r"\bllvmc\b",
r"\blto\b",

View File

@ -14,7 +14,6 @@ add_subdirectory(llvm-dis)
add_subdirectory(llvm-mc)
add_subdirectory(llc)
add_subdirectory(llvm-ranlib)
add_subdirectory(llvm-ar)
add_subdirectory(llvm-nm)
add_subdirectory(llvm-size)

View File

@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-ranlib llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup
subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup
[component_0]
type = Group

View File

@ -28,7 +28,7 @@ OPTIONAL_DIRS := lldb
# in parallel builds. Please retain this ordering.
DIRS := llvm-config
PARALLEL_DIRS := opt llvm-as llvm-dis \
llc llvm-ranlib llvm-ar llvm-nm \
llc llvm-ar llvm-nm \
llvm-prof llvm-link \
lli llvm-extract llvm-mc \
bugpoint llvm-bcanalyzer \

View File

@ -376,7 +376,7 @@ bool doPrint(std::string* ErrMsg) {
const char* data = reinterpret_cast<const char*>(I->getData());
// Skip things that don't make sense to print
if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() ||
if (I->isSVR4SymbolTable() ||
I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode()))
continue;

View File

@ -1,5 +0,0 @@
set(LLVM_LINK_COMPONENTS archive)
add_llvm_tool(llvm-ranlib
llvm-ranlib.cpp
)

View File

@ -1,22 +0,0 @@
;===- ./tools/llvm-ranlib/LLVMBuild.txt ------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Tool
name = llvm-ranlib
parent = Tools
required_libraries = Archive

View File

@ -1,17 +0,0 @@
##===- tools/llvm-ranlib/Makefile --------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL := ../..
TOOLNAME := llvm-ranlib
LINK_COMPONENTS := archive
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
include $(LEVEL)/Makefile.common

View File

@ -1,98 +0,0 @@
//===-- llvm-ranlib.cpp - LLVM archive index generator --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Adds or updates an index (symbol table) for an LLVM archive file.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
#include "llvm/Bitcode/Archive.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
using namespace llvm;
// llvm-ar operation code and modifier flags
static cl::opt<std::string>
ArchiveName(cl::Positional, cl::Optional, cl::desc("<archive-file>"));
static cl::opt<bool>
Verbose("verbose",cl::Optional,cl::init(false),
cl::desc("Print the symbol table"));
// printSymbolTable - print out the archive's symbol table.
void printSymbolTable(Archive* TheArchive) {
outs() << "\nArchive Symbol Table:\n";
const Archive::SymTabType& symtab = TheArchive->getSymbolTable();
for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end();
I != E; ++I ) {
unsigned offset = TheArchive->getFirstFileOffset() + I->second;
outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n";
}
}
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Have the command line options parsed and handle things
// like --help and --version.
cl::ParseCommandLineOptions(argc, argv,
"LLVM Archive Index Generator (llvm-ranlib)\n\n"
" This program adds or updates an index of bitcode symbols\n"
" to an LLVM archive file."
);
int exitCode = 0;
// Check the path name of the archive
sys::Path ArchivePath;
if (!ArchivePath.set(ArchiveName)) {
errs() << argv[0] << ": " << "Archive name invalid: " << ArchiveName <<
"\n";
return 1;
}
// Make sure it exists, we don't create empty archives
bool Exists;
if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) {
errs() << argv[0] << ": " << "Archive file does not exist" <<
ArchivePath.str() << "\n";
return 1;
}
std::string err_msg;
OwningPtr<Archive>
AutoArchive(Archive::OpenAndLoad(ArchivePath, Context, &err_msg));
Archive* TheArchive = AutoArchive.get();
if (!TheArchive) {
errs() << argv[0] << ": " << err_msg << "\n";
return 1;
}
if (TheArchive->writeToDisk(true, false, &err_msg )) {
errs() << argv[0] << ": " << err_msg << "\n";
return 1;
}
if (Verbose)
printSymbolTable(TheArchive);
return exitCode;
}