Esempio n. 1
0
        private IEnumerable <T> Assmeble <T>(AssemblySource <MASM> assemblySource, TargetArch targetArch, Func <byte[], T> TConstructor)
            where T : ObjectFile, new()
        {
            List <T> objectFiles = new List <T>();

            using (new TemporaryContext())
            {
                foreach (var sourceFile in assemblySource.SourceFiles)
                {
                    System.IO.File.WriteAllBytes(sourceFile.Filename, sourceFile.Bytes);
                }
                foreach (var sourceFile in assemblySource.SourceFiles.Where(sf => sf.Type == AssemblySourceFileType.Asm))
                {
                    var program         = targetArch == TargetArch.x64 ? "ml64.exe" : "ml.exe";
                    var arguments       = String.Format("/nologo /Fo object.obj /c /Cx {0}", sourceFile.Filename);
                    var assembleCommand = program + " " + arguments;
                    var msvcVersion     = version.ToString().Replace("v", "").Replace("_", ".");
                    var assembleBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + assembleCommand;
                    assembleBatFile = String.Format(assembleBatFile, targetArch.ToString());
                    File.WriteAllText("assemble.bat", assembleBatFile);
                    var proc = Process.Start("cmd.exe", "/c " + "assemble.bat");
                    proc.WaitForExit();
                    if (!System.IO.File.Exists("object.obj"))
                    {
                        throw new Exception("Masm error. Object file not found.");
                    }
                    var objectFileBytes = System.IO.File.ReadAllBytes("object.obj");
                    objectFiles.Add(TConstructor(objectFileBytes));
                }
            }
            return(objectFiles);
        }
Esempio n. 2
0
        // TODO: Support compiling source files recursively
        private StaticLibrary <T> Compile <T>(ICCxxSource source, TargetArch targetArch, Func <byte[], T> TConstructor)
            where T : ObjectFile, new()
        {
            switch (targetArch)
            {
            case TargetArch.x86:
                CConfig.MACHINE = Config.Machine.X86;
                break;

            case TargetArch.x64:
                CConfig.MACHINE = Config.Machine.X64;
                break;

            case TargetArch.arm:
            case TargetArch.arm64:
                CConfig.MACHINE = Config.Machine.ARM;
                break;
            }

            using (new TemporaryContext())
            {
                var exts = new HashSet <string>();
                foreach (var sourceFile in source.SourceFiles)
                {
                    File.WriteAllText(sourceFile.Filename, sourceFile.Source);
                    if (sourceFile.Type == CCxxSourceFileType.C || sourceFile.Type == CCxxSourceFileType.Cxx)
                    {
                        exts.Add(Path.GetExtension(sourceFile.Filename));
                    }
                }
                var sourceFilenames = exts.Select(ext => "*" + ext);

                var compilerOptions = CConfig.ToString();
                var compileCommand  = $"cl.exe /c /nologo /diagnostics:column {compilerOptions} {string.Join(" ", sourceFilenames)}";
                var msvcVersion     = version.ToString().Replace("v", "").Replace("_", ".");
                var compileBatFile  = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + compileCommand;
                compileBatFile = String.Format(compileBatFile, targetArch.ToString());
                File.WriteAllText("compile.bat", compileBatFile);
                var proc = Process.Start("cmd.exe", "/c " + "compile.bat");
                proc.WaitForExit();

                string[] objectFilePaths = Directory.GetFiles(".", "*.obj", SearchOption.AllDirectories);
                var      objectFiles     = objectFilePaths.ToList().Select((file) => TConstructor(File.ReadAllBytes(file))).ToList();
                return(new StaticLibrary <T>(objectFiles));
            }
        }
Esempio n. 3
0
        private U Link <T, U>(IEnumerable <StaticLibrary <T> > staticLibraries, TargetArch targetArch, Func <byte[], U> UConstructor, Config.OutputType outputType)
            where T : ObjectFile, new()
            where U : IPortableExecutable, new()
        {
            switch (targetArch)
            {
            case TargetArch.x86:
                CConfig.MACHINE = Config.Machine.X86;
                break;

            case TargetArch.x64:
                CConfig.MACHINE = Config.Machine.X64;
                break;

            case TargetArch.arm:
            case TargetArch.arm64:
                CConfig.MACHINE = Config.Machine.ARM;
                break;
            }
            var outputExtension = ".exe";

            switch (outputType)
            {
            case Config.OutputType.EXE:
                CConfig.outputType = Config.OutputType.EXE;
                outputExtension    = ".exe";
                break;

            case Config.OutputType.DLL:
                CConfig.outputType = Config.OutputType.DLL;
                outputExtension    = ".dll";
                break;

            case Config.OutputType.DRIVER:
                CConfig.outputType = Config.OutputType.DRIVER;
                outputExtension    = ".sys";
                break;
            }

            using (new TemporaryContext())
            {
                foreach (var staticLibrary in staticLibraries)
                {
                    foreach (var objectFile in staticLibrary.ObjectFiles)
                    {
                        File.WriteAllBytes(Core.Utils.RandomString(10) + ".obj", objectFile.Bytes);
                    }
                }
                var outputfilename = "OUTPUT" + outputExtension;
                var linkerOptions  = CConfig.ToString();
                if (linkerOptions.Length > 0)
                {
                    linkerOptions = " " + linkerOptions;
                }
                var linkCommand = "link.exe";
                linkCommand += " /out:" + outputfilename;
                linkCommand += " /NOLOGO";
                linkCommand += linkerOptions;
                linkCommand += " *.obj";
                var msvcVersion = version.ToString().Replace("v", "").Replace("_", ".");
                var linkBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + linkCommand;
                linkBatFile = String.Format(linkBatFile, targetArch.ToString());
                File.WriteAllText("link.bat", linkBatFile);
                var proc = Process.Start("cmd.exe", "/c " + "link.bat");
                proc.WaitForExit();
                var pe = UConstructor(File.ReadAllBytes(outputfilename));
                if (CConfig.MAP)
                {
                    pe.Map = File.ReadAllText("OUTPUT.map");
                }
                return(pe);
            }
        }
Esempio n. 4
0
        internal static StaticLibrary <T> LibFileToStaticLibrary <T>(string libFile, Func <byte[], T> TConstructor, TargetArch targetArch, Version version = Version.v14_16, IEnumerable <string> includeFilter = null)
            where T : ObjectFile, new()
        {
            var objectPaths = new List <string>();

            using (new TemporaryContext())
            {
                var command     = $"lib.exe /nologo /list {libFile}";
                var msvcVersion = version.ToString().Replace("v", "").Replace("_", ".");
                var listBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + command;
                listBatFile = String.Format(listBatFile, targetArch.ToString());
                File.WriteAllText("list.bat", listBatFile);
                Process process = new Process();
                process.StartInfo.FileName               = "cmd.exe";
                process.StartInfo.Arguments              = "/c list.bat";
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                process.Start();
                while (!process.StandardOutput.EndOfStream)
                {
                    string line = process.StandardOutput.ReadLine();
                    if (line.Contains("**"))
                    {
                        continue;
                    }
                    if (line.ToLower().Contains("vcvars"))
                    {
                        continue;
                    }
                    if (line != "")
                    {
                        objectPaths.Add(line);
                    }
                }
                process.WaitForExit();
            }

            objectPaths = objectPaths.Where(x => includeFilter == null || includeFilter.Any(y => x.Contains(y))).ToList();

            using (new TemporaryContext())
            {
                var msvcVersion    = version.ToString().Replace("v", "").Replace("_", ".");
                var extractBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n";
                extractBatFile = String.Format(extractBatFile, targetArch.ToString());
                File.WriteAllText("extract.bat", extractBatFile);
                foreach (var objectPath in objectPaths)
                {
                    var command = $"lib.exe /nologo {libFile} /EXTRACT:{objectPath}";
                    File.AppendAllText("extract.bat", $"\r\n{command}");
                }
                Process.Start("cmd.exe", "/c extract.bat").WaitForExit();


                // Parse the object files for their Symbol names
                string[] objectFilePaths = Directory.GetFiles(".", "*.obj", SearchOption.AllDirectories);
                var      symbolsBatFile  = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n";
                symbolsBatFile = String.Format(symbolsBatFile, targetArch.ToString());
                File.WriteAllText("symbols.bat", symbolsBatFile);
                foreach (var objectFilePath in objectFilePaths)
                {
                    var command = $"dumpbin /symbols {objectFilePath} | findstr External | findstr -v UNDEF > {objectFilePath}.txt";
                    File.AppendAllText("symbols.bat", $"\r\n{command}");
                }
                Process.Start("cmd.exe", "/c symbols.bat").WaitForExit();
                var objectFiles = new List <T>();
                foreach (var objectFilePath in objectFilePaths)
                {
                    var symbols    = new List <string>();
                    var objectFile = TConstructor(File.ReadAllBytes(objectFilePath));
                    var lines      = File.ReadLines($"{objectFilePath}.txt");
                    foreach (var line in lines)
                    {
                        var line2 = line.Trim();
                        if (line2 == "")
                        {
                            continue;
                        }
                        var symbol = line.Split("| ")[1];
                        symbols.Add(symbol);
                    }
                    objectFile.ExternalSymbols = symbols;
                    objectFiles.Add(objectFile);
                }

                return(new StaticLibrary <T>(objectFiles));
            }
        }