/*
 * $Revision: 42181 $
 * $Date: 2013-03-26 15:04:45 -0500 (Tue, 26 Mar 2013) $
 */


//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
//
//===----------------------------------------------------------------------===//


#include <stdlib.h>
#include <iostream>
#include <strstream>
#include <fstream>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <cstring>

using namespace std;

typedef std::string                      string_t;
typedef std::vector< string_t >          strings_t;
typedef std::map< string_t, string_t >   str_hash_t;
typedef std::pair< string_t, string_t >  str_pair_t;
#ifdef _WIN32
    typedef long long  int64_t;
#endif

string_t
shift( strings_t & strs ) {
    string_t first = strs.front();
    strs.erase( strs.begin() );
    return first;
} // shift

string_t
find(
    str_hash_t const & hash,
    string_t const &   key
) {
    string_t value;
    str_hash_t::const_iterator it = hash.find( key );
    if ( it != hash.end() ) {
        value = it->second;
    }; // if
    return value;
} // find

void die( string_t const & message ) {
    std::cerr << message << std::endl;
    exit( 1 );
} // die

void stop( string_t const & message ) {
    printf( "%s\n", message.c_str() );
    exit( 1 );
}

// An entry in the symbol table of a .obj file.
struct symbol_t {
    long long        name;
    unsigned         value;
    unsigned  short  section_num;
    unsigned  short  type;
    char             storage_class;
    char             nAux;
}; // struct symbol_t


class _rstream_t : public std::istrstream {

    private:

        const char * buf;

    protected:

        _rstream_t( pair< const char *, streamsize > p )
            : istrstream( p.first, p.second ), buf( p.first )
        {
        }

        ~_rstream_t() {
            delete [] buf;
        }

}; // class _rstream_t

/* A stream encapuslating the content of a file or the content of a string, overriding the
   >> operator to read various integer types in binary form, as well as a symbol table
   entry.
*/
class rstream_t : public _rstream_t {
private:

    template< typename type_t >
    inline rstream_t & do_read( type_t & x ) {
	read( (char*) & x, sizeof( type_t ) );
	return * this;
    }

    static pair<const char*, streamsize> getBuf(const char *fileName) {
	ifstream raw(fileName,ios::binary | ios::in);
	if(!raw.is_open())
	    stop("rstream.getBuf: Error opening file");
	raw.seekg(0,ios::end);
	streampos fileSize = raw.tellg();
	if(fileSize < 0)
	    stop("rstream.getBuf: Error reading file");
	char *buf = new char[fileSize];
	raw.seekg(0,ios::beg);
	raw.read(buf, fileSize);
	return pair<const char*, streamsize>(buf,fileSize);
    }
public:
    // construct from a string
    rstream_t( const char * buf, streamsize size ) :
        _rstream_t( pair< const char *, streamsize >( buf, size ) )
    {}
    /* construct from a file whole content is fully read once to initialize the content of
       this stream
    */
    rstream_t( string_t const & fileName )
        : _rstream_t( getBuf( fileName.c_str() ) )
    {
    }

    rstream_t & operator >>( int & x ) {
	return do_read(x);
    }
    rstream_t & operator >>(unsigned &x) {
	return do_read(x);
    }
    rstream_t & operator>>(short &x) {
	return do_read(x);
    }
    rstream_t & operator>>(unsigned short &x) {
	return do_read(x);
    }
    rstream_t & operator>>( symbol_t & e ) {
	read((char*)&e, 18);
	return *this;
    }
}; // class rstream_t

// string table in a .OBJ file
class StringTable {
private:
    map<string, unsigned> directory;
    size_t length;
    char *data;

    // make <directory> from <length> bytes in <data>
    void makeDirectory(void) {
	unsigned i = 4;
	while(i < length) {
	    string s = string(data + i);
	    directory.insert(make_pair(s, i));
	    i += s.size() + 1;
	}
    }
    // initialize <length> and <data> with contents specified by the arguments
    void init(const char *_data) {
	unsigned _length = *(unsigned*)_data;

	if(_length < sizeof(unsigned) || _length != *(unsigned*)_data)
	    stop("StringTable.init: Invalid symbol table");
	if(_data[_length - 1]) {
	    // to prevent runaway strings, make sure the data ends with a zero
	    data = new char[length = _length + 1];
	    data[_length] = 0;
	} else {
	    data = new char[length = _length];
	}
	*(unsigned*)data = length;
	memcpy( data + sizeof(unsigned), _data + sizeof(unsigned), length - sizeof(unsigned) );
	makeDirectory();
    }
public:
    StringTable( rstream_t & f ) {
	/* Construct string table by reading from f.
	 */
	streampos s;
	unsigned strSize;
	char *strData;

	s = f.tellg();
	f>>strSize;
	if(strSize < sizeof(unsigned))
	    stop("StringTable: Invalid string table");
	strData = new char[strSize];
	*(unsigned*)strData = strSize;
	// read the raw data into <strData>
	f.read(strData + sizeof(unsigned), strSize - sizeof(unsigned));
	s = f.tellg() - s;
	if(s < strSize)
	    stop("StringTable: Unexpected EOF");
	init(strData);
	delete[]strData;
    }
    StringTable(const set<string> &strings) {
	/* Construct string table from given strings.
	 */
	char *p;
	set<string>::const_iterator it;
	size_t s;

	// count required size for data
	for(length = sizeof(unsigned), it = strings.begin(); it != strings.end(); ++it) {
	    size_t l = (*it).size();

	    if(l > (unsigned) 0xFFFFFFFF)
		stop("StringTable: String too long");
	    if(l > 8) {
		length += l + 1;
		if(length > (unsigned) 0xFFFFFFFF)
		    stop("StringTable: Symbol table too long");
	    }
	}
	data = new char[length];
	*(unsigned*)data = length;
	// populate data and directory
	for(p = data + sizeof(unsigned), it = strings.begin(); it != strings.end(); ++it) {
	    const string &str = *it;
	    size_t l = str.size();
	    if(l > 8) {
		directory.insert(make_pair(str, p - data));
		memcpy(p, str.c_str(), l);
		p[l] = 0;
		p += l + 1;
	    }
	}
    }
    ~StringTable() {
	delete[] data;
    }
    /* Returns encoding for given string based on this string table.
       Error if string length is greater than 8 but string is not in
       the string table--returns 0.
    */
    int64_t encode(const string &str) {
	int64_t r;

	if(str.size() <= 8) {
	    // encoded directly
	    ((char*)&r)[7] = 0;
	    strncpy((char*)&r, str.c_str(), 8);
	    return r;
	} else {
	    // represented as index into table
	    map<string,unsigned>::const_iterator it = directory.find(str);
	    if(it == directory.end())
		stop("StringTable::encode: String now found in string table");
	    ((unsigned*)&r)[0] = 0;
	    ((unsigned*)&r)[1] = (*it).second;
	    return r;
	}
    }
    /* Returns string represented by x based on this string table.
       Error if x references an invalid position in the table--returns
       the empty string.
    */
    string decode(int64_t x) const {
	if(*(unsigned*)&x == 0) {
	    // represented as index into table
	    unsigned &p = ((unsigned*)&x)[1];
	    if(p >= length)
		stop("StringTable::decode: Invalid string table lookup");
	    return string(data + p);
	} else {
	    // encoded directly
	    char *p = (char*)&x;
	    int i;

	    for(i = 0; i < 8 && p[i]; ++i);
	    return string(p, i);
	}
    }
    void write(ostream &os) {
	os.write(data, length);
    }
};


void
obj_copy(
    string_t const &    src,    // Name of source file.
    string_t const &    dst,    // Name of destination file.
    str_hash_t const &  redefs  // List of redefinititions.
) {

    set< string > strings; // set of all occurring symbols, appropriately prefixed
    streampos fileSize;
    size_t strTabStart;
    unsigned symTabStart;
    unsigned symNEntries;
    int i;


    string const error_reading = "Error reading \"" + src + "\" file: ";

    rstream_t in( src );

    in.seekg( 0, ios::end );
    fileSize = in.tellg();

    in.seekg( 8 );
    in >> symTabStart >> symNEntries;
    strTabStart = symTabStart + 18 * size_t( symNEntries );
    in.seekg( strTabStart );
    if ( in.eof() ) {
        stop( error_reading + "Unexpected end of file" );
    }
    StringTable stringTableOld( in ); // Read original string table.

    if ( in.tellg() != fileSize ) {
        stop( error_reading + "Unexpected data after string table" );
    }

    // compute set of occurring strings with prefix added
    for ( i = 0; i < symNEntries; ++ i ) {

	symbol_t e;

	in.seekg( symTabStart + i * 18 );
	if ( in.eof() ) {
            stop("hideSymbols: Unexpected EOF");
        }
	in >> e;
	if ( in.fail() ) {
            stop("hideSymbols: File read error");
        }
	if ( e.nAux ) {
            i += e.nAux;
        }
	const string & s = stringTableOld.decode( e.name );
	// if symbol is extern and found in <hide>, prefix and insert into strings,
	// otherwise, just insert into strings without prefix
        string_t name = find( redefs, s );
	strings.insert( name != "" && e.storage_class == 2 ? name : s );
    }

    ofstream out( dst.c_str(), ios::trunc | ios::out | ios::binary );
    if ( ! out.is_open() ) {
        stop("hideSymbols: Error opening output file");
    }

    // make new string table from string set
    StringTable stringTableNew = StringTable( strings );

    // copy input file to output file up to just before the symbol table
    in.seekg( 0 );
    char * buf = new char[ symTabStart ];
    in.read( buf, symTabStart );
    out.write( buf, symTabStart );
    delete [] buf;

    // copy input symbol table to output symbol table with name translation
    for ( i = 0; i < symNEntries; ++ i ) {
	symbol_t e;

	in.seekg( symTabStart + i * 18 );
	if ( in.eof() ) {
            stop("hideSymbols: Unexpected EOF");
        }
	in >> e;
	if ( in.fail() ) {
            stop("hideSymbols: File read error");
        }
	const string & s = stringTableOld.decode( e.name );
	out.seekp( symTabStart + i * 18 );
        string_t name = find( redefs, s );
	e.name = stringTableNew.encode( ( e.storage_class == 2 && name != "" ) ? name : s );
	out.write( (char*) & e, 18 );
	if ( out.fail() ) {
            stop( "hideSymbols: File write error" );
        }
	if ( e.nAux ) {
	    // copy auxiliary symbol table entries
	    int nAux = e.nAux;
	    for (int j = 1; j <= nAux; ++j ) {
		in >> e;
		out.seekp( symTabStart + ( i + j ) * 18 );
		out.write( (char*) & e, 18 );
	    }
	    i += nAux;
	}
    }
    // output string table
    stringTableNew.write( out );
}


void
split( string_t const & str, char ch, string_t & head, string_t & tail ) {
    string_t::size_type pos = str.find( ch );
    if ( pos == string_t::npos ) {
        head = str;
        tail = "";
    } else {
        head = str.substr( 0, pos );
        tail = str.substr( pos + 1 );
    }; // if
} // split


void help() {
    std::cout
        << "NAME\n"
        << "    objcopy -- copy and translate object files\n"
        << "\n"
        << "SYNOPSIS\n"
        << "    objcopy options... source destination\n"
        << "\n"
        << "OPTIONS\n"
        << "    --help  Print this help and exit.\n"
        << "    --redefine-sym old=new\n"
        << "            Rename \"old\" symbol in source object file to \"new\" symbol in\n"
        << "            destination object file.\n"
        << "    --redefine-syms sym_file\n"
        << "            For each pair \"old new\" in sym_file rename \"old\" symbol in \n"
        << "            source object file to \"new\" symbol in destination object file.\n"
        << "\n"
        << "ARGUMENTS\n"
        << "    source  The name of source object file.\n"
        << "    destination\n"
        << "            The name of destination object file.\n"
        << "\n"
        << "DESCRIPTION\n"
        << "    This program implements a minor bit of Linux* OS's objcopy utility on Windows* OS.\n"
        << "    It can copy object files and edit its symbol table.\n"
        << "\n"
        << "EXAMPLES\n"
        << "    \n"
        << "        > objcopy --redefine-sym fastcpy=__xxx_fastcpy a.obj b.obj\n"
        << "\n";
} // help


int
main( int argc, char const * argv[] ) {

    strings_t   args( argc - 1 );
    str_hash_t  redefs;
    strings_t   files;

    std::copy( argv + 1, argv + argc, args.begin() );

    while ( args.size() > 0 ) {
        string_t arg = shift( args );
        if ( arg.substr( 0, 2 ) == "--" ) {
            // An option.
            if ( 0  ) {
            } else if ( arg == "--help" ) {
                help();
                return 0;
            } else if ( arg == "--redefine-sym" ) {
                if ( args.size() == 0 ) {
                    die( "\"" + arg + "\" option requires an argument" );
                }; // if
                // read list of symbol pairs "old new" from command line.
                string_t redef = shift( args );
                string_t old_sym;
                string_t new_sym;
                split( redef, '=', old_sym, new_sym );
                if ( old_sym.length() == 0 || new_sym.length() == 0 ) {
                    die( "Illegal redefinition: \"" + redef + "\"; neither old symbol nor new symbol may be empty" );
                }; // if
                redefs.insert( str_pair_t( old_sym, new_sym ) );
            } else if ( arg == "--redefine-syms" ) {
                if ( args.size() == 0 ) {
                    die( "\"" + arg + "\" option requires an argument" );
                }; // if
                // read list of symbol pairs "old new" from file.
                string_t fname = shift( args );
                string_t redef;
		ifstream ifs( fname.c_str() );
		while ( ifs.good() ) {
                    getline( ifs, redef );// get pair of old/new symbols separated by space
                    string_t old_sym;
                    string_t new_sym;
                    // AC: gcount() does not work here (always return 0), so comment it
                    //if ( ifs.gcount() ) { // skip empty lines
                    split( redef, ' ', old_sym, new_sym );
                    if ( old_sym.length() == 0 || new_sym.length() == 0 ) {
                        break;  // end of file reached (last empty line)
                        //die( "Illegal redefinition: \"" + redef + "\"; neither old symbol nor new symbol may be empty" );
                    }; // if
                    redefs.insert( str_pair_t( old_sym, new_sym ) );
                    //}
		}
            } else {
                die( "Illegal option: \"" + arg + "\"" );
            }; // if
        } else {
            // Not an option, a file name.
            if ( files.size() >= 2 ) {
                die( "Too many files specified; two files required (use --help option for help)" );
            }; // if
            files.push_back( arg );
        }; // if
    }; // while
    if ( files.size() < 2 ) {
        die( "Not enough files specified; two files required (use --help option for help)" );
    }; // if

    obj_copy( files[ 0 ], files[ 1 ], redefs );

    return 0;

} // main


// end of file //
