コード例 #1
0
ファイル: LinkManager.cs プロジェクト: rmhasan/FlingOS
        /// <summary>
        /// Performs the link.
        /// </summary>
        /// <param name="TheLibrary">The root library to link.</param>
        /// <returns>CompileResult.OK if the link succeeded. Otherwise, CompileResult.Fail.</returns>
        public static CompileResult Link(IL.ILLibrary TheLibrary, bool dependency = false, string Name = null)
        {
            bool OK = true;
            
            // If: Link to ELF and Libraries
            //      - Link sub-libs to .a files
            //      - Link main lib to .elf file (if present)
            // If: Link to ISO
            //      - Generate basic link-script
            //      - Generate full link-script by inserting necessary file location instructions for all object files
            //      - Execute ld to build bin file
            //      - Execute ISO9660Generator to build .ISO file

            if (Options.LinkMode == Options.LinkModes.ELF)
            {
                // Check for main method. If found, that library gets linked to Executable not Shared Lib

                List<string> depLibNames = new List<string>();
                foreach (IL.ILLibrary depLib in TheLibrary.Dependencies)
                {
                    string depLibName = Utilities.CleanFileName(depLib.TheAssembly.GetName().Name);
                    if (Options.ShortenDependencyNames)
                    {
                        if (!DependencyNameMapping.ContainsKey(depLibName))
                        {
                            DependencyNameMapping.Add(depLibName, (NameGenerator++).ToString());
                        }

                        depLibName = DependencyNameMapping[depLibName];
                    }
                    depLibNames.Add(depLibName);

                    OK = OK && (Link(depLib, true, depLibName) == CompileResult.OK);
                    if (!OK)
                    {
                        break;
                    }
                }

                if (!OK)
                {
                    return CompileResult.Fail;
                }

                List<ASM.ASMBlock> SequencedASMBlocks = new List<ASM.ASMBlock>();
                SequencedASMBlocks.AddRange(TheLibrary.TheASMLibrary.ASMBlocks);
                SequencedASMBlocks.Sort(GetOrder);
                SequencedASMBlocks.ForEach(delegate(ASM.ASMBlock block)
                {
                    if (block != null && block.OriginMethodInfo != null)
                    {
                        DebugDataWriter.AddMethodMapping(block.OriginMethodInfo.ID, block.ASMOutputFilePath);
                    }
                });
                
                // Find start method if any, use as ENTRY point
                bool ExecutableOutput = false;
                string EntryPoint = null;
                if (IL.ILLibrary.SpecialMethods.ContainsKey(typeof(Attributes.MainMethodAttribute)))
                {
                    Types.MethodInfo mainMethodInfo = IL.ILLibrary.SpecialMethods[typeof(Attributes.MainMethodAttribute)].First();
                    IL.ILBlock mainMethodBlock = TheLibrary.GetILBlock(mainMethodInfo, false);
                    if (mainMethodBlock != null)
                    {
                        ExecutableOutput = true;
                        EntryPoint = mainMethodInfo.ID;
                    }
                }

                if (Options.ShortenDependencyNames && string.IsNullOrWhiteSpace(Name))
                {
                    Name = "Driver";
                }

                string AssemblyName = string.IsNullOrWhiteSpace(Name) ? Utilities.CleanFileName(TheLibrary.TheAssembly.GetName().Name) : Name;

                DebugDataWriter.SaveDataFiles(Options.OutputPath, AssemblyName);
                DebugDataWriter.SaveLibraryInfo(Options.OutputPath, TheLibrary);

                LinkInformation LinkInfo = new LinkInformation()
                {
                    ToolsPath = Options.ToolsPath,
                    LinkScriptCmdPath = Path.Combine(Options.OutputPath, @"DriversCompiler\" + AssemblyName + "_linker_command.txt"),
                    LinkScriptPath = Path.Combine(Options.OutputPath, @"DriversCompiler\" + AssemblyName + "_linker.ld"),
                    BinPath = Path.Combine(Options.OutputPath, "Output\\" + (ExecutableOutput ? AssemblyName + ".elf" : "Lib" + AssemblyName + ".a")),
                    MapPath = Path.Combine(Options.OutputPath, AssemblyName + ".map"),
                    ASMPath = Path.Combine(Options.OutputPath, AssemblyName + ".new.asm"),
                    LdWorkingDir = Path.Combine(Options.OutputPath, "") + "\\",
                    ExecutableOutput = ExecutableOutput,
                    EntryPoint = EntryPoint,
                    SequencedASMBlocks = SequencedASMBlocks,
                    depLibNames = depLibNames
                };

                if (!Directory.Exists(Path.GetDirectoryName(LinkInfo.BinPath)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(LinkInfo.BinPath));
                }

                OK = TargetArchitecture.TargetFunctions.LinkELF(TheLibrary, LinkInfo);

                if (OK)
                {
                    DebugDataWriter.ProcessMapFile(LinkInfo.MapPath);
                }
            }
            else if (Options.LinkMode == Options.LinkModes.ISO)
            {
                List<ASM.ASMBlock> SequencedASMBlocks = new List<ASM.ASMBlock>();
                List<IL.ILLibrary> FlattenedLibs = TheLibrary.Flatten();
                foreach (IL.ILLibrary depLib in FlattenedLibs)
                {
                    SequencedASMBlocks.AddRange(depLib.TheASMLibrary.ASMBlocks);
                    DebugDataWriter.SaveLibraryInfo(Options.OutputPath, depLib);
                }
                SequencedASMBlocks.Sort(GetOrder);
                SequencedASMBlocks.ForEach(delegate(ASM.ASMBlock block)
                {
                    if (block != null && block.OriginMethodInfo != null)
                    {
                        DebugDataWriter.AddMethodMapping(block.OriginMethodInfo.ID, block.ASMOutputFilePath);
                    }
                });
                
                string AssemblyName = Utilities.CleanFileName(TheLibrary.TheAssembly.GetName().Name);

                DebugDataWriter.SaveDataFiles(Options.OutputPath, AssemblyName);
                DebugDataWriter.SaveLibraryInfo(Options.OutputPath, TheLibrary);

                LinkInformation LinkInfo = new LinkInformation()
                {
                    ToolsPath = Options.ToolsPath,
                    ISOGenPath = Path.Combine(Options.ToolsPath, @"ISO9660Generator.exe"),
                    ISOToolsDirPath = Path.Combine(Options.ToolsPath, @"ISO"),
                    ISODirPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO"),
                    LinkScriptPath = Path.Combine(Options.OutputPath, @"DriversCompiler\linker.ld"),
                    BinPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO\Kernel.bin"),
                    ISOLinuxPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO\" + (Options.BuildMode == Options.BuildModes.Debug ? "isolinux-debug.bin" : "isolinux.bin")),
                    ISOPath = Path.Combine(Options.OutputPath, AssemblyName + ".iso"),
                    MapPath = Path.Combine(Options.OutputPath, AssemblyName + ".map"),
                    ASMPath = Path.Combine(Options.OutputPath, AssemblyName + ".new.asm"),
                    LdWorkingDir = Path.Combine(Options.OutputPath, "DriversCompiler") + "\\",
                    SequencedASMBlocks = SequencedASMBlocks
                };

                if (Directory.Exists(LinkInfo.ISODirPath))
                {
                    Directory.Delete(LinkInfo.ISODirPath, true);
                }
                CopyDirectory(LinkInfo.ISOToolsDirPath, LinkInfo.ISODirPath, true);

                OK = TargetArchitecture.TargetFunctions.LinkISO(TheLibrary, LinkInfo);

                if (OK)
                {
                    DebugDataWriter.ProcessMapFile(LinkInfo.MapPath);
                }
            }

            return OK ? CompileResult.OK : CompileResult.Fail;
        }