I obtained a generic linker script using "ld --verbose test.o" and simply added a memory section. From what I understand this should work fine, but no matter how I setup the memory section the resulting program never functions properly. (ld generated linker script can be found here).
tl;dr; How do you use MEMORY{...} correctly in GNU ld linker scripts?
Test program (sum the elements of an array):
#include <stdio.h>
#include <stdint.h>
uint32_t array[1024];
uint32_t sumArray(uint32_t *arr, size_t size)
{
size_t i;
uint32_t sum=0;
for(i=0; i<size; i++){
sum += arr[i];
}
return sum;
}
int main()
{
uint32_t sum;
int i;
for (i=0; i<1024; i++) array[i] = 1;
sum = sumArray(array,1024);
printf("%d\n", sum);
return 0;
}
If I compile this (gcc -c test.c) then link the .o file via:
ld --no-add-needed --build-id -m elf_i386 --hash-style=gnu -static -o test /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i686-redhat-linux/4.4.4/crtbeginT.o -L/usr/lib/gcc/i686-redhat-linux/4.4.4 -L/usr/lib/gcc/i686-redhat-linux/4.4.4 -L/usr/lib test.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/i686-redhat-linux/4.4.4/crtend.o /usr/lib/crtn.o -T ld.script -lc
Things work fine.
But when I modify the linker script to include a memory section (I've tried many different memory declarations, this is just an example):
MEMORY
{
lowMem (wx) : o = 0x0, l = 2048M
allocMem (ax) : o = 0x80000000, l = 1024M
}
The process segfaults, gdb reports:
Program received signal SIGSEGV, Segmentation fault.
0x0000092f in __pthread_initialize_minimal ()
Yes, that's an awfully low link address for pthread, but even changing the memory declaration to something like:
lowMem (wx) : o = 0x08000000, l = 32M
Doesn't seem to help - the pthread address is now somewhere normal, but the process still segfaults at this new, higher, address.
Example disassembly of __pthread_initialize_minimal:
0x08000900 <+0>: push %ebp
0x08000901 <+1>: mov %esp,%ebp
0x08000903 <+3>: push %edi
0x08000904 <+4>: push %esi
0x08000905 <+5>: push %ebx
0x08000906 <+6>: sub $0x4c,%esp
0x08000909 <+9>: mov 0x808d07c,%eax
0x0800090e <+14>: test %eax,%eax
0x08000910 <+16>: je 0x8000970 <__pthread_initialize_minimal+112>
0x08000912 <+18>: mov 0x808d0a0,%edx
0x08000918 <+24>: shl $0x5,%edx
0x0800091b <+27>: lea (%eax,%edx,1),%edx
0x0800091e <+30>: cmp %edx,%eax
0x08000920 <+32>: jb 0x800092f <__pthread_initialize_minimal+47>
0x08000922 <+34>: jmp 0x8000970 <__pthread_initialize_minimal+112>
0x08000924 <+36>: nopl 0x0(%eax)
0x08000928 <+40>: add $0x20,%eax
0x0800092b <+43>: cmp %edx,%eax
0x0800092d <+45>: jae 0x8000970 <__pthread_initialize_minimal+112>
=> 0x0800092f <+47>: cmpl $0x7,(%eax)
and yes, EAX is pointing out of the memory area... but why?
(gdb) info registers
eax 0x7fff034 134213684