BinaryBurst
BinaryBurst

Reputation: 139

How can I allocate more than 2GB of memory in gas assembler?

I have a 64bit OS and I am building a 64bit program that uses rip-relative addressing. My problem is that I cannot allocate using .lcomm directive more than 2GB of data. Is there a way to allocate more than 2GB in gas or do I have to use a different directive?

.lcomm array,2*1024*1024*1024 
#>=2GB doesn't work
#error:additional relocation overflows omitted from the output

Upvotes: 0

Views: 339

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 364593

RIP-relative displacements are signed 32-bit. The default code model is "small", where all static code/data is in the low 2GB of virtual address space, so a RIP-relative addressing mode or a rel32 branch / call can reach any symbol from anywhere. (Or for small PIC, everything is within 2GB at most but you let ASLR put it anywhere in memory.)

Check the x86-64 System V ABI for how to use code models other than the default "small". Where is the x86-64 System V ABI documented?.


If it's only just this one giant array, you should probably use some kind of linker script or something to arrange for it to be the only thing that extends outside the low 2G, so everything else can still assume the small code model. i.e. put it at the end of the BSS above everything else, so the array symbol is RIP-relative addressable from code anywhere in the low 2G, along with all other labels.

But the end of the array can be out of reach without causing a problem, because you get the base address into a register and index it. You'll only get a linker error if you write something like array[1ULL<<32] = 1; in C and the compiler is using the small code model so it will emit asm like movb $1, array+1<<32 (%rip) which of course won't work.

Upvotes: 1

Related Questions