This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

MIPS md_apply_fix()(?) problem.


So, I ran across a rather serious problem, which i believe is caused
by Richard S's change:

2001-08-03  Richard Sandiford  <rsandifo@redhat.com>

        * config/tc-mips.c (md_apply_fix): Don't subtract the symbol value
        from GPREL addends.

The test case below assembles incorrectly with that change.  (If you
read the test, you end up thinking "WTF?!?!?!" that's unrelated!!!
but read on!  FYI, this test case is distilled from assembly code
generated compiling a mips linux kernel w/ gcc 3.0.1.)

Assemble it with mips-{elf,linux}-as -o foo.o foo.s; it's that easy.  8-)

Before that change, you get:

   0:   3c050000        lui     a1,0x0
                        0: R_MIPS_HI16  boot_mem_map
   4:   00b12821        addu    a1,a1,s1
   8:   8ca5000c        lw      a1,12(a1)
                        8: R_MIPS_LO16  boot_mem_map
   c:   00000000        nop

After you get:

   0:   3c050000        lui     a1,0x0
                        0: R_MIPS_HI16  boot_mem_map
   4:   00b12821        addu    a1,a1,s1
   8:   8ca50010        lw      a1,16(a1)
                        8: R_MIPS_LO16  boot_mem_map
   c:   00000000        nop

Note the 12 -> 16 you get in the instruction @ 0x8.  This is the
offset of "boot_mem_map" in .bss in the object file produced by
assembling this source.  (If you then go on to final link, it still
produces a value off by the same offset, in this example 4.)


I went back and debugged this in the 08-03 sources, and what I found
is described below.  I don't get all of the way frags and relocs are
handled, so some of this may be ... way wrong, but please bear with
me.  8-)

What I believe is happening here is that code code is generated by the
"ld_st" code in tc-mips.c, which generates, from the comment:

             If we have a base register, and this is a reference to a
             GP relative symbol, we want
               addu     $tempreg,$breg,$gp
               <op>     $treg,<sym>($tempreg)   (BFD_RELOC_MIPS_GPREL)
             Otherwise we want
               lui      $tempreg,<sym>          (BFD_RELOC_HI16_S)
               addu     $tempreg,$tempreg,$breg
               <op>     $treg,<sym>($tempreg)   (BFD_RELOC_LO16)

This is set up via a rs_machine_dependent/RELAX_ENCODEd frag_var().

Anyway, md_estimate_size_before_relax says "take the second option",
and md_convert_frag frobs the instructions.

However, when md_apply_fix and tc_gen_reloc are invoked, the 'fixp'
they're given is still of type BFD_RELOC_GPREL16.  (I don't understand
how/if the operations on it touch the 'right' address, but I think
they somehow do.  anyway...)

>From looking at the code, it looks like the relocs won't be emitted
for code in the variant frags.  and, in the case of the RELAX_ENCODE /
md_convert_frag handling, even if they were generated that
md_convert_frag doesn't try to discard relocs for the discarded code,
and instead use the ones for the replacement code.

So, all of this leads me to believe that the _only_ time you can
use the RELAX_ENCODE magic is when the two types of relocs in the
different parts of the variant frag are handled 'the same'.  In this
case (and in many others throughout the tc-mips.c!!!) since GPREL and
LO16 relocs are no longer treated the same, the RELAX_ENCODE magic
doesn't work properly.

I have _no_ idea how the reloc on the lui is supposed to be handled
properly (is handled properly, it seems), but it definitely looks like
the LO16 reloc is being treated like a GPREL instead...


Thoughts?  "HELP!!!!"


chris
===
	.text

        .ent    fn				# unneeded
        .type   fn,@function			# unneeded
fn:						# unneeded
        lw      $5,boot_mem_map+12($17)
	.end	fn				# unneeded

        .data
        .align  2

spacer:   
        .space  4


        .globl  boot_mem_map
boot_mem_map:   
        .space  4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]