Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link using lld #370

Closed
phil-opp opened this issue Nov 24, 2017 · 8 comments
Closed

Link using lld #370

phil-opp opened this issue Nov 24, 2017 · 8 comments
Labels
enhancement Potential improvements for the code or the blog.

Comments

@phil-opp
Copy link
Owner

Use the cross-platform lld linker of the LLVM project. Compared to the binutils linker, no manual cross-compilation is required.

@phil-opp phil-opp added the enhancement Potential improvements for the code or the blog. label Nov 24, 2017
@gil0mendes
Copy link
Contributor

@phil-opp One question. lld already has support for removing unused sections? The gc-sections of ld? That was one of the drawbacks that I found when used the lld.

@robert-w-gries
Copy link
Contributor

@gil0mendes ld.lld supports the gc-sections option, at least in version 4.0.1. I actually ran into a different issue where nmagic was missing as an option in a newer release.

@robert-w-gries
Copy link
Contributor

I had a chance to look into the issue again. I managed to get latest ld.lld working for blog_os

Notes regarding flags

  • gc-sections is available in the 4.x and later.
  • nmagic was removed at some point before 4.0 release. I believe it was removed when they moved to the new ELF linker.
  • omagic seems to be our replacement for nmagic. This flag differs from nmagic in that it sets the text and data sections to be readable and writable, in addition to disabling page-alignment. I'm not experienced enough with linkers to know whether this is allowed for our kernel.

Changes to linker.ld

In addition to using the omagic flag, I had to add ALIGNs to linker.ld in order to align the pages properly

Click to expand diff
diff --git a/src/arch/x86_64/linker.ld b/src/arch/x86_64/linker.ld
index 62f8f26..d5d5acc 100644
--- a/src/arch/x86_64/linker.ld
+++ b/src/arch/x86_64/linker.ld
@@ -14,7 +14,7 @@ ENTRY(start)
 SECTIONS {
   . = 1M;
 
-  .rodata :
+  .rodata : ALIGN(4K)
   {
     /* ensure that the multiboot header is at the beginning */
     KEEP(*(.multiboot_header))
@@ -22,31 +22,31 @@ SECTIONS {
     . = ALIGN(4K);
   }
 
-  .text :
+  .text : ALIGN(4K)
   {
     *(.text .text.*)
     . = ALIGN(4K);
   }
 
-  .data :
+  .data : ALIGN(4K)
   {
     *(.data .data.*)
     . = ALIGN(4K);
   }
 
-  .bss :
+  .bss : ALIGN(4K)
   {
     *(.bss .bss.*)
     . = ALIGN(4K);
   }
 
-  .got :
+  .got : ALIGN(4K)
   {
     *(.got)
     . = ALIGN(4K);
   }
 
-  .got.plt :
+  .got.plt : ALIGN(4K)

Testing for various linkers

  • ld - version 2.29-6.fc27 on my system
  • ld.lld v6.0.0 - This was the latest code available on the master branch
  • ld.lld v4.0.1 - This was the binary available on Fedora

ld.lld version 4.0.1

I could not get this version to work with blog_os.

PANIC in src/memory/paging/mod.rs at line 209:
    sections need to be page aligned

Dumping the sections in kernel-x86_64.bin reveals a duplicate .rodata section that is mis-aligned.

[rob@localhost blog_os]$ objdump -h build/kernel-x86_64.bin

build/kernel-x86_64.bin:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .rodata       00002c25  0000000000100000  0000000000100000  00001000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .rodata       000003d8  0000000000102c28  0000000000102c28  00003c28  2**3

I believe there was an issue with alignment in ld.lld 4.0.1 that was fixed later. I am going to build llvm 5.0.0 to narrow down where it was fixed.

@gil0mendes
Copy link
Contributor

Hey, before all, great report! 👏

Now. I had some time to look at this, and you are right. Forget what I said before, my problem was exactly the same. The -n (or -nmagic) flag is missing, and not using this flag led to issues since sections' pages become misaligned.

@phil-opp
Copy link
Owner Author

@robert-w-gries Awesome work!

omagic seems to be our replacement for nmagic. This flag differs from nmagic in that it sets the text and data sections to be readable and writable, in addition to disabling page-alignment. I'm not experienced enough with linkers to know whether this is allowed for our kernel.

Hmm, ideally we don't want a writable text section. But it's great that this seems to be the only issue with the latest lld!

ld.lld version 4.0.1

I could not get this version to work with blog_os.

It seems like lld will be distributed with the compiler soon (see rust-lang/rust#39915 (comment), which is currently blocked on the upgrade to LLVM 5). So we might not need to support older lld versions.

@Evrey
Copy link

Evrey commented Nov 28, 2017

Hmm, ideally we don't want a writable text section.

In fashion of the general security principle of "never trust a damn thing", you can always set the NX bit for the pages mapping your code sections, no matter what the kernel loader actually did. (And the read-only bit for .rodata and friends.)

@phil-opp phil-opp added this to the Second Edition milestone Dec 7, 2017
@steveklabnik
Copy link
Contributor

This can now be closed, right?

@phil-opp
Copy link
Owner Author

phil-opp commented Mar 6, 2018

Yes, closing in favor of #360. Thank you all for helping!

@phil-opp phil-opp closed this as completed Mar 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Potential improvements for the code or the blog.
Projects
None yet
Development

No branches or pull requests

5 participants