bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: BUG elf32-i386 R_386_PC32 done wrong


From: doctor electron
Subject: Re: BUG elf32-i386 R_386_PC32 done wrong
Date: Fri, 23 Jun 2006 17:28:35 -0500

Long, long ago, Ian Lance Taylor, a life form in far off space,
emitted:

>doctor electron <address@hidden> writes:
>
>> As author of the HotBasic compiler for Windows, in porting same
>> to Linux, I find that ld does not properly link relative
>> relocations (R_386_PC32) in correct elf32-i386 .o files.
>
>GNU ld is correct according to the ELF ABI Processor Supplement for
>i386 Processors.

Thank you for your reply, Ian.  The first smoking gun was
described in my first email:  ld overshoots the target for rel
relocs within module by 4 bytes.  This is undeniably a linker
failure.  The processor adds the value in the rel relocated
address to eip ... and, period; that's it.  ld does not know how
i386 and essentially all other microprocessors work.  There is
no other credible explanation.

>In typical use, the .o file will contain a 0xfffffffc in the four
>bytes affected by R_386_PC32.

Yes, this is what I predicted in my previous email and found in
files such as acquirew.o; and which you now admit -- that all .o
and .so files have to have a -4 fudge factor placed in such
locations by compilers since ld knows not how to do rel relocs.

If not fixed, the ld manual should, I think, "come clean" on
this an state plainly that ld fails on rel relocs since it
requires object files to contain a fudge factor to prevent this
failure.

The one and only formula for rel relocs is:

S - (A + 4)

where S is the symbol address and A is the location to be
relocated relatively (the 4 byte field after E8 for example).
Notice that the contents of that E8 field in the
.obj or .o is irrelevant, it should be overwritten.

[This is why it looks ridiculous (!) to see -4 in these
locations in existing linux .o and .so files -- really looks
like people have no idea what they are doing -- KeyStone Cops.
I would like to be an advocate/promoter of Linux, but this, my
friend, is totally second-class.]  

All the compiler has to do is allocate a 4-byte field with *any*
value in the .obj or .o file and make an entry for it in the rel
reloc table.  The linker should *never* read the value in this
rel reloc address; rather it should put the correct offset in
it.

This table contains entries of three values and the third is a
code that the entry is absolute or relative relocation.  So we
are down to two values, which are precisely the S and A values
above.  For each module in the link, both values are referenced
to the beginning of the .text (code) section -- 0.  Thus, if a
linker is concatenating .text sections from multiple modules
(aligned 16 as we have seen), the "0" address for both S and A
needs to be adjusted (but only when S and A are in different
modules originally).  Anyway, once you have the right S and A
values, the formula above is applied and the result is stored at
the A address.  And you know why the formula works -- it is the
way the processors work -- purely hardware related.

Knowledge of how microprocessors work (re adding the offset to
eip) goes back the beginning of the very first microprocessors
of any kind.  This is why it is amazing that *both* compiler
writers and linker writers in linux seem to be completely
uninformed about how the processors they use work, even in their
best known and simplest aspects.  Anyone who sees those -4's in
existing .o and .so files cannot conclude anything other than
"this Linux is bound together with rubber bands."

SUMMARY:  The two S and A values in the rel reloc table entries
are the only thing needed to write the relocs into the
executable.

So I humbly ask again:  Where is this code, so e might best find
this code in ld, rewrite it correctly, and then ld would link
all i386 formats, for both good and existing (contain the -4
gibberish) input files.

This code might be buried in some include or bfd (?) module
called by ld, but whatever it is, it seems to be feasible to do
a completely general and complete fix to the benefit of all
linux users.  Since a rel-reloc-fixed ld would not read the -4
values, it would work both for good and fudge-factored (existing
Linux) input files.

As it is, this ld failure prevents porting valid object files
into a Linux environment.  Surely, Linux people do not intend to
say, "Do not enter here", to the public looking at Linux.

>R_386_PC32 is defined to add the PC relative offset from the start of the 4 
>byte field
>to the existing contents of the 4 byte field.

Above is wrong.  What could possibly be the "trial and error"
origin of this definition?  [Scenario:  In early days of ld and
linux-based compilers, someone found that a program ran it -4
was stuck in the object file.  If this is true:  This is "design
by random trial and error"; why not use the real definition of
rel relocs?

Your statement is a crystal clear acknowledgment that ld is
wrong.  Thank you.

I rest my case.  The correct definition, I give above.  Let's
fix it!

Then, gee whiz!  People could bring compilers like mine to Linux
-- compilers that produce correct object files, and use to link
them.  That would sort of open the doors of Linux to the wider
world of computing; no telling the benefits to Linux if
outsiders could get in.

Warm greetings, j





reply via email to

[Prev in Thread] Current Thread [Next in Thread]