From 57c70a62e0162b531c395b9babe92ac45066a305 Mon Sep 17 00:00:00 2001 From: Tanya Lattner Date: Thu, 28 Aug 2003 15:22:38 +0000 Subject: [PATCH] First version of llvm-ar added to cvs repository. llvm-svn: 8173 --- llvm/tools/llvm-ar/Makefile | 6 + llvm/tools/llvm-ar/llvm-ar.cpp | 373 +++++++++++++++++++++++++++++++++ 2 files changed, 379 insertions(+) create mode 100644 llvm/tools/llvm-ar/Makefile create mode 100644 llvm/tools/llvm-ar/llvm-ar.cpp diff --git a/llvm/tools/llvm-ar/Makefile b/llvm/tools/llvm-ar/Makefile new file mode 100644 index 000000000000..73aabbb21acb --- /dev/null +++ b/llvm/tools/llvm-ar/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../.. + +TOOLNAME = llvm-ar +USEDLIBS = bcreader vmcore support.a + +include $(LEVEL)/Makefile.common diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp new file mode 100644 index 000000000000..0af2b05b722f --- /dev/null +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -0,0 +1,373 @@ +//===----------------------------------------------------------------------===// +// LLVM 'ar' UTILITY +// +// This utility may be invoked in the following manner: +// llvm-ar archivename files.. +// +//===----------------------------------------------------------------------===// +#include "Support/CommandLine.h" +#include "llvm/Bytecode/Reader.h" +#include "llvm/Module.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using std::string; +using std::vector; +using std::cout; + + +#define ARFMAG "\n" /* header trailer string */ +#define ARMAG "!\n" /* magic string */ +#define SARMAG 8 /* length of magic string */ + +namespace { + + // Each file member is preceded by a file member header. Which is + // of the following format: + // + // char ar_name[16] - '/' terminated file member name. + // If the file name does not fit, a dummy name is used. + // char ar_date[12] - file date in decimal + // char ar_uid[6] - User id of file owner in decimal. + // char ar_gid[6] - Group ID file belongs to in decimal. + // char ar_mode[8] - File mode in octal. + // char ar_size[10] - Size of file in decimal. + // char ar_fmag[2] - Trailer of header file, a newline. + struct ar_hdr { + char name[16]; + char date[12]; + char uid[6]; + char gid[6]; + char mode[8]; + char size[10]; + char fmag[2]; + void init() { + memset(name,' ',16); + memset(date,' ',12); + memset(uid,' ',6); + memset(gid,' ',6); + memset(mode,' ',8); + memset(size,' ',10); + memset(fmag,' ',2); + } + }; +} + +//Option to generate symbol table or not +//running llvm-ar -s is the same as ranlib +cl::opt SymbolTable ("s", cl::desc("Generate an archive symbol table")); + +//Archive name +cl::opt Archive (cl::Positional, cl::desc(""), + cl::Required); + +//For now we require one or more member files, this should change so +//we can just run llvm-ar -s on an archive to generate the symbol +//table +cl::list Members(cl::ConsumeAfter, cl::desc("...")); + + +static inline bool Error(std::string *ErrorStr, const char *Message) { + if (ErrorStr) *ErrorStr = Message; + return true; +} + + +// WriteSymbolTable - Writes symbol table to ArchiveFile, return false +// on errors. Also returns by reference size of symbol table. +// +// Overview of method: +// 1) Generate the header for the symbol table. This is a normal +// archive member header, but it has a zero length name. +// 2) For each archive member file, stat the file and parse the bytecode +// Store cummulative offset (file size + header size). +// 3) Loop over all the symbols for the current member file, +// add offset entry to offset vector, and add symbol name to its vector. +// Note: The symbol name vector is a vector of chars to speed up calculating +// the total size of the symbol table. +// 4) Update offset vector once we know the total size of symbol table. This is +// because the symbol table appears before all archive member file contents. +// We add the size of magic string, and size of symbol table to each offset. +// 5) If the new updated offset it not even, we add 1 byte to offset because +// a newline will be inserted when writing member files. This adjustment is +// cummulative (ie. each time we have an odd offset we add 1 to total adjustment). +// 6) Lastly, write symbol table to file. +// +bool WriteSymbolTable(std::ofstream &ArchiveFile) { + + //Create header for symbol table. This is essentially an empty header with the + //name set to a '/' to indicate its a symbol table. + ar_hdr Hdr; + Hdr.init(); + + //Name of symbol table is '/' + Hdr.name[0] = '/'; + Hdr.name[1] = '/0'; + + //Set the header trailer to a newline + memcpy(Hdr.fmag,ARFMAG,sizeof(ARFMAG)); + + + //Write header to archive file + ArchiveFile.write((char*)&Hdr, sizeof(Hdr)); + + + unsigned memoff = 0; //Keep Track of total size of files added to archive + vector offsets; //Vector of offsets into archive file + vector names; //Vector of characters that are the symbol names. + + //Loop over archive member files, parse bytecode, and generate symbol table. + for(unsigned i=0; ibegin(), E=M->end(); I != E; ++I) { + + //get function name + string NM = ((Function*)I)->getName(); + + //Loop over the characters in the name and add to symbol name vector + for(unsigned i=0; i> 24) & 255; + num[1] = (temp >> 16) & 255; + num[2] = (temp >> 8) & 255; + num[3] = temp & 255; + + //Write number of symbols to archive file + ArchiveFile.write(num,4); + + //Adjustment to offset to start files on even byte boundaries + unsigned adjust = 0; + + //Update offsets write symbol tabel to archive. + for(unsigned i=0; i> 24) & 255; + output[1] = (offsets[i] >> 16) & 255; + output[2] = (offsets[i] >> 8) & 255; + output[3] = offsets[i] & 255; + ArchiveFile.write(output,4); + } + + + //Write out symbol name vector. + for(unsigned i=0; i