Page 1 of 1

[Solved] lld produces file with LMA=0 and no LOAD proghdr

Posted: Sun Dec 06, 2020 6:45 pm
by rooster
I was tryna write a x86_64 kernel in Rust and the kernel I get has sections at LMA=VMA=0.
src/main.rs is very simple:

Code: Select all

#![no_std]
#![no_main]
#![feature(global_asm)]

use core::panic::PanicInfo;

#[panic_handler]
fn on_panic(_info: &PanicInfo) -> ! {
	loop {}
}

global_asm!(r#"
.section ".mbhdr"
mb_header:
	.long 0xe85250d6
	.long 0
	.long mb_header_end - mb_header

	.long -(0xe85250d6 + 0 + (mb_header_end - mb_header))

	.short 0
	.short 0
	.long 8
mb_header_end:

.text
.globl start
.code32
start:
	movl $0x2f4b2f4f, 0xb8000
	hlt
"#);
JSON target config:

Code: Select all

{
	"arch": "x86_64",
	"code-model": "kernel",
	"cpu": "x86-64",
	"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
	"disable-redzone": true,
	"eliminate-frame-pointer": false,

	"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
	"is-builtin": true,

	"llvm-target": "x86_64-elf",
	"max-atomic-width": 64,

	"panic-strategy": "abort",

	"os": "none",
	"executables": true,
	"linker-flavor": "ld.lld",
	"linker": "rust-lld",
	"pre-link-args": {
		"ld.lld": ["-Tlinker.ld"]
	},
	"relocation-model": "static",


	"target-pointer-width": "64"
}
linker.ld

Code: Select all

ENTRY(start)

SECTIONS {
	. = 1M;

	.boot :
	{
		*(.mbhdr)
	}

	.text :
	{
		*(.text)
	}

	/DISCARD/ :
	{
		*(.debug*)
	}
}
`cargo xbuild` produces an executable with LMA=0 and no LOAD program header

Code: Select all

$ objdump -x target/x86_64_kernel/debug/rosd

target/x86_64_kernel/debug/rosd:     file format elf64-x86-64
target/x86_64_kernel/debug/rosd
architecture: i386:x86-64, flags 0x00000012:
EXEC_P, HAS_SYMS
start address 0x0000000000000030

Program Header:
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .boot         00000018  0000000000000000  0000000000000000  000000e8  2**0
                  CONTENTS, READONLY
  1 .comment      00000013  0000000000000000  0000000000000000  00000100  2**0
                  CONTENTS, READONLY
  2 .text         0000000b  0000000000000030  0000000000000030  000001f0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
0000000000000000 l    df *ABS*	0000000000000000 2x5qyqlxdq6xy7n9
0000000000000000 l       .boot	0000000000000000 mb_header
0000000000000018 l       .boot	0000000000000000 mb_header_end
0000000000000030 g       .text	0000000000000000 start
I've tried rust bootloader project json target description, but got absolutely the same resulting binary. Is it LLD's fault?

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 12:41 am
by iansjack
If you've not already done so, I'd suggest that you read this blog: https://os.phil-opp.com/

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 8:56 am
by xeyes
It's always a huge pain to fight with the linker, a lot of times it is easier to manually copy code and fix up offsets on the fly.

Some general ideas to try (this is for the plain old ld though, not sure if applicable to the llvm one):

1. name your code input sections

Code: Select all

.text.whatever
instead of plain

Code: Select all

.whatever
, this can trigger some undocumented magical behaviors that usually results in more desirable outcome
2. specify memories and phdrs explicitly
3. use lots of AT(LMA)

good luck!

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 9:41 am
by rooster
iansjack wrote:If you've not already done so, I'd suggest that you read this blog: https://os.phil-opp.com/
I've done so, but I don't get how this should solve my issue.

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 10:54 am
by iansjack
I only mention it because it produces a kernel that boots, so it might be a good starting point. In particular, take note of the requirement that the entry function be named "_start".

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 10:59 am
by rooster
iansjack wrote:I only mention it because it produces a kernel that boots, so it might be a good starting point. In particular, take note of the requirement that the entry function be named "_start".
You can use any name for the entrypoint, as long as you specify it in the linker script.

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 11:13 am
by linuxyne
Tested with ld.lld, and saw a similar behaviour.

Try making .mbhdr allocatable:

Code: Select all

.section ".mbhdr", "a"

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 11:35 am
by rooster
Now I have a LOAD program header and proper LMA, but .mbhdr section (and its content) disappeared from the executable:

Code: Select all

user@host $ objdump -x target/x86_64_kernel/debug/rosd

target/x86_64_kernel/debug/rosd:     file format elf64-x86-64
target/x86_64_kernel/debug/rosd
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000100000

Program Header:
    LOAD off    0x0000000000001000 vaddr 0x0000000000100000 paddr 0x0000000000100000 align 2**12
         filesz 0x000000000000000b memsz 0x000000000000000b flags r-x
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0000000b  0000000000100000  0000000000100000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .comment      00000013  0000000000000000  0000000000000000  0000100b  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
0000000000000000 l    df *ABS*	0000000000000000 2x5qyqlxdq6xy7n9
0000000000100000 g       .text	0000000000000000 start

Code: Select all

user@host $ objdump --disassemble-all -m i386 target/x86_64_kernel/debug/rosd

target/x86_64_kernel/debug/rosd:     file format elf64-x86-64


Disassembly of section .text:

0000000000100000 <start>:
  100000:	c7 05 00 80 0b 00 4f 	movl   $0x2f4b2f4f,0xb8000
  100007:	2f 4b 2f 
  10000a:	f4                   	hlt    

Disassembly of section .comment:

0000000000000000 <.comment>:
   0:	4c                   	dec    %esp
   1:	69 6e 6b 65 72 3a 20 	imul   $0x203a7265,0x6b(%esi),%ebp
   8:	4c                   	dec    %esp
   9:	4c                   	dec    %esp
   a:	44                   	inc    %esp
   b:	20 31                	and    %dh,(%ecx)
   d:	31 2e                	xor    %ebp,(%esi)
   f:	30 2e                	xor    %ch,(%esi)
  11:	30 00                	xor    %al,(%eax)
(And also .text now has file offset of 0x1000, which means if one move multiboot header to .text, GRUB won't find it that far).

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 12:04 pm
by linuxyne
You may want to test with ld.lld directly.

No idea why the linker dropped the mbhdr section; ld.lld on my machine didn't.

One can place mbhdr as shown in [1].

The 0x1000 offset is because ld page-aligned the sections. One can disable that by -n.

Following iansjack's comment, you may want to look at [2].




[1] https://wiki.osdev.org/Multiboot
[2] https://os.phil-opp.com/multiboot-kernel

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 12:54 pm
by rooster
linuxyne wrote:Following iansjack's comment, you may want to look at [2].
I've already done a multiboot-bootable executable with nasm and ld. I wanted to do smth like in https://lowenware.com/blog/osdev/aarch6 ... m-in-rust/, but for x86_64 with GRUB2.

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 7:11 pm
by Octocontrabass
rooster wrote:I wanted to do smth like in https://lowenware.com/blog/osdev/aarch6 ... m-in-rust/, but for x86_64 with GRUB2.
The author of that page notes that they had to put their assembly in a separate file to get their project to link correctly. Have you tried doing that?

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 7:17 pm
by rooster
Octocontrabass wrote:
rooster wrote:I wanted to do smth like in https://lowenware.com/blog/osdev/aarch6 ... m-in-rust/, but for x86_64 with GRUB2.
The author of that page notes that they had to put their assembly in a separate file to get their project to link correctly. Have you tried doing that?
Could you plz cite the exact sentence(s)? Because what I've found is that the author tells they had to keep the panic handler in a separate file so that linker script is not ignored.
But in my case, linker script is definitely not ignored. I had a bunch of `.debug.xxx` sections before I started /DISCARD/ing them.

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Mon Dec 07, 2020 7:26 pm
by Octocontrabass
Whoops, my mistake - they are indeed talking about the panic handler.

But, have you tried putting the panic handler in a separate file anyway, just to see if it makes a difference?

Re: [Rust] lld produces file with LMA=0 and no LOAD proghdr

Posted: Tue Dec 08, 2020 1:14 am
by rooster
Solved by changing the linker to ld:

Code: Select all

@@ -16,10 +16,10 @@
 
 	"os": "none",
 	"executables": true,
-	"linker-flavor": "ld.lld",
-	"linker": "rust-lld",
+	"linker-flavor": "ld",
+
 	"pre-link-args": {
-		"ld.lld": ["-Tlinker.ld"]
+		"ld": ["-n", "-Tlinker.ld"]
 	},
 	"relocation-model": "static",
 
(Also, the multiboot header shall be aligned to 8 bytes).