openhwgroup / corev-binutils-gdb

GNU General Public License v2.0
9 stars 26 forks source link

a possible issue in relaxing call to zcmt instruction #48

Closed JoshCafe closed 1 year ago

JoshCafe commented 1 year ago

hi,

https://github.com/openhwgroup/corev-binutils-gdb/blob/development/bfd/elfnn-riscv.c

For R_RISCV_CALL and R_RISCV_CALL_PLT, in relax_pass 0 and relax_trip 2 of _bfd_riscv_relax_section, if benifical the auipc is replaced by zcmt instruction in _bfd_riscv_table_jump_mark.

But in relax_pass 1 of _bfd_riscv_relax_call, it seems the marked instruction fails to be relaxed to a zcmt insntruction if auipc+jalr could not be shortened to jal or jalr(near zero) due to the following condition check:

  /* See if this function call can be shortened.  */
  if (!VALID_JTYPE_IMM (foff) && !(!bfd_link_pic (link_info) && near_zero)
      && link_info->relax_pass != 0)
    return true;

Seems we need to move the following codes to the top of function to avoid being blocked by the condition above.

  /* Relax a table jump instruction that is marked. */
  if (link_info->relax_pass == 1
    && ((auipc ^ MATCH_TABLE_JUMP) & MASK_CM_JALT) == 0)
    {
      rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_TABLE_JUMP);
      *again = true;
      return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 6, link_info, pcgp_relocs);
    }

BR Joshcafe

linsinan1995 commented 1 year ago

It is truly a problem. Thanks for pointing this out. @jeremybennett @pz9115

jeremybennett commented 1 year ago

This is now fixed.