[U-Boot-Users] Why objdump Creates 4G U-Boot Images

U-Booters,
Executive Summary: With this piece of mail, I hope to simply provide some documentation for a problem I've had building U-Boot where the u-boot elf file is made, but the u-boot.bin and u-boot.srec files are not made with objdump due to large file size limitations.
In short, check your floating point code carefully and make sure you are _really_ creating a standalone executable.
Here we go.
Original Problem:
The u-boot elf file is built, however the u-boot.bin and u-boot.srec images are not created. On my system, objdump dies complaining that it "the file limit is exceeded." In fact, it was trying to create a roughly 4GB file. Cool. I speculated that we were having either an unsigned problem, a sign-bit problem or an endian issue and were somehow rolling a full 32-bit address space.
I isolated the problem by locating a working 3.3.2 with binutils 2.15 toolchain from Metrowerks(!) for my board. This was an x86 to PPC cross compiling environment.
My non-working toolchain was GCC 3.4.3 with binutils 2.15 on a PPC box, not really cross compiling to PPC.
I managed to find a 3.4.3 cross compiling environment as well, and could show that the objdump worked there on the elf image created by 3.3.2. Oh yeah.
Inspecting the "readelf -a" output from the working and non-working elf images showed this critical difference:
Working:
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000078 0xfe000000 0xfe000000 0x277b0 0x2c5fc RWE 0x8
Section to Segment mapping: Segment Sections... 00 .text .reloc .data .data.rel.local .data.rel .u_boot_cmd .bss
Not Working:
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000098 0x000002b0 0x000002b0 0x00010 0x00010 R 0x8 LOAD 0x0000a8 0xfe000000 0xfe000000 0x257bc 0x2a5fc RWE 0x8 STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
Section to Segment mapping: Segment Sections... 00 .rodata.cst8 01 .text .reloc .data .data.rel .data.rel.local .u_boot_cmd .bss 02
Now it was clear: The two LOAD sections in the non-working image were conspiring to place data at address 0x2b0 and at 0xfe000000, thus producing an image with an address space roughly 4G large. An srec file, with an expansion factor of about 2.5 ~ 3 per byte was trying to make a 10GB file or so. Oh yeah. I can see why Linux would want to kill -9 that large objdump file process dead....
So, where'd the 0x2b0 come from? Turns out this section:
Section Headers: [22] .rodata.cst8 PROGBITS 000002b0 000098 000010 08 AM 0 0 8
And what causes .rodata.cst8 sections? Google suggested it was a floating point intrinsic, and peering at the u-boot.map confirmed:
.rodata.cst8 0x00000000000002b0 0x10 .rodata.cst8 0x00000000000002b0 0x10 /usr/lib/gcc-lib/ppc64-yellowdog-linux/3.3.3/libgcc.a(_fixunsdfsi.oS)
Interesting. It came from libgcc and was called _fixunsdfsi. And, more grepping and nm'ing yielded a file (speed.c) in our board port that did this:
core_clk = 1.5 * csb_clk;
On a hunch, we converted that to this:
core_clk = (3 * csb_clk) / 2;
Which suddenly worked splendidly! Bad floating point. Bad.
OK, so why did _fixunsdfsi get introduced in the first place?
Poking around showed that this symbol should have been resolved with the -msoft-float and the "nof", no-floating-point form of the libraries. How come they didn't use the nof form of the libs?
And, the last piece of the puzzle, the load line on u-boot itself at the very end of the main Makefile shows this:
u-boot: depend $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT) UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*(__u_boot_cmd_.*)/-u\1/p'|sort|uniq`;\ $(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) \ --start-group $(LIBS) $(PLATFORM_LIBS) --end-group \ -Map u-boot.map -o u-boot
where the last $(LD) is the important line, and the symbol
PLATFORM_LIBS += --no-warn-mismatch -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
is the key factor. The call to $(CC) requesting the name of the libgcc library file name _should_ in the case of using the -msoft-float option, produce the "nof" form of the library. Our tool chain was _not_ doing that. It was supplying the same non-nof library regardless of the -msoft-float option.
So, lesson one: If you are using soft-float, make sure your toolchain has the "nof" multilib'ed into the build properly.
Lesson two: If you want to multiply by 1.5, instead multiply by 3 and divide by 2. :-)
Finally, lesson three: In addition to (un)signed problems, sign-bit issues and endian problems, another cause for very large (~4G) files is floating point. As we've all known for a very long time now, floating point numbers are a pain and should be avoided.
There are margaritas at home with my name all over them.
jdl

Dear Jon,
in message 1106259987.18076.43.camel@cashmere.sps.mot.com you wrote:
Executive Summary:
Ummm... there's only engineers around here ;-)
...
There are margaritas at home with my name all over them.
Thanks for the "funny" story, and enjoy your margaritas.
Best regards,
Wolfgang Denk
participants (2)
-
Jon Loeliger
-
Wolfgang Denk