[PATCH] [BINUTILS] [MICROBLAZE] PIC Data Text Relative

Andrew Sadek andrew.sadek.se@gmail.com
Fri Mar 30 14:07:00 GMT 2018


Hello Michael,

Please find below the patch/ Change Log after fixes.
Regarding the 'adjust-insn-abs-refs' option, I m just waiting for your reply
whether we keep it or generate the correct opcode from gcc.
Thanks.

Change Log:
===============

2018-03-30 Andrew Sadek  <andrew.sadek.se@gmail.com>

    Microblaze Target: PIC data text relative
    * include/elf/microblaze.h (Add 3 new relocations):
'R_MICROBLAZE_TEXTPCREL_64', 'R_MICROBLAZE_TEXTREL_64'
    and 'R_MICROBLAZE_TEXTREL_32_LO' for relax function.
    * bfd/reloc.c (2 new BFD relocations):
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL' +
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL'
    * bfd/bfd-in2.h: Regenerate
    * bfd/libbfd.h: Regenerate
    * bfd/elf32-microblaze.c (Handle new relocs): define 'HOWTO' of 3
new relocs and handle them in both relocate
    and relax functions.
    (microblaze_elf_reloc_type_lookup): add mapping between for new bfd relocs.
    (microblaze_bfd_write_branch_absolute_value_64): replace relative
branch with absolute in case 'adjust_insn_abs_refs' is true
    (microblaze_bfd_revert_base_reg_value_64): revert base register
from r20 to r0 in case 'adjust_insn_abs_refs' is true
    (microblaze_elf_relocate_section): Handle new relocs in case of
elf relocation.
    (microblaze_elf_relax_section): Handle new relocs for elf relaxation.
    * gas/config/tc-microblaze.c (Handle new relocs directives in
assembler): Handle new relocs from compiler output.
    (imm_types): add new imm types for data text relative addressing
'TEXT_OFFSET', 'TEXT_PC_OFFSET'
    (md_convert_frag): conversion for
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL' ,
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL'
    (md_apply_fix): apply fix for 'BFD_RELOC_MICROBLAZE_64_TEXTPCREL'
, 'BFD_RELOC_MICROBLAZE_64_TEXTPCREL'
    (md_estimate_size_before_relax): estimate size for
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL' ,
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL'
    (tc_gen_reloc): generate relocations for
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL' ,
'BFD_RELOC_MICROBLAZE_64_TEXTPCREL'
    Add new linker options for static linking: adjust-insn-abs-refs,
disable-multiple-abs-defs
    * ld/lexsup.c (Add 2 ld options):
    (ld_options): add adjust-insn-abs-refs, disable-multiple-abs-defs
@ 'ld_options' array
    (parse_args): parse options and pass flags to 'link_info' struct.
    * ld/ldlex.h (Add 2 enums): add new enums @ 'option_values' enum.
    * include/bfdlink.h (Add 2 flags): Add new flags @ 'bfd_link_info' struct.
    * ld/main.c: Initialize flags with false @ 'main'. Handle
disable-multiple-abs-defs
    @ 'mutiple_definition'.

Patch:
======
Patch attached here and updated as well in
https://github.com/andrewsadek/microblaze-pic-data-text-rel/blob/pic_data_text_rel/PATCH_BUNDLE/binutils.patch




On Mon, Mar 26, 2018 at 8:16 AM, Andrew Sadek <andrew.sadek.se@gmail.com> wrote:
> On Mon, Mar 26, 2018 at 1:48 AM, Michael Eager <eager@eagercon.com> wrote:
>>
>>>>>       (microblaze_bfd_write_branch_absolute_value_64): replace relative
>>>>> branch with absolute in case 'adjust_insn_abs_refs' is true
>>>>>       (microblaze_bfd_revert_base_reg_value_64): revert base register
>>>>> from r20 to r0 in case 'adjust_insn_abs_refs' is true
>>>>
>>>>
>>>>
>>>> These two functions are short and only referenced in
>>>> microblaze_elf_relocate_section().  It might be clearer to put them
>>>> inline in this function.
>>>>
>>>> I'm unclear what is going on in these functions or why.  Why are you
>>>> replacing PCREL or TEXTREL reloc with a generic reloc?
>>>>
>>>> I'm not comfortable with editing the instructions to replace opcodes or
>>>> registers.  Shouldn't this be handled in GCC by generating the correct
>>>> instruction in the first place?  What this means is that the source
>>>> assembly generated by GCC will be different from that generated by
>>>> objdump.
>>>>
>>>
>>> In fact, the idea behind 'adjust-insn-abs-refs' option is when making
>>> static linking
>>> to a position independent executable with the base program using -R,
>>> the relocate function
>>> checks whether the symbol is coming from the external file or not then
>>> re-adjust the instruction
>>> to use absolute addressing instead since the reference location in
>>> memory is fixed and shall be
>>> excluded from PIC/PIE.
>>> - For function call: brlid => bralid and accordingly PCREL => Generic
>>> Reloc
>>> - For data reference => replace base register  r0 => r20 and TEXTREL =>
>>> Generic
>>>
>>> I understand it's not the best clean way. I agree with you that it
>>> would be better to handle it in GCC.
>>> So, I came up with this solution: Make a variable/function declaration
>>> attribute in microblaze.c called for example
>>> 'absolute_reference' which then excludes the symbol reference from PIC
>>> and generate the corresponding
>>> instruction. In addition, replace 'adjust-insn-abs-refs' in linker
>>> with something like 'validate-insn-abs-refs'
>>> that only checks if symbol references coming from the external file
>>> are invoked with absolute addressing
>>> and generate error/warning if not. What do you think ?
>>
>>
>> I'll have to give this some thought.
>>
>> Do any other targets support a text relative addressing mode?
>
> I could find it in ARM but the instructions that retrieve the data
> support pc-relative addressing also could not find the feature of
> switching between relative and absolute addressing in PIC.
> I found this discussion in gnu archive:
> https://lists.gnu.org/archive/html/help-gplusplus/2012-03/msg00000.html
>
>>
>>> I get this error:
>>>
>>> *Hi. This is the qmail-send program at sourceware.org.
>>> *I'm afraid I wasn't able to deliver your message to the following
>>> addresses.
>>> *This is a permanent error; I've given up. Sorry it didn't work out.
>>>
>>> *<gcc-patches@gcc.gnu.org>:
>>> *Invalid mime type "text/html" detected in message text or
>>> *attachment.  Please send plain text messages only.
>>> *See http://sourceware.org/lists.html#sourceware-list-info for more
>>> information.
>>>
>>> I checked the website, it's stated that only plain text is allowed.
>>
>> Set your email client to send text only.  If you are using gmail, click
>> the arrow at the bottom right of the compose window and select "Plain
>> Text Mode".
>
> Thanks. It's working now. I m just attaching the same patch.
>
>> --
>> Michael Eager    eager@eagercon.com
>>
>> 1960 Park Blvd., Palo Alto, CA 94306
>
>
>
> --
>
> Andrew



-- 

Andrew
-------------- next part --------------
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 9742c1a..11b1705 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -5904,6 +5904,16 @@ to two words (uses imm instruction).  */
 to two words (uses imm instruction).  */
   BFD_RELOC_MICROBLAZE_64_TLSTPREL,
 
+/* This is a 64 bit reloc that stores the 32 bit pc relative
+value in two words (with an imm instruction).  The relocation is
+PC-relative offset from start of TEXT.  */
+  BFD_RELOC_MICROBLAZE_64_TEXTPCREL,
+
+/* This is a 64 bit reloc that stores the 32 bit offset
+value in two words (with an imm instruction).  The relocation is
+relative offset from start of TEXT.  */
+  BFD_RELOC_MICROBLAZE_64_TEXTREL,
+
 /* AArch64 pseudo relocation code to mark the start of the AArch64
 relocation enumerators.  N.B. the order of the enumerators is
 important as several tables in the AArch64 bfd backend are indexed
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index 3acf93a..f6bd634 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -251,6 +251,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
 	  0x0000ffff,		/* Dest Mask.  */
 	  TRUE),		/* PC relative offset?  */
 
+     /* A 64 bit TEXTPCREL relocation.  Table-entry not really used.  */
+   HOWTO (R_MICROBLAZE_TEXTPCREL_64,   	/* Type.  */
+	  0,			/* Rightshift.  */
+	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
+	  16,			/* Bitsize.  */
+	  TRUE,			/* PC_relative.  */
+	  0,			/* Bitpos.  */
+	  complain_overflow_dont, /* Complain on overflow.  */
+	  bfd_elf_generic_reloc,	/* Special Function.  */
+	  "R_MICROBLAZE_TEXTPCREL_64", 	/* Name.  */
+	  FALSE,		/* Partial Inplace.  */
+	  0,			/* Source Mask.  */
+	  0x0000ffff,		/* Dest Mask.  */
+	  TRUE), 		/* PC relative offset?  */
+
    /* A 64 bit GOT relocation.  Table-entry not really used.  */
    HOWTO (R_MICROBLAZE_GOT_64,  /* Type.  */
 	  0,			/* Rightshift.  */
@@ -266,6 +281,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
 	  0x0000ffff,		/* Dest Mask.  */
 	  FALSE),		/* PC relative offset?  */
 
+    /* A 64 bit TEXTREL relocation.  Table-entry not really used.  */
+   HOWTO (R_MICROBLAZE_TEXTREL_64,  /* Type.  */
+	  0,			/* Rightshift.  */
+	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
+	  16,			/* Bitsize.  */
+	  FALSE,		/* PC_relative.  */
+	  0,			/* Bitpos.  */
+	  complain_overflow_dont, /* Complain on overflow.  */
+	  bfd_elf_generic_reloc,/* Special Function.  */
+	  "R_MICROBLAZE_TEXTREL_64",/* Name.  */
+	  FALSE,		/* Partial Inplace.  */
+	  0,			/* Source Mask.  */
+	  0x0000ffff,		/* Dest Mask.  */
+	  FALSE), 		/* PC relative offset?  */
+
    /* A 64 bit PLT relocation.  Table-entry not really used.  */
    HOWTO (R_MICROBLAZE_PLT_64,  /* Type.  */
 	  0,			/* Rightshift.  */
@@ -578,6 +608,12 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
     case BFD_RELOC_MICROBLAZE_64_GOT:
       microblaze_reloc = R_MICROBLAZE_GOT_64;
       break;
+    case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
+      microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
+      break;
+    case BFD_RELOC_MICROBLAZE_64_TEXTREL:
+      microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
+      break;
     case BFD_RELOC_MICROBLAZE_64_PLT:
       microblaze_reloc = R_MICROBLAZE_PLT_64;
       break;
@@ -840,6 +876,59 @@ microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
 	      (sreloc->contents + reloc_index * sizeof (Elf32_External_Rela)));
 }
 
+#define BRLID_BRALID_OPCODE_MASK    0xFC1F0000
+#define BRLID_OPCODE                0xB8140000
+#define BRALID_OPCODE               0xB81C0000
+#define ADDK_OPCODE                 0x10000000
+#define RD_MASK                     0x03E00000
+#define RA_MASK                     0x001F0000
+#define RB_MASK                     0x0000F800
+#define NOP                         0x80000000
+#define R0                          0x00
+#define R20                         0x14
+
+/*
+This code is to replace relative branch instruction with absolute
+branch instruction in case of absolute address coming from external elf
+*/
+
+static void
+microblaze_bfd_write_branch_absolute_value_64 (bfd *abfd, bfd_byte *bfd_addr)
+{
+    unsigned long instr_lo;
+
+    instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
+    if ((instr_lo & BRLID_BRALID_OPCODE_MASK) == BRLID_OPCODE)
+      {
+	    instr_lo &= ~BRLID_BRALID_OPCODE_MASK;
+	    instr_lo |= BRALID_OPCODE;
+      }
+
+    bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
+}
+
+/*
+This code is to revert base register of instruction
+back to R0 instead of R20 in case of absolute address coming from external elf
+and -mpic-data-text-rel option was invoked in compilation
+*/
+
+static void
+microblaze_bfd_revert_base_reg_value_64 (bfd *abfd, bfd_byte *bfd_addr)
+{
+    unsigned long instr_lo;
+    unsigned long base_reg;
+
+    instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
+    base_reg = ((instr_lo & RA_MASK) >> 16);
+    if (base_reg == R20)
+      {
+	    instr_lo &= ~RA_MASK;
+	    instr_lo |= R0;
+	    bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
+      }
+}
+
 /* This code is taken from elf32-m32r.c
    There is some attempt to make this function usable for many architectures,
    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
@@ -1009,11 +1098,32 @@ microblaze_elf_relocate_section (bfd *output_bfd,
 	      bfd_boolean warned ATTRIBUTE_UNUSED;
 	      bfd_boolean ignored ATTRIBUTE_UNUSED;
 
-	      RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
-				       r_symndx, symtab_hdr, sym_hashes,
-				       h, sec, relocation,
-				       unresolved_reloc, warned, ignored);
-	      sym_name = h->root.root.string;
+		  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+				  r_symndx, symtab_hdr, sym_hashes,
+				  h, sec, relocation,
+				  unresolved_reloc, warned, ignored);
+		  sym_name = h->root.root.string;
+
+		  if (info->adjust_insn_abs_refs
+		     && h->root.u.def.section->sec_info_type
+		     == SEC_INFO_TYPE_JUST_SYMS)
+		  {
+		    //symbol from external file
+			if ((int)r_type == R_MICROBLAZE_64_PCREL)
+			{
+			  //Fix relative branches to be absolute
+			  r_type = R_MICROBLAZE_64;
+			  microblaze_bfd_write_branch_absolute_value_64 (
+					  input_bfd, contents + offset);
+			}
+			else if ((int) r_type == R_MICROBLAZE_TEXTREL_64)
+			{
+			  // Fix base register to be r0 instead of r20
+			  r_type = R_MICROBLAZE_64;
+			  microblaze_bfd_revert_base_reg_value_64 (
+					  input_bfd, contents + offset);
+			}
+		  }
 	    }
 
 	  /* Sanity check the address.  */
@@ -1140,6 +1250,18 @@ microblaze_elf_relocate_section (bfd *output_bfd,
 			  contents + offset + endian + INST_WORD_SIZE);
 	      break;
 
+	    case (int) R_MICROBLAZE_TEXTPCREL_64:
+	      relocation = input_section->output_section->vma;
+	      relocation -= (input_section->output_section->vma
+			     + input_section->output_offset
+			     + offset + INST_WORD_SIZE);
+	      relocation += addend;
+	      bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+			  contents + offset + endian);
+	      bfd_put_16 (input_bfd, relocation & 0xffff,
+			  contents + offset + endian + INST_WORD_SIZE);
+	      break;
+
 	    case (int) R_MICROBLAZE_PLT_64:
 	      {
 		bfd_vma immediate;
@@ -1390,6 +1512,8 @@ microblaze_elf_relocate_section (bfd *output_bfd,
 	      bfd_put_16 (input_bfd, relocation & 0xffff,
 			  contents + offset + 2 + INST_WORD_SIZE);
 	      break;
+	    case (int) R_MICROBLAZE_TEXTREL_64:
+	    case (int) R_MICROBLAZE_TEXTREL_32_LO:
 	    case (int) R_MICROBLAZE_64_PCREL :
 	    case (int) R_MICROBLAZE_64:
 	    case (int) R_MICROBLAZE_32:
@@ -1408,11 +1532,22 @@ microblaze_elf_relocate_section (bfd *output_bfd,
 			  relocation -= (input_section->output_section->vma
 					 + input_section->output_offset
 					 + offset + INST_WORD_SIZE);
-			bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+			else if (r_type == R_MICROBLAZE_TEXTREL_64
+					|| r_type == R_MICROBLAZE_TEXTREL_32_LO)
+			  relocation -= input_section->output_section->vma;
+
+			if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
+			  bfd_put_16 (input_bfd, relocation & 0xffff,
+					      contents + offset + endian);
+
+			else
+			  {
+			    bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
 				    contents + offset + endian);
-			bfd_put_16 (input_bfd, relocation & 0xffff,
+			    bfd_put_16 (input_bfd, relocation & 0xffff,
 				    contents + offset + endian + INST_WORD_SIZE);
 		      }
+		    }
 		    break;
 		  }
 
@@ -1503,11 +1638,27 @@ microblaze_elf_relocate_section (bfd *output_bfd,
 			  relocation -= (input_section->output_section->vma
 					 + input_section->output_offset
 					 + offset + INST_WORD_SIZE);
-			bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
-				    contents + offset + endian);
-			bfd_put_16 (input_bfd, relocation & 0xffff,
-				    contents + offset + endian + INST_WORD_SIZE);
-		      }
+			else if (r_type == R_MICROBLAZE_TEXTREL_64
+					|| r_type == R_MICROBLAZE_TEXTREL_32_LO)
+			  relocation -= input_section->output_section->vma;
+
+			if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
+			  {
+				bfd_put_16 (input_bfd, relocation & 0xffff,
+							contents + offset
+							+ endian);
+			  }
+			else
+			  {
+			   bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+							contents + offset
+							+ endian);
+			   bfd_put_16 (input_bfd, relocation & 0xffff,
+							contents + offset
+							+ endian
+							+ INST_WORD_SIZE);
+			  }
+		    }
 		    break;
 		  }
 	      }
@@ -1700,7 +1851,8 @@ microblaze_elf_relax_section (bfd *abfd,
     {
       bfd_vma symval;
       if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
-	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64 ))
+	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64)
+	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
 	continue; /* Can't delete this reloc.  */
 
       /* Get the section contents.  */
@@ -1756,6 +1908,12 @@ microblaze_elf_relax_section (bfd *abfd,
 	       regular reloc processing.  */
 	    continue;
 
+      if (link_info->adjust_insn_abs_refs
+	      && h->root.u.def.section->sec_info_type
+	      == SEC_INFO_TYPE_JUST_SYMS)
+	    /* Just ignore symbol from external file.  */
+	    continue;
+
 	  symval = (h->root.u.def.value
 		    + h->root.u.def.section->output_section->vma
 		    + h->root.u.def.section->output_offset);
@@ -1769,7 +1927,11 @@ microblaze_elf_relax_section (bfd *abfd,
 	    - (irel->r_offset
 	       + sec->output_section->vma
 	       + sec->output_offset);
-	}
+    }
+      else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
+	    {
+	      symval = symval + irel->r_addend - (sec->output_section->vma);
+	    }
       else
 	symval += irel->r_addend;
 
@@ -1792,6 +1954,10 @@ microblaze_elf_relax_section (bfd *abfd,
 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
 					   (int) R_MICROBLAZE_32_LO);
 	      break;
+	    case R_MICROBLAZE_TEXTREL_64:
+	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+					   (int) R_MICROBLAZE_TEXTREL_32_LO);
+	      break;
 	    default:
 	      /* Cannot happen.  */
 	      BFD_ASSERT (FALSE);
@@ -1818,6 +1984,8 @@ microblaze_elf_relax_section (bfd *abfd,
 	      break;
 	    case R_MICROBLAZE_64_PCREL:
 	      break;
+	    case R_MICROBLAZE_TEXTREL_64:
+	    case R_MICROBLAZE_TEXTREL_32_LO:
 	    case R_MICROBLAZE_64:
 	    case R_MICROBLAZE_32_LO:
 	      /* If this reloc is against a symbol defined in this
@@ -1954,7 +2122,10 @@ microblaze_elf_relax_section (bfd *abfd,
 		    }
 		}
 	      else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
-		       || (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_LO))
+		       || (ELF32_R_TYPE (irelscan->r_info)
+				   == (int) R_MICROBLAZE_32_LO)
+		       || (ELF32_R_TYPE (irelscan->r_info)
+				   == (int) R_MICROBLAZE_TEXTREL_32_LO))
 		{
 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
 
@@ -1998,7 +2169,9 @@ microblaze_elf_relax_section (bfd *abfd,
 		    }
 		}
 
-	      if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64)
+	      if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
+		      || (ELF32_R_TYPE (irelscan->r_info)
+			      == (int) R_MICROBLAZE_TEXTREL_64))
 		{
 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
 
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 0fba5be..1d2007f 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -2857,6 +2857,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_MICROBLAZE_64_TLSDTPREL",
   "BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL",
   "BFD_RELOC_MICROBLAZE_64_TLSTPREL",
+  "BFD_RELOC_MICROBLAZE_64_TEXTPCREL",
+  "BFD_RELOC_MICROBLAZE_64_TEXTREL",
   "BFD_RELOC_AARCH64_RELOC_START",
   "BFD_RELOC_AARCH64_NULL",
   "BFD_RELOC_AARCH64_NONE",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 42e35b9..06526a7 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -6982,6 +6982,18 @@ ENUM
 ENUMDOC
   This is a 64 bit reloc that stores 32-bit thread pointer relative offset
   to two words (uses imm instruction).
+ENUM
+  BFD_RELOC_MICROBLAZE_64_TEXTPCREL
+ENUMDOC
+  This is a 64 bit reloc that stores the 32 bit pc relative
+  value in two words (with an imm instruction).  The relocation is
+  PC-relative offset from start of TEXT.
+ENUM
+  BFD_RELOC_MICROBLAZE_64_TEXTREL
+ENUMDOC
+  This is a 64 bit reloc that stores the 32 bit offset
+  value in two words (with an imm instruction).  The relocation is
+  relative offset from start of TEXT.
 
 ENUM
   BFD_RELOC_AARCH64_RELOC_START
diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
index 0194cd9..8b814a5 100644
--- a/gas/config/tc-microblaze.c
+++ b/gas/config/tc-microblaze.c
@@ -87,6 +87,8 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
 #define TLSDTPREL_OFFSET     14
 #define TLSGOTTPREL_OFFSET   15
 #define TLSTPREL_OFFSET      16
+#define TEXT_OFFSET      	 17
+#define TEXT_PC_OFFSET     	 18
 
 /* Initialize the relax table.  */
 const relax_typeS md_relax_table[] =
@@ -107,7 +109,9 @@ const relax_typeS md_relax_table[] =
   { 0x7fffffff, 0x80000000, INST_WORD_SIZE*1, 0 },  /* 13: TLSDTPMOD_OFFSET.  */
   { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /* 14: TLSDTPREL_OFFSET.  */
   { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /* 15: TLSGOTTPREL_OFFSET.  */
-  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }   /* 16: TLSTPREL_OFFSET.  */
+  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /* 16: TLSTPREL_OFFSET.  */
+  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /* 17: TEXT_OFFSET.  */
+  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }   /* 18: TEXT_PC_OFFSET.  */
 };
 
 static struct hash_control * opcode_hash_control;	/* Opcode mnemonics.  */
@@ -624,7 +628,9 @@ parse_exp (char *s, expressionS *e)
 #define IMM_TLSDTPMOD 6
 #define IMM_TLSDTPREL 7
 #define IMM_TLSTPREL  8
-#define IMM_MAX    9
+#define IMM_TXTREL    9
+#define IMM_TXTPCREL  10
+#define IMM_MAX    11
 
 struct imm_type {
 	const char *isuffix;	 /* Suffix String */
@@ -643,7 +649,9 @@ static struct imm_type imm_types[] = {
 	{ "TLSLDM", IMM_TLSLD, TLSLD_OFFSET },
 	{ "TLSDTPMOD", IMM_TLSDTPMOD, TLSDTPMOD_OFFSET },
 	{ "TLSDTPREL", IMM_TLSDTPREL, TLSDTPREL_OFFSET },
-	{ "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET }
+	{ "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET },
+	{ "TXTREL", IMM_TXTREL, TEXT_OFFSET },
+	{ "TXTPCREL", IMM_TXTPCREL, TEXT_PC_OFFSET }
 };
 
 static int
@@ -1019,7 +1027,7 @@ md_assemble (char * str)
       if (check_spl_reg (& reg2))
 	as_fatal (_("Cannot use special register with this instruction"));
 
-      if (exp.X_op != O_constant)
+      if (exp.X_op != O_constant || exp.X_md == IMM_TXTPCREL)
 	{
           const char *opc;
 	  relax_substateT subtype;
@@ -1921,6 +1929,18 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
       fragP->fr_fix += INST_WORD_SIZE * 2;
       fragP->fr_var = 0;
       break;
+    case TEXT_OFFSET:
+      fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
+	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTREL);
+      fragP->fr_fix += INST_WORD_SIZE * 2;
+      fragP->fr_var = 0;
+      break;
+    case TEXT_PC_OFFSET:
+      fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
+	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTPCREL);
+      fragP->fr_fix += INST_WORD_SIZE * 2;
+      fragP->fr_var = 0;
+      break;
     case PLT_OFFSET:
       fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
 	              fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_PLT);
@@ -2097,6 +2117,7 @@ md_apply_fix (fixS *   fixP,
       break;
     case BFD_RELOC_64_PCREL:
     case BFD_RELOC_64:
+    case BFD_RELOC_MICROBLAZE_64_TEXTREL:
       /* Add an imm instruction.  First save the current instruction.  */
       for (i = 0; i < INST_WORD_SIZE; i++)
 	buf[i + INST_WORD_SIZE] = buf[i];
@@ -2144,6 +2165,7 @@ md_apply_fix (fixS *   fixP,
     case BFD_RELOC_MICROBLAZE_64_GOT:
     case BFD_RELOC_MICROBLAZE_64_PLT:
     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
+    case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
       /* Add an imm instruction.  First save the current instruction.  */
       for (i = 0; i < INST_WORD_SIZE; i++)
 	buf[i + INST_WORD_SIZE] = buf[i];
@@ -2240,16 +2262,18 @@ md_estimate_size_before_relax (fragS * fragP,
       break;
 
     case INST_NO_OFFSET:
+    case TEXT_OFFSET:
       /* Used to be a reference to somewhere which was unknown.  */
       if (fragP->fr_symbol)
         {
 	  if (fragP->fr_opcode == NULL)
 	    {
-              /* Used as an absolute value.  */
-              fragP->fr_subtype = DEFINED_ABS_SEGMENT;
-              /* Variable part does not change.  */
-              fragP->fr_var = INST_WORD_SIZE*2;
-            }
+		  /* Used as an absolute value.  */
+		  if (fragP->fr_subtype == INST_NO_OFFSET)
+		    fragP->fr_subtype = DEFINED_ABS_SEGMENT;
+		  /* Variable part does not change.  */
+		  fragP->fr_var = INST_WORD_SIZE*2;
+	    }
 	  else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
 	    {
               /* It is accessed using the small data read only anchor.  */
@@ -2318,6 +2342,7 @@ md_estimate_size_before_relax (fragS * fragP,
     case GOT_OFFSET:
     case PLT_OFFSET:
     case GOTOFF_OFFSET:
+    case TEXT_PC_OFFSET:
     case TLSGD_OFFSET:
     case TLSLD_OFFSET:
     case TLSTPREL_OFFSET:
@@ -2418,6 +2443,8 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
     case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
     case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
+    case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
+    case BFD_RELOC_MICROBLAZE_64_TEXTREL:
       code = fixp->fx_r_type;
       break;
 
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 5d637ac..65b9c8d 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -439,6 +439,12 @@ struct bfd_link_info
   /* TRUE if ok to have multiple definition.  */
   unsigned int allow_multiple_definition: 1;
 
+  /* TRUE if ok to have prohibit multiple definition of absolute symbols.  */
+  unsigned int prohibit_multiple_definition_absolute: 1;
+
+  /* TRUE if ok to adapt instructions for abs references.  */
+  unsigned int adjust_insn_abs_refs: 1;
+
   /* TRUE if ok to have version with no definition.  */
   unsigned int allow_undefined_version: 1;
 
diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h
index ae98099..dbaa16c 100644
--- a/include/elf/microblaze.h
+++ b/include/elf/microblaze.h
@@ -58,7 +58,9 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type)
   RELOC_NUMBER (R_MICROBLAZE_TLSDTPREL64, 27)   /* TLS Offset Within TLS Block */
   RELOC_NUMBER (R_MICROBLAZE_TLSGOTTPREL32, 28) /* TLS Offset From Thread Pointer */
   RELOC_NUMBER (R_MICROBLAZE_TLSTPREL32, 29)    /* TLS Offset From Thread Pointer */
-   
+  RELOC_NUMBER (R_MICROBLAZE_TEXTPCREL_64, 30)  /* PC-relative TEXT offset.  */
+  RELOC_NUMBER (R_MICROBLAZE_TEXTREL_64, 31)    /* TEXT Entry offset 64-bit.  */
+  RELOC_NUMBER (R_MICROBLAZE_TEXTREL_32_LO, 32) /* TEXT Entry offset 32-bit.  */
 END_RELOC_NUMBERS (R_MICROBLAZE_max)
 
 /* Global base address names.  */
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 226e2de..5fbc317 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1582,6 +1582,17 @@ that the relocs are stored in a target specific section.  This option
 is only supported by the @samp{BFIN}, @samp{CR16} and @emph{M68K}
 targets.
 
+@kindex --adjust-insn-abs-refs
+@item --adjust-insn-abs-refs
+This option is used to adjust instruction to absolute addressing
+when relocation refers to a symbol from filename invoked by -R
+or --just-symbols
+
+@kindex --disable-multiple-abs-defs
+@item --disable-multiple-abs-defs
+Do not allow multiple definitions with symbols included
+in filename invoked by -R or --just-symbols
+
 @kindex --fatal-warnings
 @kindex --no-fatal-warnings
 @item --fatal-warnings
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 1ecb152..4f5fe3a 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -143,6 +143,8 @@ enum option_values
   OPTION_IGNORE_UNRESOLVED_SYMBOL,
   OPTION_PUSH_STATE,
   OPTION_POP_STATE,
+  OPTION_ADJUST_INSN_ABS_REFS,
+  OPTION_DISABLE_MULTIPLE_DEFS_ABS,
   OPTION_PRINT_MEMORY_USAGE,
   OPTION_REQUIRE_DEFINED_SYMBOL,
   OPTION_ORPHAN_HANDLING,
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 6527613..22650f4 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -280,6 +280,8 @@ main (int argc, char **argv)
   link_info.keep_memory = TRUE;
   link_info.combreloc = TRUE;
   link_info.strip_discarded = TRUE;
+  link_info.prohibit_multiple_definition_absolute = FALSE;
+  link_info.adjust_insn_abs_refs = FALSE;
   link_info.emit_hash = DEFAULT_EMIT_SYSV_HASH;
   link_info.emit_gnu_hash = DEFAULT_EMIT_GNU_HASH;
   link_info.callbacks = &link_callbacks;
@@ -970,12 +972,13 @@ multiple_definition (struct bfd_link_info *info,
      discarded, and this is not really a multiple definition at all.
      FIXME: It would be cleaner to somehow ignore symbols defined in
      sections which are being discarded.  */
-  if ((osec->output_section != NULL
-       && !bfd_is_abs_section (osec)
-       && bfd_is_abs_section (osec->output_section))
+  if (!info->prohibit_multiple_definition_absolute
+      && ((osec->output_section != NULL
+      && ! bfd_is_abs_section (osec)
+      && bfd_is_abs_section (osec->output_section))
       || (nsec->output_section != NULL
-	  && !bfd_is_abs_section (nsec)
-	  && bfd_is_abs_section (nsec->output_section)))
+      && !bfd_is_abs_section (nsec)
+      && bfd_is_abs_section (nsec->output_section))))
     return;
 
   name = h->root.string;
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 636ce17..c15d830 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -314,6 +314,15 @@ static const struct ld_option ld_options[] =
   { {"demangle", optional_argument, NULL, OPTION_DEMANGLE},
     '\0', N_("[=STYLE]"), N_("Demangle symbol names [using STYLE]"),
     TWO_DASHES },
+  { {"adjust-insn-abs-refs", no_argument, NULL, OPTION_ADJUST_INSN_ABS_REFS},
+    '\0', NULL, N_("Adjust instruction when relocation contains a symbol\n"
+		   "           from filename invoked by -R or --just-symbols"),
+    TWO_DASHES},
+  { {"disable-multiple-abs-defs", no_argument, NULL,
+     OPTION_DISABLE_MULTIPLE_DEFS_ABS},
+    '\0', NULL, N_("Do not allow multiple definitions with symbols included\n"
+		   "           in filename invoked by -R or --just-symbols"),
+    TWO_DASHES},
   { {"embedded-relocs", no_argument, NULL, OPTION_EMBEDDED_RELOCS},
     '\0', NULL, N_("Generate embedded relocs"), TWO_DASHES},
   { {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL},
@@ -1159,6 +1168,12 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_NO_STRIP_DISCARDED:
 	  link_info.strip_discarded = FALSE;
 	  break;
+	case OPTION_ADJUST_INSN_ABS_REFS:
+	  link_info.adjust_insn_abs_refs = TRUE;
+	  break;
+	case OPTION_DISABLE_MULTIPLE_DEFS_ABS:
+	  link_info.prohibit_multiple_definition_absolute = TRUE;
+	  break;
 	case OPTION_SHARED:
 	  if (config.has_shared)
 	    {


More information about the Binutils mailing list