PATCH: BZ/175: Fix dynamic string offset

H. J. Lu hjl@lucon.org
Fri May 21 01:25:00 GMT 2004
For
	x = "1111" + (y - 0x1000) * 2;

gcc can generate

        addl r14 = @ltoffx(.LC0-8192), r1
        ;;
        ld8.mov r14 = [r14], .LC0-8192
        ;;

_bfd_merged_section_offset thinks offset + adddend is bad when it is
not the real string position. I looked at _bfd_merged_section_offset.
It is always passed with addend == 0. I changed addend to dynamic_offset
so that we can tell _bfd_merged_section_offset to compute offset
properly. If my patch is right, we may need to make similar change
to elf32-ppc.c.


H.J.

-------------- next part --------------
2004-05-20  H.J. Lu  <hongjiu.lu@intel.com>

	* elfxx-ia64.c (elfNN_ia64_relax_section): Call
	_bfd_merged_section_offset with irel->r_addend as dynamic
	offset.

	* merge.c (merged_section_offset): New. Modified from
	_bfd_merged_section_offset.
	(_bfd_merged_section_offset): Use it. Handle dynamic offset.

--- bfd/elfxx-ia64.c.merge	2004-05-19 08:30:21.000000000 -0700
+++ bfd/elfxx-ia64.c	2004-05-20 14:57:30.976418338 -0700
@@ -923,8 +923,7 @@ elfNN_ia64_relax_section (abfd, sec, lin
       if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
 	toff = _bfd_merged_section_offset (abfd, &tsec,
 					   elf_section_data (tsec)->sec_info,
-					   toff + irel->r_addend,
-					   (bfd_vma) 0);
+					   toff, irel->r_addend);
       else
 	toff += irel->r_addend;
 
--- bfd/merge.c.merge	2003-11-04 09:43:23.000000000 -0800
+++ bfd/merge.c	2004-05-20 15:04:45.299057245 -0700
@@ -778,9 +778,8 @@ _bfd_write_merged_section (bfd *output_b
    *PSEC, this returns the new offset in the adjusted SEC_MERGE
    section and writes the new section back into *PSEC.  */
 
-bfd_vma
-_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
-			    void *psecinfo, bfd_vma offset, bfd_vma addend)
+static bfd_vma
+merged_section_offset (asection **psec, void *psecinfo, bfd_vma offset)
 {
   struct sec_merge_sec_info *secinfo;
   struct sec_merge_hash_entry *entry;
@@ -789,13 +788,13 @@ _bfd_merged_section_offset (bfd *output_
 
   secinfo = (struct sec_merge_sec_info *) psecinfo;
 
-  if (offset + addend >= sec->_raw_size)
+  if (offset >= sec->_raw_size)
     {
-      if (offset + addend > sec->_raw_size)
+      if (offset > sec->_raw_size)
 	{
 	  (*_bfd_error_handler)
-	    (_("%s: access beyond end of merged section (%ld + %ld)"),
-	     bfd_get_filename (sec->owner), (long) offset, (long) addend);
+	    (_("%s: access beyond end of merged section (%ld)"),
+	     bfd_get_filename (sec->owner), (long) offset);
 	}
       return (secinfo->first ? sec->_cooked_size : 0);
     }
@@ -804,7 +803,7 @@ _bfd_merged_section_offset (bfd *output_
     {
       if (sec->entsize == 1)
 	{
-	  p = secinfo->contents + offset + addend - 1;
+	  p = secinfo->contents + offset - 1;
 	  while (p >= secinfo->contents && *p)
 	    --p;
 	  ++p;
@@ -812,7 +811,7 @@ _bfd_merged_section_offset (bfd *output_
       else
 	{
 	  p = secinfo->contents
-	      + ((offset + addend) / sec->entsize) * sec->entsize;
+	      + (offset / sec->entsize) * sec->entsize;
 	  p -= sec->entsize;
 	  while (p >= secinfo->contents)
 	    {
@@ -831,7 +830,7 @@ _bfd_merged_section_offset (bfd *output_
   else
     {
       p = secinfo->contents
-	  + ((offset + addend) / sec->entsize) * sec->entsize;
+	  + (offset / sec->entsize) * sec->entsize;
     }
   entry = sec_merge_hash_lookup (secinfo->htab, p, 0, FALSE);
   if (!entry)
@@ -846,10 +845,24 @@ _bfd_merged_section_offset (bfd *output_
 	abort ();
       entry = secinfo->htab->first;
       p = secinfo->contents
-	  + ((offset + addend) / sec->entsize + 1) * sec->entsize
+	  + (offset / sec->entsize + 1) * sec->entsize
 	  - entry->len;
     }
 
   *psec = entry->secinfo->sec;
   return entry->u.index + (secinfo->contents + offset - p);
 }
+
+bfd_vma
+_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
+			    asection **psec, void *psecinfo,
+			    bfd_vma offset, bfd_vma dynamic_offset)
+{
+  offset = merged_section_offset (psec, psecinfo, offset);
+  if (dynamic_offset)
+    /* If there is a dynamic_offset, the actual string position is
+       computed at the run-time, which is the new offset +
+       dynamic_offset.  */
+    offset += dynamic_offset;
+  return offset;
+}


More information about the Binutils mailing list