Author: arty Date: Sun Apr 29 08:05:11 2007 New Revision: 26574
URL: http://svn.reactos.org/svn/reactos?rev=26574&view=rev Log: Start of a simple ELF PE augmenter.
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/ branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-dlltool.in (with props) branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-gcc.in branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-ld.in branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-windres.in branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr.cpp branches/powerpc/reactos/tools/ppc-build/elfpe/fork_execvp.h (with props) branches/powerpc/reactos/tools/ppc-build/elfpe/fork_unix.cpp (with props) branches/powerpc/reactos/tools/ppc-build/elfpe/fork_win32.cpp (with props) branches/powerpc/reactos/tools/ppc-build/elfpe/header.cpp branches/powerpc/reactos/tools/ppc-build/elfpe/header.h branches/powerpc/reactos/tools/ppc-build/elfpe/makefile branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.cpp branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.h branches/powerpc/reactos/tools/ppc-build/elfpe/pedef.h branches/powerpc/reactos/tools/ppc-build/elfpe/util.cpp branches/powerpc/reactos/tools/ppc-build/elfpe/util.h
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-dlltool.in URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-dlltool.in (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-dlltool.in Sun Apr 29 08:05:11 2007 @@ -1,0 +1,7 @@ +#!/bin/sh + +DIR=@PREFIX@ +BPREFIX=@BPREFIX@ +TARGET=@TARGET@ + +${BPREFIX}dlltool -S $DIR/bin/${TARGET}as -L $DIR/bin/${TARGET}ld $*
Propchange: branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-dlltool.in ------------------------------------------------------------------------------ svn:executable = *
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-gcc.in URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-gcc.in (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-gcc.in Sun Apr 29 08:05:11 2007 @@ -1,0 +1,58 @@ +#!/bin/sh + +DIR=@PREFIX@ +CPREFIX=@CPREFIX@ +TARGET=@TARGET@ + +if [ "x$*" = "x-v" ] ; then + exec ${CPREFIX}gcc -v +fi + +includes="-isystem $DIR/lib/mingw-crt-headers -isystem $DIR/lib/gcc-core-headers" + +argstr="" +for arg in $* ; do + if [ x"$arg" = x-mingw ] ; then + argstr="$argstr -isystem $DIR/lib/windows-headers" + else + argstr="$argstr $arg" + fi +done + +TEMP=`mktemp -d` +export TEMP +if [ ! -d $TEMP ] ; then + echo "Could not make temp dir $TEMP" + exit 1 +fi +TMP=$TEMP + +`dirname $0`/${TARGET}driver-gcc \ + -nostdinc \ + -D__cdecl__= \ + -D__stdcall__= \ + -D__fastcall__= \ + -D__declspec(x)= \ + -D__cdecl= \ + -D__stdcall= \ + -D__fastcall= \ + -Dcdecl= \ + -Dstdcall= \ + -Dfastcall= \ + -Ddllimport= \ + -Ddllexport= \ + -Du_short=unsigned\ short \ + -Du_long=unsigned\ long \ + -Du_int=unsigned\ int \ + -Du_char=unsigned\ char \ + -ldscript ${DIR}/lib/ldscript \ + -gcc-name ${CPREFIX}gcc \ + -link-stage-name ${DIR}/bin/${TARGET}ld \ + -mingw-lib-dir $DIR/lib \ + $includes \ + $argstr </dev/null + +RES=$? + +rm -rf $TEMP +exit $RES
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-ld.in URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-ld.in (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-ld.in Sun Apr 29 08:05:11 2007 @@ -1,0 +1,28 @@ +#!/bin/sh + +DIR=@PREFIX@ +BPREFIX=@BPREFIX@ +TARGET=@TARGET@ + +if [ "x$*" = x-v ] ; then + exec ${BPREFIX}ld -v +fi + +TEMP=`mktemp -d` +export TEMP +if [ ! -d $TEMP ] ; then + echo "Could not make temp dir $TEMP" + exit 1 +fi +TMP=$TEMP + +`dirname $0`/${TARGET}driver-ld \ + -ldscript ${DIR}/lib/ldscript \ + -mingw-lib-dir ${DIR}/lib \ + -link-stage-name ${BPREFIX}ld \ + $* + +RES=$? + +rm -rf $TEMP +exit $RES
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-windres.in URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-windres.in (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr-windres.in Sun Apr 29 08:05:11 2007 @@ -1,0 +1,7 @@ +#!/bin/sh + +DIR=@PREFIX@ +BPREFIX=@BPREFIX@ +TARGET=@TARGET@ + +exec ${BPREFIX}windres -F elf32-powerpc $*
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr.cpp URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr.cpp (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/compdvr.cpp Sun Apr 29 08:05:11 2007 @@ -1,0 +1,336 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <list> +#include <string> +#include <vector> +#include <sstream> +#include <algorithm> +#include "objectfile.h" +#include "header.h" +#include "fork_execvp.h" + +#define TYPE_PEHEADER (SHT_LOOS + 1) + +/* tool for transforming gcc -### output and using it to drive the compiler + * elements ourselves. Most importantly, we need to know what file gcc asks + * the linker to input and output, and add an intermediate stage with alink. + */ + +typedef enum { empty, found_q, found_bs } break_t; + +template <class T> +T break_arguments( const std::string &line ) { + break_t state = empty; + T args; + std::string arg; + + for( size_t i = 0; i < line.size(); i++ ) { + switch( state ) { + case empty: + if( line[i] == '"' ) { + state = found_q; + } + break; + + case found_q: + if( line[i] == '\' ) state = found_bs; + else if( line[i] == '"' ) { + state = empty; + args.push_back(arg); + arg = ""; + } else arg += line[i]; + break; + + case found_bs: + state = found_q; + arg += line[i]; + break; + } + } + + return args; +} + +template <class T> +std::vector<char *> get_arg_ptrs +( const T &arg_strings ) { + std::vector<char *> arg_out; + for( size_t i = 0; i < arg_strings.size(); i++ ) + arg_out.push_back( (char *)arg_strings[i].c_str() ); + arg_out.push_back(0); + return arg_out; +} + +int execute_command( bool verbose, const std::vectorstd::string &args ) { + std::string error; + std::vector<char *> args_ptrs; + const char *tag = "executable"; + + if( verbose ) { + fprintf( stderr, "<command>\n" ); + for( size_t i = 0; i < args.size(); i++ ) { + fprintf( stderr, "<%s>%s</%s>\n", tag, args[i].c_str(), tag ); + tag = "argument"; + } + } + + Process p = fork_execvp( args ); + + while( p && p->ProcessStarted() && !p->EndOfStream() ) + fprintf( stderr, "%s", p->ReadStdError().c_str() ); + + if( verbose ) { + fprintf( stderr, "<status>%d</status>\n", p->GetStatus() ); + fprintf( stderr, "</command>\n" ); + } + + return p ? p->GetStatus() : -1; +} + +std::string make_tmp_name() { + int fd; + std::string name; + + while( true ) { + name = tmpnam(NULL); + name += ".obj"; + if( (fd = creat( name.c_str(), 0644 )) != -1 ) { + close(fd); + return name; + } + } +} + +void recognize_arg( std::vectorstd::string &args, + std::string &result, + size_t &i, + const std::string &argname, + const std::string &short_argname = "" ) { + if( (short_argname.size() && (args[i] == short_argname)) || + (args[i] == argname) ) { + result = args[i+1]; + args.erase(args.begin()+i); + args.erase(args.begin()+i--); + } else if( args[i].substr(0,argname.size()+1) == argname + "=" ) { + result = args[i].substr(argname.size()+1); + args.erase(args.begin()+i--); + } +} + +int run_ld( bool verbose, bool nostdlib, bool nostartfiles, bool is_dll, + bool make_map, + const std::string &lib_dir, + const std::string &ldscript, + const std::vectorstd::string &arg_vect ) { + bool use_libgcc = false; + std::vectorstd::string args = arg_vect; + std::string real_output, + entry_point = "0x1000", + image_base = "0x400000", subsystem = "windows", + make_dll, + file_align = "0x1000", + section_align = "0x1000", base_file; + std::vectorstd::string::iterator i = + std::find(args.begin(),args.end(),"-lgcc"); + + if( i != args.end() ) { + args.erase( i ); + use_libgcc = true; + } + + if( !nostartfiles ) { + if( make_dll.size() ) + args.push_back(lib_dir + "/dllcrt2.o"); + else + args.push_back(lib_dir + "/crt2.o"); + } + + if( !nostdlib ) { + args.push_back(std::string("-L") + lib_dir); + args.push_back("-lkernel32"); + args.push_back("-lmsvcrt"); + args.push_back("-lcrtdll"); + args.push_back("-lmingw32"); + } + if( use_libgcc ) + args.push_back(lib_dir + "/libgcc.a"); + + if( verbose ) + args.insert(args.begin()+1,"-v"); + + args.insert(args.begin()+1,"-T"); + args.insert(args.begin()+2,ldscript); + args.insert(args.begin()+1,"-r"); + args.insert(args.begin()+1,"--start-group"); + args.push_back("--end-group"); + + for( size_t i = 0; i < args.size(); i++ ) { + if( args[i] == "-o" && i < args.size()-1 ) { + real_output = args[++i]; + } else if( args[i].substr(0,4) == "-mdll" ) { + args.erase(args.begin()+i--); + make_dll = "-dll"; + } + + recognize_arg( args, entry_point, i, "--entry", "-e" ); + recognize_arg( args, image_base, i, "--image-base" ); + recognize_arg( args, subsystem, i, "--subsystem" ); + recognize_arg( args, file_align, i, "--file-alignment" ); + recognize_arg( args, section_align, i, "--section-alignment" ); + recognize_arg( args, base_file, i, "--base-file" ); + } + + if( execute_command( verbose, args ) ) + return 1; + + if( base_file.size() ) { + FILE *f = fopen(base_file.c_str(), "wb"); + if( !f ) { + fprintf(stderr, "<error>\n"); + perror(base_file.c_str()); + fprintf(stderr, "</error>\n"); + return 1; + } + fclose(f); + } + + /* Ok fixup the elf object file */ + ElfObjectFile eof(real_output); + + if(!eof) return 1; + + ElfPeHeader header + (strtoul(image_base.c_str(), 0, 0), + strtoul(section_align.c_str(), 0, 0), + strtoul(file_align.c_str(), 0, 0), + 0x10000, + 0x100000, + 0x10000, + 0x100000, + is_dll, + atoi(subsystem.c_str()), + &eof); + + eof.addSection(".peheader", header.getData(), TYPE_PEHEADER); + + return 0; +} + +int main( int argc, char **argv ) { + bool verbose = false, ld_mode = false, nostdlib = false, + nostartfiles = false, is_dll = false, make_map = false; + int err_fd[2], read_len, child_pid_gcc, child_pid_command, status = 0; + std::string gcc_name, gcc_hash_output, gcc_line, linker_name = "ld", + mingw_lib_dir, ldscript; + std::vectorstd::string gcc_args_str, + subcmd_args; + std::vector<char *> arguments_for_gcc; + char buf[1024]; + + for( int i = 1; i < argc; i++ ) { + if( std::string("-gcc-name") == argv[i] && i < argc-1 ) { + gcc_name = argv[++i]; + } else if( std::string("-ldscript") == argv[i] && i < argc-1 ) { + ldscript = argv[++i]; + } else if( std::string("-link-stage-name") == argv[i] && i < argc-1 ) { + linker_name = argv[++i]; + } else if( std::string("-mingw-lib-dir") == argv[i] && i < argc-1 ) { + mingw_lib_dir = argv[++i]; + } else if( std::string("-v") == argv[i] ) { + verbose = true; + } else if( std::string("-pipe") == argv[i] ) { + /* ignore */ + } else if( std::string("-T") == argv[i] ) { + /* ignore */ + i++; + } else if( std::string("-nostdlib") == argv[i] ) { + nostdlib = true; + } else if( std::string("-nostartfiles") == argv[i] ) { + nostartfiles = true; + } else if( std::string("-shared") == argv[i] ) { + is_dll = true; + } else if( std::string("-map") == argv[i] ) { + make_map = true; + } else { + gcc_args_str.push_back(argv[i]); + } + } + + /* We never use the system start files or standard libs */ + gcc_args_str.insert(gcc_args_str.begin()+1,"-nostdlib"); + gcc_args_str.insert(gcc_args_str.begin()+1,"-nostartfiles"); + + if( std::string(argv[0]).find("ld") != std::string::npos ) { + gcc_args_str.insert + ( gcc_args_str.begin(), linker_name ); + return run_ld + ( verbose, nostdlib, nostartfiles, is_dll, make_map, mingw_lib_dir, + ldscript, gcc_args_str ); + } + if( verbose ) fprintf( stderr, "<compiler-driver>\n" ); + + // Stack on driver name and dump commands flag + gcc_args_str.insert(gcc_args_str.begin(),std::string("-###")); + gcc_args_str.insert(gcc_args_str.begin(),gcc_name); + + /* Redirect stderr to our pipe */ + if( verbose ) { + const char *tag = "executable"; + fprintf( stderr, "<gcc>\n" ); + for( size_t i = 0; i < gcc_args_str.size(); i++ ) { + fprintf( stderr, " <%s>%s</%s>\n", + tag, gcc_args_str[i].c_str(), + tag ); + tag = "arg"; + } + fprintf( stderr, "</gcc>\n" ); + } + + Process p = fork_execvp( gcc_args_str ); + + while( p && p->ProcessStarted() && !p->EndOfStream() ) + gcc_hash_output += p->ReadStdError(); + + std::istringstream iss( gcc_hash_output ); + + if( p->GetStatus() ) goto final; + + while( std::getline( iss, gcc_line, '\n' ) ) { + // command line + if( gcc_line.size() > 2 && gcc_line[0] == ' ' ) { + subcmd_args = + break_arguments<std::vectorstd::string >( gcc_line ); + + if( subcmd_args.size() < 1 ) continue; + + if( subcmd_args[0].find("collect2") != std::string::npos || + subcmd_args[0].find("ld") != std::string::npos ) { + if( run_ld( verbose, nostdlib, nostartfiles, is_dll, make_map, + mingw_lib_dir, ldscript, subcmd_args ) ) + goto final; + else + continue; + } + + if( verbose ) + subcmd_args.insert(subcmd_args.begin()+1,"-v"); + + if( execute_command + ( verbose, subcmd_args ) ) + goto final; + } else if( verbose ) + fprintf( stderr, "<error>%s</error>\n", gcc_line.c_str() ); + } + goto theend; + + final: + status = 1; + theend: + if( verbose ) { + fprintf( stderr, "<status>%d</status>\n", status ); + fprintf( stderr, "</compiler-driver>\n" ); + } + return status; +}
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/fork_execvp.h URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/fork_execvp.h (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/fork_execvp.h Sun Apr 29 08:05:11 2007 @@ -1,0 +1,28 @@ +#ifndef FORK_EXECVP_H +#define FORK_EXECVP_H + +#include <string> +#include <vector> + +class ProcessHolder { +public: + virtual ~ProcessHolder() { } + virtual std::string ReadStdError() = 0; + virtual bool ProcessStarted() const = 0; + virtual bool EndOfStream() const = 0; + virtual int GetStatus() const = 0; +}; + +class Process { +public: + Process( ProcessHolder *h ) : holder(h) { } + ~Process() { delete holder; } + ProcessHolder *operator -> () const { return holder; } + operator ProcessHolder *() const { return (holder && holder->ProcessStarted()) ? holder : NULL; } +private: + ProcessHolder *holder; +}; + +ProcessHolder *fork_execvp( const std::vectorstd::string &args ); + +#endif//FORK_EXECVP_H
Propchange: branches/powerpc/reactos/tools/ppc-build/elfpe/fork_execvp.h ------------------------------------------------------------------------------ svn:executable = *
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/fork_unix.cpp URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/fork_unix.cpp (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/fork_unix.cpp Sun Apr 29 08:05:11 2007 @@ -1,0 +1,66 @@ +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include "fork_execvp.h" + +class UnixProcessHolder : public ProcessHolder { +public: + UnixProcessHolder( const std::vectorstd::string &args ) + : read_fd(-1), child_pid(-1), at_end(false), status(-1) { + std::vector<char *> argvect(args.size()+1); + for( size_t i = 0; i < args.size(); i++ ) + argvect[i] = (char *)args[i].c_str(); + argvect[args.size()] = 0; + + int err_fd[2]; + + if( pipe( err_fd ) == -1 ) + return; + + fflush(stdout); + + child_pid = fork(); + + if( !child_pid ) { + dup2( err_fd[1], 2 ); + close( err_fd[0] ); + close( err_fd[1] ); + + execvp(args[0].c_str(), &argvect[0] ); + exit(1); + } else { + close( err_fd[1] ); + read_fd = err_fd[0]; + } + } + + ~UnixProcessHolder() { + close( read_fd ); + } + + std::string ReadStdError() { + char buf[1024]; + int rl = read( read_fd, buf, sizeof(buf) ); + if( rl < 1 ) { + at_end = true; + waitpid( child_pid, &status, 0 ); + return ""; + } + return std::string(buf, rl); + } + + bool ProcessStarted() const { return child_pid != -1; } + bool EndOfStream() const { return at_end; } + int GetStatus() const { return status; } + +private: + bool at_end; + int read_fd; + int child_pid; + int status; +}; + +ProcessHolder *fork_execvp( const std::vectorstd::string &args ) { + return new UnixProcessHolder( args ); +}
Propchange: branches/powerpc/reactos/tools/ppc-build/elfpe/fork_unix.cpp ------------------------------------------------------------------------------ svn:executable = *
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/fork_win32.cpp URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/fork_win32.cpp (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/fork_win32.cpp Sun Apr 29 08:05:11 2007 @@ -1,0 +1,109 @@ +#include <windows.h> +#include "fork_execvp.h" + +class Win32ProcessHolder : public ProcessHolder { +public: + Win32ProcessHolder( const std::string &args ) + : ErrorRead(INVALID_HANDLE_VALUE), + ProcessHandle(INVALID_HANDLE_VALUE), + StreamEnded(false) { + HANDLE ErrorWrite = NULL, ErrorReadTemp = NULL; + PROCESS_INFORMATION pi = { }; + SECURITY_ATTRIBUTES sa = { }; + STARTUPINFO si = { }; + + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + if(!CreatePipe(&ErrorReadTemp, &ErrorWrite, &sa, 0)) return; + + if(!DuplicateHandle(GetCurrentProcess(), ErrorReadTemp, + GetCurrentProcess(), &ErrorRead, + 0, FALSE, + DUPLICATE_SAME_ACCESS)) return; + + CloseHandle(ErrorReadTemp); + + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = ErrorWrite; + + if(!CreateProcess(NULL, (char *)args.c_str(), NULL, NULL, TRUE, + 0, NULL, NULL, &si, &pi)) return; + + ProcessHandle = pi.hProcess; + + CloseHandle(ErrorWrite); + } + + ~Win32ProcessHolder() { + CloseHandle( ErrorRead ); + CloseHandle( ProcessHandle ); + } + + std::string ReadStdError() { + char Buf[1024]; + DWORD ReadBytes; + + if( StreamEnded ) return ""; + + StreamEnded = + !ReadFile(ErrorRead, Buf, sizeof(Buf), &ReadBytes, NULL) || + !ReadBytes; + + if( !StreamEnded ) return std::string(Buf, ReadBytes); + else return ""; + } + + bool EndOfStream() const { + return StreamEnded; + } + + bool ProcessStarted() const { + return ProcessHandle != INVALID_HANDLE_VALUE; + } + + int GetStatus() const { + DWORD Status = 1; + if( ProcessHandle != INVALID_HANDLE_VALUE ) { + WaitForSingleObject( ProcessHandle, INFINITE ); + GetExitCodeProcess( ProcessHandle, &Status ); + } + return Status; + } + +private: + bool StreamEnded; + HANDLE ErrorRead, ProcessHandle; +}; + +std::string quote_escape( const std::string &_str ) { + std::string str = _str; + size_t q; + + q = str.find('"'); + while( q != std::string::npos ) { + str.replace(q, 1, "\""); + q = str.find('"'); + } + + return std::string(""") + str + """; +} + +ProcessHolder *fork_execvp( const std::vectorstd::string &args ) { + std::string argstring; + ProcessHolder *holder; + + for( std::vectorstd::string::const_iterator i = args.begin(); + i != args.end(); + i++ ) { + if( i != args.begin() ) + argstring += " "; + argstring += quote_escape(*i); + } + + return new Win32ProcessHolder( argstring ); +}
Propchange: branches/powerpc/reactos/tools/ppc-build/elfpe/fork_win32.cpp ------------------------------------------------------------------------------ svn:executable = *
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/header.cpp URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/header.cpp (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/header.cpp Sun Apr 29 08:05:11 2007 @@ -1,0 +1,176 @@ +#include <time.h> +#include "util.h" +#include "header.h" + +ElfPeHeader::ElfPeHeader + (uint32_t imagebase, + uint32_t filealign, + uint32_t sectionalign, + uint32_t stackreserve, + uint32_t stackcommit, + uint32_t heapreserve, + uint32_t heapcommit, + int subsysid, + bool dll, + ElfObjectFile *eof) : + imagebase(imagebase), + sectionalign(sectionalign), + stackreserve(stackreserve), + stackcommit(stackcommit), + heapreserve(heapreserve), + heapcommit(heapcommit), + subsysid(subsysid), + eof(eof) +{ + data.resize(computeSize()); + createHeaderSection(); +} + +int ElfPeHeader::computeSize() const +{ + return sectionalign; /* We'll compute it for real later */ +} + +void ElfPeHeader::createHeaderSection() +{ + data[0] = 'M'; data[1] = 'Z'; + uint8_t *dataptr = &data[0x3c]; + uint32_t coffHeaderSize, optHeaderSizeMember; + le32write_postinc(dataptr, 0x80); + dataptr = &data[0x80]; + le32write_postinc(dataptr, 0x4550); + le16write_postinc(dataptr, getPeArch()); + le16write_postinc(dataptr, getNumSections()); + le32write_postinc(dataptr, time(NULL)); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, 0); + optHeaderSizeMember = dataptr - &data[0]; + le16write_postinc(dataptr, 0); // Will fixup sizeof opt header + le16write_postinc(dataptr, getExeFlags()); + coffHeaderSize = dataptr - &data[0]; + le16write_postinc(dataptr, 0); + le16write_postinc(dataptr, 0x100); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, getEntryPoint()); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, imagebase); + le32write_postinc(dataptr, sectionalign); + le32write_postinc(dataptr, filealign); + le16write_postinc(dataptr, 4); + le16write_postinc(dataptr, 0); + le16write_postinc(dataptr, 1); + le16write_postinc(dataptr, 0); + le16write_postinc(dataptr, 4); + le16write_postinc(dataptr, 0); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, getImageSize()); + le32write_postinc(dataptr, computeSize()); + le32write_postinc(dataptr, 0); // No checksum yet + le16write_postinc(dataptr, subsysid); + le16write_postinc(dataptr, getDllFlags()); + le32write_postinc(dataptr, stackreserve); + le32write_postinc(dataptr, stackcommit); + le32write_postinc(dataptr, heapreserve); + le32write_postinc(dataptr, heapcommit); + le32write_postinc(dataptr, 0); + le32write_postinc(dataptr, 10); // # Directories + // "Directories" + le32pwrite_postinc(dataptr, getExportInfo()); + le32pwrite_postinc(dataptr, getImportInfo()); + le32pwrite_postinc(dataptr, getResourceInfo()); + le32pwrite_postinc(dataptr, getExceptionInfo()); + le32pwrite_postinc(dataptr, getSecurityInfo()); + le32pwrite_postinc(dataptr, getRelocInfo()); + le32pwrite_postinc(dataptr, getDebugInfo()); + le32pwrite_postinc(dataptr, getDescrInfo()); + le32pwrite_postinc(dataptr, getMachInfo()); + le32pwrite_postinc(dataptr, getTlsInfo()); + // Fixup size of optional header + le16write + (&data[0] + optHeaderSizeMember, + (dataptr - &data[0]) - coffHeaderSize); +} + +const std::vector<uint8_t> &ElfPeHeader::getData() const { return data; } + +uint32_t ElfPeHeader::getImageSize() const +{ + uint32_t start = 0; + uint32_t limit = 0; + for(int i = 0; i < eof->getNumSections(); i++) { + { + const ElfObjectFile::Section § = eof->getSection(i); + limit = roundup(start + sect.logicalSize(), sectionalign); + } + start = limit; + } + + return limit; +} + +uint16_t ElfPeHeader::getPeArch() const +{ + return IMAGE_FILE_MACHINE_POWERPCBE; /* for now */ +} + +u32pair_t getNamedSectionInfo(ElfObjectFile *eof, const std::string &name) +{ + const ElfObjectFile::Section *sect = eof->getNamedSection(name); + if(sect) + return std::make_pair(sect->getStartRva(), sect->logicalSize()); + else + return std::make_pair(0,0); +} + +u32pair_t ElfPeHeader::getExportInfo() const +{ + return getNamedSectionInfo(eof, ".edata"); +} + +u32pair_t ElfPeHeader::getImportInfo() const +{ + return getNamedSectionInfo(eof, ".idata"); +} + +u32pair_t ElfPeHeader::getResourceInfo() const +{ + return getNamedSectionInfo(eof, ".rsrc"); +} + +u32pair_t ElfPeHeader::getExceptionInfo() const +{ + return std::make_pair(0,0); +} + +u32pair_t ElfPeHeader::getSecurityInfo() const +{ + return std::make_pair(0,0); +} + +u32pair_t ElfPeHeader::getRelocInfo() const +{ + return std::make_pair(0,0); +} + +u32pair_t ElfPeHeader::getDebugInfo() const +{ + return std::make_pair(0,0); +} + +u32pair_t ElfPeHeader::getDescrInfo() const +{ + return std::make_pair(0,0); +} + +u32pair_t ElfPeHeader::getTlsInfo() const +{ + return std::make_pair(0,0); +} + +u32pair_t ElfPeHeader::getMachInfo() const +{ + return std::make_pair(0,0); +}
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/header.h URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/header.h (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/header.h Sun Apr 29 08:05:11 2007 @@ -1,0 +1,58 @@ +#ifndef COMPDVR_ELFHEADER_H +#define COMPDVR_ELFHEADER_H + +#include <vector> +#include <utility> +#include "pedef.h" +#include "util.h" +#include "objectfile.h" + +class ElfPeHeader { +public: + ElfPeHeader + (uint32_t imagebase, + uint32_t imagealign, + uint32_t filealign, + uint32_t stackreserve, + uint32_t stackcommit, + uint32_t heapreserve, + uint32_t heapcommit, + int subsysid, + bool dll, + ElfObjectFile *eof); + const ElfObjectFile::secdata_t &getData() const; + +private: + void createHeaderSection(); + int getNumSections() const { return eof->getNumSections(); } + int computeSize() const; + int getExeFlags() const { return 0; } + int getDllFlags() const { return dll ? IMAGE_FILE_DLL : 0; } + u32pair_t getExportInfo() const; + u32pair_t getImportInfo() const; + u32pair_t getResourceInfo() const; + u32pair_t getExceptionInfo() const; + u32pair_t getSecurityInfo() const; + u32pair_t getRelocInfo() const; + u32pair_t getDebugInfo() const; + u32pair_t getDescrInfo() const; + u32pair_t getMachInfo() const; + u32pair_t getTlsInfo() const; + uint32_t getEntryPoint() const { return eof->getEntryPoint(); } + uint32_t getImageSize() const; + uint16_t getPeArch() const; + uint32_t saToRva(int section, uint32_t offset) const; + uint32_t vaToRva(uint32_t source_addr) const; + + uint32_t + imagebase, filealign, sectionalign, + stackreserve, stackcommit, + heapreserve, heapcommit; + bool dll; + int subsysid; + ElfObjectFile *eof; + std::vector<uint8_t> data; + static const char *mzHeader; +}; + +#endif//COMPDVR_ELFHEADER_H
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/makefile URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/makefile (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/makefile Sun Apr 29 08:05:11 2007 @@ -1,0 +1,7 @@ +all: compdvr + +%.o: %.cpp + g++ -g -o $@ $< + +compdvr: compdvr.cpp fork_unix.cpp header.cpp objectfile.cpp util.cpp + g++ -g -o $@ $^ -lelf
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.cpp URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.cpp (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.cpp Sun Apr 29 08:05:11 2007 @@ -1,0 +1,83 @@ +#include <libelf/libelf.h> +#include <fcntl.h> +#include "objectfile.h" + +ElfObjectFile::ElfObjectFile(const std::string &filename) : fd(-1) +{ + Elf_Scn *s = 0; + Elf32_Ehdr *ehdr; + fd = open(filename.c_str(), O_RDWR, 0); + if(fd >= 0) { + if(elf_version(EV_CURRENT) == EV_NONE) { + // Old version + return; + } + elfHeader = elf_begin(fd, ELF_C_RDWR, (Elf*)0); + if(elf_kind(elfHeader) != ELF_K_ELF) { + // Didn't get an elf object file + return; + } + ehdr = elf32_getehdr(elfHeader); + shnum = ehdr->e_shnum; + phnum = ehdr->e_phnum; + shstrndx = ehdr->e_shstrndx; + for(size_t i = 0; i < shnum; i++) + { + s = elf_nextscn(elfHeader, s); + if(!s) break; + sections.push_back(new Section(*this, s)); + fprintf(stderr, "Got section %04d %s\n", i, sections[i]->getName().c_str()); + } + } +} + +ElfObjectFile::~ElfObjectFile() +{ + if(elfHeader) elf_end(elfHeader); + if(fd >= 0) close(fd); +} + +uint32_t ElfObjectFile::getEntryPoint() const +{ + Elf32_Ehdr *elf32ehdr = elf32_getehdr(elfHeader); + return elf32ehdr->e_entry; +} + +void ElfObjectFile::addSection(const std::string &name, const secdata_t &data, int type) +{ + Elf_Scn *newsect = elf_newscn(elfHeader), + *strsect = elf_getscn(elfHeader, shstrndx); + Elf32_Shdr *shdr = elf32_getshdr(newsect); + /* Create data for the new section */ + Elf_Data *edata = elf_newdata(newsect), *strdata = elf_getdata(strsect, 0), + *newstrdata = elf_newdata(strsect); + edata->d_align = 0x1000; + edata->d_size = data.size(); + edata->d_off = 0; + edata->d_type = ELF_T_BYTE; + edata->d_version = EV_CURRENT; + edata->d_buf = malloc(edata->d_size); + memcpy(edata->d_buf, &data[0], edata->d_size); + /* Add the name of the new section to the string table */ + newstrdata->d_off = strdata->d_off + strdata->d_size; + newstrdata->d_size = name.size() + 1; + newstrdata->d_align = 1; + newstrdata->d_buf = (void *)name.c_str(); + /* Finish the section */ + shdr->sh_name = newstrdata->d_off; + shdr->sh_type = type; + shdr->sh_flags = 0; + shdr->sh_addr = 0; + shdr->sh_link = 0; + shdr->sh_info = 0; + + elf_update(elfHeader, ELF_C_WRITE); +} + +const ElfObjectFile::Section *ElfObjectFile::getNamedSection(const std::string &name) const +{ + for(size_t i = 0; i < sections.size(); i++) { + if(sections[i]->getName() == name) return sections[i]; + } + return NULL; +}
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.h URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.h (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/objectfile.h Sun Apr 29 08:05:11 2007 @@ -1,0 +1,66 @@ +#ifndef COMPDVR_ELFOBJECT_H +#define COMPDVR_ELFOBJECT_H + +#include <string> +#include <vector> +#include <libelf/libelf.h> + +class ElfObjectFile { +public: + typedef std::vector<uint8_t> secdata_t; + + class Section { + public: + Section(const Section &other) : + obj(other.obj), section(other.section) { } + Section(ElfObjectFile &obj, Elf_Scn *sechdr) : + obj(&obj), section(sechdr) { } + Section &operator = (const Section &other) { + obj = other.obj; + section = other.section; + } + operator bool () { return !!section; } + std::string getName() const { + Elf32_Shdr *e32shdr = elf32_getshdr(section); + return obj->getString(e32shdr->sh_name); + } + + int logicalSize() const { + Elf32_Shdr *e32shdr = elf32_getshdr(section); + return e32shdr->sh_size; + } + + uint32_t getStartRva() const { + Elf32_Shdr *e32shdr = elf32_getshdr(section); + return e32shdr->sh_addr; + } + + private: + const ElfObjectFile *obj; + Elf_Scn *section; + }; + + ElfObjectFile(const std::string &filename); + ~ElfObjectFile(); + + Elf *operator -> () { return fd >= 0 ? elfHeader : 0; } + bool operator ! () const { return fd == -1 ? true : false; } + int getNumSections() const { return sections.size(); } + uint32_t getEntryPoint() const; + std::string getString(int offset) const { + return elf_strptr(elfHeader, shstrndx, offset); + } + void addSection + (const std::string &name, const secdata_t &data, int type = SHT_PROGBITS); + const Section &getSection(int sect) const { return *sections[sect]; } + const Section *getNamedSection(const std::string &name) const; + +private: + int fd; + int shnum, phnum; + int shstrndx; + Elf *elfHeader; + std::vector<Section*> sections; +}; + +#endif//COMPDVR_ELFOBJECT_H
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/pedef.h URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/pedef.h (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/pedef.h Sun Apr 29 08:05:11 2007 @@ -1,0 +1,32 @@ +#ifndef COMPDVR_PEDEF_H +#define COMPDVR_PEDEF_H + +// Definitions from bernd.luevelsmeyer@iplan.heitec.net 's pe.txt reference +#define IMAGE_FILE_MACHINE_I386 (0x14c) +#define IMAGE_FILE_MACHINE_I486 (0x14d) +#define IMAGE_FILE_MACHINE_I586 (0x14e) +#define IMAGE_FILE_MACHINE_R3000BE (0x160) +#define IMAGE_FILE_MACHINE_R3000 (0x162) +#define IMAGE_FILE_MACHINE_R4000 (0x166) +#define IMAGE_FILE_MACHINE_R10000 (0x168) +#define IMAGE_FILE_MACHINE_ALPHA (0x184) +#define IMAGE_FILE_MACHINE_POWERPC (0x1F0) +// Recognize BE PowerPC by a coff BE style arch magic +#define IMAGE_FILE_MACHINE_POWERPCBE (0xF001) + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +#endif//COMPDVR_PEDEF_H
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/util.cpp URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/util.cpp (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/util.cpp Sun Apr 29 08:05:11 2007 @@ -1,0 +1,35 @@ +#include "util.h" + +uint32_t roundup(uint32_t value, int round) +{ + round--; + return (value + round) & ~round; +} + +void le16write(uint8_t *dataptr, uint16_t value) +{ + dataptr[0] = value; + dataptr[1] = value >> 8; +} + +void le16write_postinc(uint8_t *&dataptr, uint16_t value) +{ + le16write(dataptr, value); dataptr += 2; +} + +void le32write(uint8_t *dataptr, uint32_t value) +{ + le16write(dataptr, value); + le16write(dataptr + 2, value >> 16); +} + +void le32write_postinc(uint8_t *&dataptr, uint32_t value) +{ + le32write(dataptr, value); dataptr += 4; +} + +void le32pwrite_postinc(uint8_t *&dataptr, const u32pair_t &value) +{ + le32write_postinc(dataptr, value.first); + le32write_postinc(dataptr, value.second); +}
Added: branches/powerpc/reactos/tools/ppc-build/elfpe/util.h URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build/... ============================================================================== --- branches/powerpc/reactos/tools/ppc-build/elfpe/util.h (added) +++ branches/powerpc/reactos/tools/ppc-build/elfpe/util.h Sun Apr 29 08:05:11 2007 @@ -1,0 +1,20 @@ +#ifndef COMPDVR_UTIL_H +#define COMPDVR_UTIL_H + +#include <utility> +#include <stdint.h> + +void le16write(uint8_t *dataptr, uint16_t value); +void le16write_postinc(uint8_t *&dataptr, uint16_t value); +void le32write(uint8_t *dataptr, uint32_t value); +void le32write_postinc(uint8_t *&dataptr, uint32_t value); +uint16_t le16read(uint8_t *dataptr); +uint16_t le16read_postinc(uint8_t *&dataptr); +uint32_t le32read(uint8_t *dataptr); +uint32_t le32read_postinc(uint8_t *&dataptr); +typedef std::pair<uint32_t, uint32_t> u32pair_t; +void le32pwrite_postinc(uint8_t *&dataptr, const u32pair_t &pair); +void le32pwrite(uint8_t *dataptr, const u32pair_t &pair); +uint32_t roundup(uint32_t value, int round); + +#endif//COMPDVR_UTIL_H