Page 1 of 1
Using LD to output a flat binary?
Posted: Fri Nov 07, 2008 7:56 pm
by lollynoob
Hello, I've been working on a bootloader, and have recently run into trouble getting my linker (LD from binutils-2.16 targeting i386-elf, compiled in Cygwin) to output a flat binary correctly. I've tried various scripts I found while searching google, as well as a few I wrote myself after reading the documentation from the LD manpages; however, in the cases where the script works and produces a binary file, my dispstr() function (similar to puts() ) doesn't work. When I disassemble the binary file it appears that the string pointer passed to the function is an address somewhere above 0x8048000, which is LD's default virtual address (I think). So basically, I'm not sure what exactly is messing up; if anyone's had this problem before, or can offer any advice, it'd be greatly appreciated.
Re: Using LD to output a flat binary?
Posted: Fri Nov 07, 2008 9:39 pm
by Troy Martin
Hmm, I'm not sure. You mind posting your most successful script for us so we can check it out?
Re: Using LD to output a flat binary?
Posted: Fri Nov 07, 2008 9:42 pm
by 01000101
Below is pretty much the 'defacto' standard for a minimal linker script for flat binaries. It will link everything to 0x10000. In your linkers did you ever include the *(.rodata) placement section? Also, could you give more specifics on what you are using to compile the code with (using just n/f/m/y/tasm/gcc/etc...) and could you post the compilation script/makefile.
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00010000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
Re: Using LD to output a flat binary?
Posted: Fri Nov 07, 2008 10:11 pm
by lollynoob
Well, the linker script posted worked just as well as the others, so that would be the most successful script; here's my makefile (I'm using MinGW's make tool, if you're wondering about the backwards slashes in the file paths)
Code: Select all
L = i386-elf-ld
LF = -T link -nostdlib -nostartfiles -nodefaultlibs
A = nasm
AF = -f bin
AE = -f elf
C = i386-elf-gcc
CF = --freestanding -fstrength-reduce -fomit-frame-pointer -finline-functions -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -Wall -Werror -O0 -Iinc
all: bin\image.bin
bin\image.bin: bin\boot.bin
imgtool bin\image.bin bin\boot.bin image 1440k
bin\boot.bin: bin\aboot.bin bin\cboot.bin
copy /b bin\aboot.bin + bin\cboot.bin bin\boot.bin
bin\aboot.bin: boot.asm
$(A) $(AF) -o bin\aboot.bin boot.asm
bin\cboot.bin: bin\stub.o bin\boot.o
$(L) $(LF) -o bin\cboot.bin bin\stub.o bin\boot.o
bin\stub.o: stub.asm
$(A) $(AE) -o bin\stub.o stub.asm
bin\boot.o: boot.c
$(C) $(CF) -o bin\boot.o boot.c
You know, I'm actually not sure what every one of those GCC flags does; if any are redundant or possibly problematic, let me know and I'll rebuild everything without them and see if that fixes it.
EDIT: In case you're wondering, imgtool is a utility I wrote to make disk images, and all of this is a single-stage bootloader intended to be loaded from the first few sectors of the disk.
EDIT: I looked up what each of those flags does, and removed all the optimization-related ones, and it's still giving me weird addresses for strings (even when I declare them outside of the main function). I'm thinking it's something to do with .rodata having a weird virtual address, but the linker script posted has no indication of that being done. Still don't know exactly what's messing up.
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 1:52 pm
by dosfan
Perhaps it isn't actually using the linker script? Try passing the following to LD:
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 6:05 pm
by lollynoob
Just tried that and had the same result; the code links fine, but string addresses are way off. Also I tried compiling a later version of binutils (2.18) and using it instead made no difference. Maybe it's due to binutils' target (i386-elf); a while ago when I was targeting i386-aout things were working fine (granted, the code was somewhat different, but it was still outputting a flat binary in the same manner).
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 6:51 pm
by CodeCat
Does including a .bss section really have any effect? AFAIK it needs file headers to be correctly initialised, which of course a flat binary lacks. So the effect is the same as if it hadn't been included at all.
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 6:55 pm
by lollynoob
I was under the impression that the linker would just zero out a section of the binary and use that for the uninitialized data; I could be wrong though.
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 6:57 pm
by CodeCat
No, the .bss section is normally initialised with zeroes only when loaded. The idea is that since it's not initialised anyway, there's no point in wasting space in the binary.
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 7:00 pm
by lollynoob
But if space outside of the binary is used for data, and there is no formatting in the binary to tell where this space is, wouldn't that cause undefined behavior due to the fact that there's no way to tell how much memory is being used beyond the end of the actual file?
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 7:24 pm
by CodeCat
That was my point in my first post.
Re: Using LD to output a flat binary?
Posted: Sun Nov 09, 2008 7:27 pm
by lollynoob
What I was saying is that it's included in the binary as zeroes because of that. It wouldn't make sense to support flat binary output if such output would have unpredictable results from writing to unspecified memory locations.
EDIT: Could we get back on-topic? As far as I know, strings are in .rodata, not .bss.
Re: Using LD to output a flat binary?
Posted: Fri Nov 14, 2008 9:04 pm
by lollynoob
Yes, I'm bumping, but i've also got some new information regarding my problem. After simplifying my build setup to just compile one .c file to one .o file, then link that .o file to a flat binary, I ran across this warning:
Code: Select all
/usr/cross/lib/gcc/i386-elf/4.2.0/../../../../i386-elf/bin/ld: warning: cannot find entry symbol _start; defaulting to 08048054
Now in the LD man page, it specifies that if start or _start aren't found, and no other start address is specified, the start address defaults to 0, so I'm not sure why it's doing this. What makes this interesting is that this start address is very close to my strange string addresses; it's almost as if whether I specify a start address or not, it silently sets it to 08048054 and links everything to that address. Does anyone know of what might be causing this problem, or how to fix it?