limine-bootloader/limine-rs

Causes conflict when used in a staticlib

Closed this issue · 12 comments

When using limine-rs in a staticlib, and linking that into an executable using ld.lld, the IDs inside the statics somehow get duplicated and cause conflicts:

image

Source with staticlib changes to reproduce: https://github.com/xdevs23/limine-rust-barebones/tree/staticlib-issue

When using binwalk on the staticlib file, we can see that there are two findings:

$ binwalk -R "\x75\xdd\x81\xd8\xdc\x27\x58\x9d\x1b" kernel/target/x86_64-unknown-none/debug/liblimine_rust_barebones.a

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
155068        0x25DBC         Raw signature (\x75\xdd\x81\xd8\xdc\x27\x58\x9d\x1b)
206148        0x32544         Raw signature (\x75\xdd\x81\xd8\xdc\x27\x58\x9d\x1b)

But when the same command is run on the executable (without my changes), only one occurrence is found:

$ binwalk -R "\x75\xdd\x81\xd8\xdc\x27\x58\x9d\x1b" kernel/target/x86_64-unknown-none/debug/limine-rust-barebones 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
9320          0x2468          Raw signature (\x75\xdd\x81\xd8\xdc\x27\x58\x9d\x1b)

I tried to define the structs myself in a more simple manner:
xdevs23/limine-rust-barebones@55f3376

If you build this branch, it works: https://github.com/xdevs23/limine-rust-barebones/tree/staticlib-issue-workaround

On the branch I mentioned, the limine crate is not used and instead, the limine_def module contains simpler structs.
Here's the binwalk output:

$ binwalk -R "\x75\xdd\x81\xd8\xdc\x27\x58\x9d\x1b" kernel/target/x86_64-unknown-none/debug/liblimine_rust_barebones.a 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
136288        0x21460         Raw signature (\x75\xdd\x81\xd8\xdc\x27\x58\x9d\x1b)

And a screenshot:

image

I created a modified version of limine-rs which seemed to have fixed the issue, but now, whenever I use the response, there's a conflict again:

Without using boot_info:
image

Using boot_info:
image

This is really weird and I'm starting to think that the rust compiler is redundantly placing the ID of the request somewhere in the data.

Why are you compiling as a static library and then turning it into an executable? Compiling it normally works fine.

In my actual kernel project, I'm linking object files written in other languages together with the rust staticlib to form the final executable.

I heard that I can also use #[limine_tag]. I'm currently trying that instead.

Using #[limine_tag] and having a .limine_reqs section solves the issue.


use limine::{LimineBootInfoRequest, limine_tag};

#[limine_tag]
static BOOT_INFO_REQUEST: LimineBootInfoRequest = LimineBootInfoRequest::new(0);

	.limine_reqs ALIGN(0x1000) : AT (ADDR (.limine_reqs) - load_addr)
	{
		KEEP(*(.limine_reqs))
	}

Binwalk still shows two occurrences for the statliclib, but when linked to a final executable, only one remains.

I think it is because of debug info. Try release @xdevs23.

I think it is because of debug info. Try release @xdevs23.

Release has the same result from what I have tested so far.

Are you sure you do not have debug information enabled? That is the only way I can think of right now that could produce a duplicate tag.

@Andy-Python-Programmer I think so. I built it as release:
image

Hi @xdevs23,

Could you please clone the crate and apply the following patch:

diff --git a/src/lib.rs b/src/lib.rs
index 7b69a87..32b90d8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -190,11 +190,11 @@ macro_rules! make_struct {
             // XXX: The request ID is composed of 4 64-bit wide unsigned integers but the first
             //      two remain constant. This is refered as `_COMMON_MAGIC` in the  protocol
             //      header.
-            pub const ID: [u64; 4] = [0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, $id1, $id2];
+            // pub const ID: [u64; 4] = [0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, $id1, $id2];
 
             pub const fn new(revision: u64) -> Self {
                 Self {
-                    id: Self::ID,
+                    id: [0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, $id1, $id2],
                     revision,
 
                     response: UnsafeCell::new(Ptr::DEFAULT),

Then make use of the patched crate to build it and see if it makes a difference.

@Andy-Python-Programmer
That works!
image

Had to also change something in the barebones code:

diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock
index b1c66b8..3292858 100644
--- a/kernel/Cargo.lock
+++ b/kernel/Cargo.lock
@@ -11,8 +11,6 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 [[package]]
 name = "limine"
 version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e9d0c951056ac044f0e6b09448b9d702f8fb1001db89cffd2bc467bd1c25307"
 
 [[package]]
 name = "limine-rust-barebones"
diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml
index d17de80..73f57a5 100644
--- a/kernel/Cargo.toml
+++ b/kernel/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-limine = "0.1"
+limine = { path = "limine-rs" }
 spin = "0.9"
 
 [profile.dev]
diff --git a/kernel/lib.rs b/kernel/lib.rs
index 504b736..cd01cb6 100644
--- a/kernel/lib.rs
+++ b/kernel/lib.rs
@@ -3,9 +3,9 @@
 
 use core::arch::asm;
 
-use limine::LimineFramebufferRequest;
+use limine::FramebufferRequest;
 
-static FRAMEBUFFER_REQUEST: LimineFramebufferRequest = LimineFramebufferRequest::new(0);
+static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new(0);
 
 #[no_mangle]
 unsafe extern "C" fn _start() -> ! {

Thank you!