1

I'm trying to cross compile a custom OS for x86 hardware on an ARM based system (Debian VM on M1 Mac). To compile I'm using "x86_64-linux-gnu-gcc" and for a linker I'm using "x86_64_linux-gnu-ld".

Note that this does build and compile normally when not on an ARM system. So an x86_64 system will compile and link correctly. I am trying to cross compile this because the ARM version of gcc does not like the x86 assembly boot code that we have (if you think this is the better approach and have tips for handling it this way please let me know).

The error I have comes up when trying to go through the linking process:

Linking for "kernel/kernel.bin"...
main/acpi.o: in function `__rsdp_search_range':
/home/project/kernel/main/acpi.c:63:(.text+0x13b): relocation truncated to fit: R_X86_64_32 against `.rodata'
main/acpi.o: in function `acpi_init':
/home/project/kernel/main/acpi.c:108:(.text+0x290): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:108:(.text+0x295): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:108:(.text+0x29a): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:108:(.text+0x2a4): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:114:(.text+0x327): additional relocation overflows omitted from the output
make[1]: *** [Makefile:34: kernel.bin] Error 1
make[1]: Leaving directory '/home/project/kernel'
make: *** [Makefile:6: all_kernel] Error 2

After trying to search for similar errors, I tried modifying the gcc flags. We already had -mcmodel=large, but i tested with the different variations. I also tested with -fPIC but none of these changes fixed the problem.

gcc flags:

cflags.x86-64   := -march=x86-64 -m64 -mno-red-zone -mcmodel=large -mno-sse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -mno-sse4 -mno-sse4a -mno-3dnow -mno-avx -mno-avx2
cflags.common   := -fno-pie -ffreestanding -fno-builtin -nostdinc -std=c99 -g3 -gdwarf-3 -fno-stack-protector -fsigned-char -Iinclude
cflags.warnings := -Wall -Wredundant-decls -Wundef -Wpointer-arith -Wfloat-equal -Wnested-externs -Wvla -Winline -Wextra -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -Wno-attributes

linker code:

OUTPUT_FORMAT(elf64-x86-64)

KERNEL_LMA = 0x00100000;
KERNEL_VMA = 0xffff800000000000;

ENTRY(_start)
STARTUP(entry/entry.o)

SECTIONS {
    . = KERNEL_VMA + KERNEL_LMA;

    k_start = .;

    .text : AT(ADDR(.text) - KERNEL_VMA) {
        _code = .;
        *(.multiboot)
        *(.text)
        . = ALIGN(0x1000);
    }

    csd_start = .;
    .csd : AT(ADDR(.csd) - KERNEL_VMA) {
        *(.csd)
        . = ALIGN(0x1000);
    }
    csd_end = .;

    .init :  AT(ADDR(.init) - KERNEL_VMA) {
        kernel_start_init = .;
        *(.init)
        . = ALIGN(0x1000);
        kernel_end_init = .;
    }


    .rodata : AT(ADDR(.rodata) - KERNEL_VMA) {
        _rodata = .;
        *(.rodata)
        . = ALIGN(0x1000);
    }

    .data : AT(ADDR(.data) - KERNEL_VMA) {
        _data = .;
        *(.data)
        . = ALIGN(0x1000);
    }

    _edata = .;

    .bss : AT(ADDR(.bss) - KERNEL_VMA) {
        _bss = .;
        *(.bss)
        *(COMMON)
        . = ALIGN(0x1000);
    }

    _end = .;

    /DISCARD/ : {
        *(.comment)
        *(note.*)
    }
    kernel_phys_off = k_start - KERNEL_LMA;
    kernel_phys_base = k_start - kernel_phys_off;
    kernel_phys_end = _end - kernel_phys_off;
    kernel_page_tables = ((_end - k_start) / 0x80000) + 1; /* XXX might be 0x200000 */
    kernel_text_sectors = ((_end - k_start) / 512) + 1;
}

Edit

Below is the __rsdp_search_range function, I dont necessarily think it is the problem because if I comment out this file, for instance, the error pops up elsewhere.

static rsdp_20_t *__rsdp_search_range(uintptr_t start, uintptr_t end)
{
    uintptr_t rsdp_candidate = start;
    while (rsdp_candidate <= end - sizeof(struct rsdp))
    {
        if (memcmp((void *)rsdp_candidate, rsdp_sig, sizeof(rsdp_sig)) == 0 &&
            __acpi_checksum((uint8_t *)rsdp_candidate, sizeof(rsdp_20_t)) ==
                0)
        {
            return (rsdp_20_t *)rsdp_candidate;
        }
        rsdp_candidate += RSDP_ALIGN;
    }
    return NULL;
}

I did try and remove -fno-pie and got the following error instead: x86_64-linux-gnu-ld: failed to convert GOTPCREL relocation; relink with --no-relax"

gizmo1479
  • 11
  • 3
  • Can you show us the code you have for `__rsdp_search_range` – Michael Petch Jan 17 '23 at 18:23
  • *I also tested with `-fPIC` ...* Did you also remove `-fno-pie` when you added `-fPIC`? – Andrew Henle Jan 17 '23 at 18:24
  • I made changes in the post! I'm most curious as to if removing -fno-pie is the way to go here. – gizmo1479 Jan 17 '23 at 18:44
  • 1
    If your bootloader doesn't do dynamic relocations (you appear to be using GRUB so it doesn't do it) and handle a GOT you should NOT be using PIC code. Compile with `-fno-PIC` and link with `-no-pie`. Since you aren't using an ELF cross compiler I'll assume what is going on is that the linux cross compiler you are using has changed the defaults it uses to generate PIC code where that may not have been the case with the other GCC toolchains you used. I'd be curious what cross compiler you used when you weren't running on your M1. – Michael Petch Jan 17 '23 at 18:54
  • We are using GRUB, so actually adding -fno-PIC gives the same "GOTPCREL" error above but linking with --no-pie gives something else: `relocation truncated to fit: R_x86_64_PC32 against symbol 'kernel_phys_end' defined in *ABS* section in kernel.bin'` When not on the M1, we are on x86 hardware so no cross compiling has to be done (we just use normal gcc). I'm fairly sure this was mostly made to be built and run on x86.... – gizmo1479 Jan 17 '23 at 18:55
  • I'd be curious to know if `kernel_phys_end` error `relocation truncated to fit: R_x86_64_PC32 against symbol 'kernel_phys_end'` was because you have some assembly code that uses that symbol, but it doesn't reference it a way can be handled if the kernel is loaded in higher half memory. – Michael Petch Jan 17 '23 at 18:57
  • I see you have github repos. Any chance you can toss your project in there to peak at it? I understand if you say no if this is some internal project where you may not wish to share source. – Michael Petch Jan 17 '23 at 19:00
  • Thanks for the help! I can't publicly share the github though. The error is actually coming from some C code here... – gizmo1479 Jan 17 '23 at 19:06
  • This means somewhere in your .rodata section you are trying to fit a 64-bit pointer in 32 bits. Since the compiler is writing the assembly code, maybe you can show us the assembly code it wrote for __rsdp_search_range? – user253751 Jan 17 '23 at 19:11
  • Are you sure you need `-mcmodel=large`? Your code+data+BSS is greater than 2GiB? Even `-mcmodel=medium` (where only large arrays need 64-bit absolute addressing) would make most function calls and static data access more efficient, but normally `-mcmodel=kernel` for a high-half kernel is sensible. Also note that `-no-pie` affects linking, and is totally separate from the code-gen options `-fPIE` or `-fno-pie`. Presumably different defaults for some option you're not setting is the problem, but your [mcve] is not at all minimal. (I'd guess just 1 or 2 source files could repro it.) – Peter Cordes Jan 18 '23 at 04:25
  • See also [32-bit absolute addresses no longer allowed in x86-64 Linux?](https://stackoverflow.com/q/43367427) for more about where these linker errors come from, and position-independent vs. 32-bit absolute addressing. – Peter Cordes Jan 18 '23 at 04:25

0 Answers0