I am writing an Forth Interpreter in i386 Assembly. Some data needs to be initialized at the start, and then re-initialized later as part of an error recovery process.
I followed the Linker Script guidance in https://sourceware.org/binutils/docs/ld/Scripts.html, but it doesn't seem to work as described. Specifically, section 3.6.8.2 talks about using the AT feature and the need for some initialization code to copy the initialized data. However, when I run my program, the data appears to be initialized already (without the copy), so I don't know how to re-initialize it.
I've reproduced the problem with the following...
I have an assembly program in my.S
:
.text
_start:
cld
mov $_etext,%esi
mov $_data,%edi
mov $_edata,%ecx
sub %edi,%ecx
rep movsb
mov (the_answer),%eax
mov $1,%ebx
int $0x80
.data
the_answer:
.long 42
In my.x
I have my linker script:
SECTIONS
{
.text 0x08048000 : { *(.text) _etext = . ; }
.mdata 0x80000000 :
AT ( ADDR (.text) + SIZEOF (.text) )
{ _data = . ; *(.data); _edata = . ; }
.bss :
{ _bstart = . ; *(.bss) *(COMMON) ; _bend = . ;}
}
The commands to build the image are:
gcc -g -o my.o my.S -c -m32 -Wa,-agnlsc > my.lst
ld -m elf_i386 -T my.x -Map=my.map my.o -o my
The my.map file shows
.mdata 0x0000000080000000 0x4 load address 0x0000000008048020
That is, the 'runtime' VMA address is 0x80000000, whereas the 'loadtime' LMA is 0x08048020, as expected. From descriptions elsewhere, I expected to execute some code to copy the data from the LMA address to the VMA address at the start of the program, (as shown in the my.S
).
I then run gdb my
and execute:
(gdb) break _start
...
(gdb) run
...
(gdb) x/w 0x8048020
0x8048020: 0
(gdb) x/w 0x80000000
0x80000000: 42
so without executing the copying code, the initialization data appears at the VMA address, but not at the LMA address as described in the manual. This wouldn't matter, except that I need to be able to re-initialize the data at a later time.
User contributions licensed under CC BY-SA 3.0