0

Im writing a kernel in Rust, but are having some problems with the panicking module. I have written a build script that should build the boot image of the OS, but i seem to get an error while trying to draw text to the VGA.

Here is the error im getting:

ld: /home/pollen/projects/pollos/kernel/target/i386/debug/deps/kernel-285a1fe9a5f16fae.o: in function `core::ptr::mut_ptr::<impl *mut T>::offset::precondition_check':
/home/pollen/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ub_checks.rs:68:(.text._ZN4core3ptr7mut_ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$6offset18precondition_check17hf78ea68a8deeea7eE+0x33): undefined reference to `core::panicking::panic_nounwind'
ld: /home/pollen/projects/pollos/kernel/target/i386/debug/deps/kernel-285a1fe9a5f16fae.o: in function `_start':
/home/pollen/projects/pollos/kernel/src/main.rs:21:(.text._start+0x73): undefined reference to `core::panicking::panic_null_pointer_dereference'

Here is my rust code:

// src/main.rs

#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[unsafe(no_mangle)] // don't mangle the name of this function
pub extern "C" fn _start() -> ! {
    // this function is the entry point, since the linker looks for a function
    // named `_start` by default
    let vga = 0xb8000 as *mut u8;
    unsafe {
        *vga = b'H';
        *vga.offset(1) = 0x0f;
    }
    loop {}
}

I am not sure why the linker is throwing an error, and i have had trouble figuring out all the build arguments and config files. Here is my .cargo/config.toml:

# in .cargo/config.toml

[unstable]
build-std = ["core", "compiler_builtins"]
build-std-features = ["compiler-builtins-mem"]

I have written a custom target, for compiling to the i386 architecture:

{
    "llvm-target": "i386-unknown-none",
    "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
    "arch": "x86",
    "os": "none",
    "vendor": "unknown",
    "linker-flavor": "ld.lld",
    "linker": "rust-lld",
    "executables": true,
    "disable-redzone": true,
    "panic-strategy": "abort",
    "relocation-model": "static",
    "code-model": "kernel",
    "target-pointer-width": "32",
    "features": "-mmx,-sse,+soft-float",
    "rustc-abi": "x86-softfloat"
}

The last (but most important) file im going to show you, is the build.sh file which i run to compile and link the kernel and bootloader:

#!/bin/bash

set -e  # Exit on any error

KERNEL_DIR="/home/pollen/projects/pollos/kernel"
KERNEL_TARGET="$KERNEL_DIR/i386.json"
BL_DIR="/home/pollen/projects/pollos/bootloader"
BL_BUILD=$BL_DIR"/build"

compile_kernel () {
    echo "[*] Compiling kernel..."
    
    export RUSTFLAGS="--emit=obj"

    rustup override set nightly

    (cd kernel && cargo clean)

    # Run Cargo with explicit --target path
    cargo build -Z build-std=core --target "$KERNEL_TARGET" --manifest-path "$KERNEL_DIR/Cargo.toml"
    
    # Optional: move resulting .o file if needed
    KERNEL_OBJ=$(find "$KERNEL_DIR/target/i386/debug/deps/" -name "kernel-*.o")

    if [ -z "$KERNEL_OBJ" ]; then
        echo "Kernel object file not found!"
        exit 1
    fi

    echo "[+] Kernel object file: $KERNEL_OBJ"
}

compile_bootloader() {
    echo "[*] Compiling bootloader..."

    mkdir -p "$BL_DIR/build"

    nasm "$BL_DIR/bootsector.asm" -f bin -o "$BL_DIR/build/bootsector.bin" -I"$BL_DIR"
    nasm "$BL_DIR/kernel_entry.asm" -f elf -o "$BL_DIR/build/kernel_entry.o"
    
    echo "[+] Bootloader binaries created."
}

link() {
    echo "[*] Linking kernel and bootloader..."

    ld -m elf_i386 -o "$BL_DIR/build/bootable_kernel.bin" \
        --entry _start \
        "$BL_DIR/build/kernel_entry.o" \
        "$KERNEL_OBJ" \
        -Ttext 0x1000 \
        --oformat binary
    
    echo "[+] Bootable kernel created."
}

link2() {
    ld -m elf_i386 -T $BL_DIR/linker.ld -o kernel.elf $BL_BUILD/kernel_entry.o "$KERNEL_OBJ"
    objcopy -O binary kernel.elf kernel.bin
    cat $BL_BUILD/bootsector.bin kernel.bin > bootable_kernel.bin
}

compile_kernel
compile_bootloader
link
4
  • This function is used by the standard library, only on debug builds, to panic when a null pointer is dereferenced. It's weird that you get this error given it is defined in core. Commented May 14 at 23:53
  • Wait. Maybe you don't link core? I'm not sure it will be in the target folder. Commented May 14 at 23:54
  • Try to use some other function from core that won't be inlined (a big or inline(never) function), to tell if you link core. Commented May 14 at 23:57
  • Note that you likely want to use volatile read/writes for VGA memory. Commented May 15 at 0:13

1 Answer 1

0

You don't link core and compiler_builtins. Beside your kernel object files, you also need to link the files compiler_builtins-<hash>.o and core-<hash>.o from target/deps.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.