From c2c13953277160f02fd4bcd46595c47c643ce23b Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Sun, 3 Dec 2023 09:39:54 -0500 Subject: [PATCH] use linker script --- source/Cosmos.Build.Tasks/Ld.cs | 101 ++++++++++++++++-- source/Cosmos.Build.Tasks/Nasm.cs | 25 +++-- .../build/Cosmos.Build.targets | 6 +- 3 files changed, 111 insertions(+), 21 deletions(-) diff --git a/source/Cosmos.Build.Tasks/Ld.cs b/source/Cosmos.Build.Tasks/Ld.cs index 8bbf1b8395..e068ec7578 100644 --- a/source/Cosmos.Build.Tasks/Ld.cs +++ b/source/Cosmos.Build.Tasks/Ld.cs @@ -25,7 +25,10 @@ public class Ld : ToolTask public string DataAddress { get; set; } - public string BssAddress { get; set; } + public string BssAddress { get; set; } + + [Required] + public string TargetArchitecture { get; set; } #endregion @@ -131,17 +134,95 @@ protected override string GenerateCommandLineCommands() { CommandLineBuilder xBuilder = new(); - xBuilder.AppendSwitchIfNotNull("-Ttext ", TextAddress); - xBuilder.AppendSwitchIfNotNull("-Tdata ", DataAddress); - xBuilder.AppendSwitchIfNotNull("-Tbss ", BssAddress); - xBuilder.AppendSwitchIfNotNull("-e ", Entry); xBuilder.AppendSwitchIfNotNull("-o ", OutputFile); - xBuilder.AppendFileNamesIfNotNull(InputFiles, " "); - xBuilder.AppendSwitch("-m elf_x86_64"); - - Log.LogMessage(MessageImportance.High, xBuilder.ToString()); - + xBuilder.AppendFileNamesIfNotNull(InputFiles, " "); + + if (TargetArchitecture == "amd64") + { + var dir = Path.GetDirectoryName(OutputFile); + var path = dir + "/linker.ld"; + xBuilder.AppendSwitch("-m elf_x86_64"); + xBuilder.AppendSwitchIfNotNull("-T ", path); + + + + File.WriteAllText(path, @"/* Tell the linker that we want an x86_64 ELF64 output file */ +OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_ARCH(i386:x86-64) + +/* We want the symbol _start to be our entry point */ +ENTRY(" + Entry + @") + +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions */ +PHDRS +{ + text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ + rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ + data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ + dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */ +} + +SECTIONS +{ + /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */ + /* and because that is what the Limine spec mandates. */ + /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ + /* that is the beginning of the region. */ + . = 0xffffffff80000000; + + .text : { + *(.text .text.*) + } :text + + /* Move to the next memory page for .rodata */ + . += CONSTANT(MAXPAGESIZE); + + .rodata : { + *(.rodata .rodata.*) + } :rodata + + /* Move to the next memory page for .data */ + . += CONSTANT(MAXPAGESIZE); + + .data : { + *(.data .data.*) + } :data + + /* Dynamic section for relocations, both in its own PHDR and inside data PHDR */ + .dynamic : { + *(.dynamic) + } :data :dynamic + + /* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */ + /* unnecessary zeros will be written to the binary. */ + /* If you need, for example, .init_array and .fini_array, those should be placed */ + /* above this. */ + .bss : { + *(.bss .bss.*) + *(COMMON) + } :data + + /* Discard .note.* and .eh_frame since they may cause issues on some hosts. */ + /DISCARD/ : { + *(.eh_frame) + *(.note .note.*) + } +}"); + } + else + { + xBuilder.AppendSwitch("-m elf_i386"); + + xBuilder.AppendSwitchIfNotNull("-Ttext ", TextAddress); + xBuilder.AppendSwitchIfNotNull("-Tdata ", DataAddress); + xBuilder.AppendSwitchIfNotNull("-Tbss ", BssAddress); + xBuilder.AppendSwitchIfNotNull("-e ", Entry); + } + + Log.LogMessage(MessageImportance.High, xBuilder.ToString()); + return xBuilder.ToString(); } diff --git a/source/Cosmos.Build.Tasks/Nasm.cs b/source/Cosmos.Build.Tasks/Nasm.cs index 4b3ebc69e9..56b4147911 100644 --- a/source/Cosmos.Build.Tasks/Nasm.cs +++ b/source/Cosmos.Build.Tasks/Nasm.cs @@ -13,10 +13,10 @@ enum OutputFormatEnum { Bin, ELF - } - + } + #region Task Parameters - + [Required] public string InputFile { get; set; } @@ -30,7 +30,10 @@ public string OutputFormat set => mOutputFormat = (OutputFormatEnum)Enum.Parse(typeof(OutputFormatEnum), value, true); } - public string OptimizationLevel { get; set; } + public string OptimizationLevel { get; set; } + + [Required] + public string TargetArchitecture { get; set; } #endregion @@ -99,11 +102,15 @@ protected override string GenerateCommandLineCommands() { xBuilder.AppendSwitch("-dBIN_COMPILATION"); } - xBuilder.AppendSwitch("-m amd64"); - - /* Apply the optimization level that the user chose */ - if(!String.IsNullOrWhiteSpace(OptimizationLevel) && !String.IsNullOrWhiteSpace(OptimizationLevel)) - xBuilder.AppendSwitch($"-O{OptimizationLevel}"); + + if (TargetArchitecture == "amd64") + { + xBuilder.AppendSwitch("-m amd64"); + } + + /* Apply the optimization level that the user chose */ + if (!String.IsNullOrWhiteSpace(OptimizationLevel) && !String.IsNullOrWhiteSpace(OptimizationLevel)) + xBuilder.AppendSwitch($"-O{OptimizationLevel}"); xBuilder.AppendFileNameIfNotNull(InputFile); diff --git a/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets b/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets index ac5e2e98f4..d368fb7a6e 100644 --- a/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets +++ b/source/Cosmos.Build.Tasks/build/Cosmos.Build.targets @@ -228,7 +228,8 @@ OutputFormat="$(BinFormat)" ToolPath="$(NasmToolPath)" ToolExe="$(NasmToolExe)" - OptimizationLevel="$(OptimizationLevel)"/> + OptimizationLevel="$(OptimizationLevel)" + TargetArchitecture="$(TargetArchitecture)"/> @@ -255,7 +256,8 @@ DataAddress="0x1000000" Entry="Kernel_Start" ToolPath="$(LdToolPath)" - ToolExe="$(LdToolExe)" /> + ToolExe="$(LdToolExe)" + TargetArchitecture="$(TargetArchitecture)"/>