Relocation truncated to R_X86_64_32S (Solved)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
blacky
Posts: 20
Joined: Mon Apr 06, 2015 3:59 am

Relocation truncated to R_X86_64_32S (Solved)

Post by blacky »

Hey guys,

My current OS state is that I am able to jump to Longmode. Recently, I have encountered the following issue:
The first thing I am doing after initializing Longmode is the allocation of a stack. The issue is that when I try to load the stack address into the rsp register, the linker complains about that start address of the stack needs to be relocated (for whatever reason) and truncated: "relocation truncated to fit: R_X86_64_32S against `.kstack'".

Here is the code in question:
To compile this code I use the "large" memory model (-mcmodel=large).

Code: Select all

.intel_syntax noprefix                                                                                                                                                                                          
.code64                                                                                                                                                                                                         
                                                                                                                                                                                                                 
                                                                                                                                                                                      
.section .kstack, "aw", @nobits                                                                                                                          
 kstack_bottom:                                                                                                                                                                                                  
     .skip 16384                                                                                                                                                                                                 
 kstack_top:                                                                                                                                                                                                     
                                                                                                                                                                                                                 
                                                                                                                                                                                                                 
 .section .text                                                                                                                                                                                                  
 .align 8                                                                                                                                                                                                        
                                                                                                                                                                                                                 
     .globl _entry                                                                                                                                                                                               
     .type _entry, @function                                                                                                                                                                                     
                                                                                                                                                                                                                 
 _entry:                                                                                                                                                                                                         
     cli                                                                                                                                                                                                         
     lea rsp, kstack_top                                                                                                                                                    
     call k_early_init                                                                                                                                                                                           
                                                                                                                                                                                                                 
 .halt:                                                                                                                                                                                                          
     cli                                                                                                                                                                                                         
     hlt                                                                                                                                                                                                         
     jmp .halt        

The section .kstack is linked into the .bss section by my linker script:

Code: Select all

.bss ALIGN(0x10) : AT(ADDR(.bss) - KERNEL_BASE)                                                                                                                                                             
{                                                                                                                                                                                                           
    PROVIDE (_sbss = .);     
                
    *(COMMON)                                                                                                                                                                                               
    *(.bss)   
    *(.gnu.linkonce.b*)        
    *(.kstack)       
           
    PROVIDE (_ebss = .);     
}
As always: any help would be appreciated :)
Last edited by blacky on Thu May 14, 2015 2:23 pm, edited 1 time in total.
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: Relocation truncated to R_X86_64_32S

Post by Octocontrabass »

blacky wrote:"relocation truncated to fit: R_X86_64_32S against `.kstack'"
You are using an addressing mode that can only fit a sign-extended 32-bit value, but the symbol you are trying to put in it can't be represented as a sign-extended 32-bit value.
blacky wrote:To compile this code I use the "large" memory model (-mcmodel=large).
That only applies to code generated by the C (or other language) compiler, not code written by you.

Code: Select all

     lea rsp, kstack_top
Hmm... :wink:
blacky
Posts: 20
Joined: Mon Apr 06, 2015 3:59 am

Re: Relocation truncated to R_X86_64_32S

Post by blacky »

Thank you so much for you fast reply :)
You are using an addressing mode that can only fit a sign-extended 32-bit value, but the symbol you are trying to put in it can't be represented as a sign-extended 32-bit value.
Hmm, I see what you mean... However I cannot find an appropriate instruction that is able to load the 64-bit address into a register. I actually thought that the instruction LEA(Q) would be capable of storing the address of the symbol "kstack_top". (The intel spec as well states that the LEA instruction should be able to do that - as far as I have understood it correctly). The same applies to the instruction MOV as well...

I am missing something: Could you provide me with another hint, please? :)

Thanks in advance.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Relocation truncated to R_X86_64_32S

Post by Combuster »

The 64-bit instruction set is written with the assumption that binaries are less than 2GB - which you'll have to go to great lengths to find an exception to. The fact that you use absolute addressing also means you're limiting yourself to the top or bottom 2GB.

Remember that

Code: Select all

LEA REG, [label]
is equivalent to

Code: Select all

MOV REG, label
and that the opposite of absolute addressing is ........ addressing :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
blacky
Posts: 20
Joined: Mon Apr 06, 2015 3:59 am

Re: Relocation truncated to R_X86_64_32S

Post by blacky »

Interesting: As soon as you stop screwing up, it actually works!
Thanks again for your help :)

To make it work, as you said, I simply mapped the kernel to the upper 2GB ... that was it. I believe this is something I will never forget...
What I am actually interested in right now is to understand the reason for this addressing limitation. I will try to dig more into that.

Besides defining absolute addresses, is there actually another possibility to reserve space for something like a stack or is it always handled like that that these kind of data structures simply need to be allocated in special (limited) memory address ranges?
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: Relocation truncated to R_X86_64_32S (Solved)

Post by Octocontrabass »

blacky wrote:What I am actually interested in right now is to understand the reason for this addressing limitation.
Most of the time, you can fit your statically allocated code and data in under 2GiB of address space. The AMD64 designers took this into account, and made the instruction set more flexible and efficient when static addresses can fit into 32 bits.

GCC supports different memory models in order to optimize its use of those 32-bit symbols. The "large" memory model allows symbols to be anywhere, but the generated code will be larger and slower. The "small" (or "kernel") memory models assume symbols will be in the lowest (or highest) 2GiB, so the generated code is smaller.
blacky wrote:Besides defining absolute addresses, is there actually another possibility to reserve space for something like a stack or is it always handled like that that these kind of data structures simply need to be allocated in special (limited) memory address ranges?
This is a limitation of the code you wrote. Had you used the appropriate instructions for loading a 64-bit symbol, the linker would have resolved it with no complaints.
Post Reply