OSDN Git Service

Whee. What a most entertaining bug.
authorDavid McCullough <davidm@snapgear.com>
Mon, 3 Apr 2006 00:06:38 +0000 (00:06 +0000)
committerDavid McCullough <davidm@snapgear.com>
Mon, 3 Apr 2006 00:06:38 +0000 (00:06 +0000)
For some (unfathomable) reason, the flat loader in the kernel likes to
use network (big endian) byte order, but only sometimes.  In particular,
its assumptions about relocation byte order depend on whether the
executable uses ID shared libraries or not.

It took me most of today to figure out why the kernel was trying to
relocate something at address 0x94160000, until I noticed that that's
the byteswapped version of 0x1694, and further noticed that it was
omitting a byteswap due to the flag Has-PIC-GOT in the flat header.

So, why is that flag set?  After all, opreport wasn't compiled with
-mid-shared-library or anything.

It turns out that elf2flt sets that flag if grepping the executable for
GLOBAL_OFFSET_TABLE succeeds.  That's a reasonable thing to do, except
when we link an executable against libbfd.a - which contains
GLOBAL_OFFSET_TABLE not as a symbol, but as a string, as it needs to
produce the symbol in linker output files.

Changing elf2flt to grep nm output, rather than the executable directly,
fixes the problem.  So, in the end it turns out this wasn't related to
the 20030928 failure at all...

Bernd Schmidt <bernds_cb1@t-online.de>

ld-elf2flt.in

index 613dcbf..778ea0d 100644 (file)
@@ -14,6 +14,7 @@
 
 LINKER="$0.real"            # the original renamed-linker
 ELF2FLT="`expr $0 : '\(.*\)ld'`elf2flt"
+NM="`expr $0 : '\(.*\)ld'`nm"
 TOOLDIR="`dirname $0`"      # let gcc find the tools for us
 LDSCRIPTPATH="@binutils_ldscript_dir@" # and the scripts
 SHARED_ID=""
@@ -153,7 +154,7 @@ then
                 $LINKER $EMUL $SDIRS -T $LDSCRIPT -o "$OFILE.gdb" "$OFILE.elf2flt"     ||exit $?
                 rm -f "$OFILE.elf2flt"
                fi
-               if grep _GLOBAL_OFFSET_TABLE_ "$OFILE.gdb" > /dev/null 
+               if $NM "$OFILE.gdb" | grep _GLOBAL_OFFSET_TABLE_ > /dev/null 
                then
                        $ELF2FLT $FLTFLAGS -o "$OFILE" -p "$OFILE.gdb" "$OFILE.elf" || exit $?
                else