Mips target in gold - revision 3 - part 2

Sasa Stankovic Sasa.Stankovic@imgtec.com
Tue Apr 15 13:53:00 GMT 2014


Hi Cary,

Attached is the second part of the patch that implements Mips target in gold. This part contains second part of the mips.cc file.

> >             // In some cases GCC dead code elimination removes the LO16 but
> >             // keeps the corresponding HI16.  This is strictly speaking a
> >             // violation of the ABI but not immediately harmful.
>
> If I understand the code correctly, in this case the HI16 reloc
> will remain on the got16_addends_ list forever. Is there a point
> where you know it's safe to remove it? Can you clear the list
> at the end of each section?

If LO16 is removed by GCC, than HI16 reloc is paired with the next found LO16
reloc (this means that two or more HI16 reloc will be paired with a single LO16 reloc).
This is what GNU ld does - it always tries to find LO16 reloc for HI16 reloc, and if it
can't find it, error is reported.

When trying to find LO16 reloc, GNU ld examines next relocations in the section until
it finds it, or reports an error.  I implemented it differently in Gold - when HI16 or GOT16
reloc is found, it is recorded in the got16_addends_ list, and the normal scaning of
relocations continues.  Then when the LO16 reloc is found, the got16_addends_ list is
examined and all pending matching HI16 and GOT16 relocs are removed.  The error when
HI16 or GOT16 reloc doesn't have the LO16 part is detected by checking whether the
section of the pending HI16 or GOT16 relocation is different from the section of the current
LO16 relocation. The check whether the final section that is scanned has HI16 or GOT16
without the LO16 part is in the do_finalize_sections method - I just check whether the
got16_addends_ list is empty - if it isn't, error is reported. 

> >   //gold_assert(static_cast<section_size_type>(pov - oview) == oview_size);
>
> Was this commented out while debugging? If you can't leave it
> enabled, please add a TODO noting what the problem is. At the
> least, you should make sure you didn't overrun the oview, and if
> you underran it, you should fill with zeroes.

I enabled it again.

> >   typename std::list<got16_addend<size, big_endian> > got16_addends_;
>
> Do you realy want to use a linked list here? Wouldn't a
> vector be better?

I used std::list because erase is called on it.

> >       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
> >                                       (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE |
> >                                       elfcpp::SHF_MIPS_GPREL),
> >                                       this->got_, ORDER_DATA, false);
> > ...
> >       // If there is no .got section, gp should be based on .sdata.
> >       // TODO(sasa): If there are both .got and .sdata sections, they must be
> >       // together, with .got comming first.
>
> If you want .got and .sdata together, shouldn't you define .got
> with ORDER_SMALL_DATA? (To guarantee that it precedes .sdata, you
> may need to add ORDER_SMALL_DATA_FIRST to layout.h.)

I removed this TODO and added a new TODO to check whether .sdata is accessed
using gp-relative addressing.  This was the case for older MIPS architectures
which accessed both .got and .sdata section using gp-relative addressing (so that
items from the .sdata were read/written using just one instruction instead of
two).  But I think that modern Mips Linux ELF architectures don't access .sdata
using gp-relative addressing.  So the code that initializes gp to point on
.sdata if there is no .got will probably be removed in the future.

> >   //   big-endian file, the result is the same; in a little-endian
> >   //   file, the two 16-bit halves of the 32 bit value are swapped.>
> Do you mean that the bytes within each are swapped, but the
> 16-bit words are stored in order, or that the 16-bit words are
> swapped (i.e., the second written before the first)? I'm guessing
> that you mean that the byte-swapping takes place within each
> 16-bit word, and the order of the two words is unaffected.

Yes. On MIPS16 and microMIPS (whose instruction sets have both 16-bit and 32-bit
instructions) [31:16] part of the instruction is always stored first, and [15:0] is stored after;
bytes within each 16-bit word are swapped based on endianess.

> >   //   To put it in MIPS ABI terms, the relocation field is T-targ26-16,
> >   //   defined as
> >   //
> >   //   big-endian:
> >   //   +-------- +----------------------+
> >   //   |           |                       |
> >   //   |           |    targ26-16      |
> >   //   |31    26|25                   0|
> >   //   +-------- +----------------------+
> >   //
> >   //   little-endian:
> >   //   +----------+------+-------------+
> >   //   |            |        |                |
> >   //   |  sub1   |        |     sub2    |
> >   //   |0        9|10  15|16         31|
> >   //   +----------+--------------------+
> >   //   where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
> >   //   ((sub1 << 16) | sub2)).
>
> I can't figure out what this diagram is saying. In particular,
> why are the bits numbered right-to-left for big endian and
> left-to-right for little endian? Most processors I'm familiar
> with use the same bit numbering convention for both big- and
> little-endian, but I certainly wouldn't expect to see this.

That whole comment (and many others) is copied from the GNU ld (file bfd/elfxx-mips.c).
32-bit JAL and JALX instructions on MIPS16 have the format

   +--------------+--------------------------------+-----------
   |     JALX   | X|   Imm 20:16  |   Imm 25:21  |
   +--------------+--------------------------------+-----------
   |                Immediate  15:0                       |
   +-----------------------------------------------+------------

First row represents the bits [31:16], second row represents the bits [15:0]. Note that two
5-bit immediates in the first word are swapped.

When producing a relocatable object file (either by gas or by giving -r option to linker),
JAL(X) MIPS16 instruction is stored like its MIPS32 equivalent:

   +--------------+----------------------------------------+
   |     JAL(X) |           Immediate 25:0        |
   +--------------+----------------------------------------+

So basically, 3 immediates are first reordered into full 26-bit target of the JAL instruction,
and then the instruction is stored as two 16-bit parts (like all the other 32-bit instructions on
MIPS16 and microMIPS). This means that in the little-endian picture from your question,
sub1 represents Imm[25:16] and sub2 represents Imm[15:0] (I agree that bit numbering on
the little-endian picture is confusing).

Note that this only applies for relocatable files. For final link, the JAL(X) instruction is stored
based on the instruction format (with bits [31:16] always stored first). MIPS16 JAL(X) instruction
is the only instruction whose layout differs in relocatable and executable files.

Regards,
Sasa
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mips3.patch
Type: text/x-patch
Size: 196095 bytes
Desc: mips3.patch
URL: <https://sourceware.org/pipermail/binutils/attachments/20140415/f692cc68/attachment.bin>


More information about the Binutils mailing list