This is the mail archive of the binutils@sourceware.org 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]

read Xtensa property tables more robustly


The bug I just fixed (an extra increment in relax_property_section) caused some property table entries to have no relocations, and the code for reading property tables assumed that either all the entries have relocations or none of them do. That assumption is normally true but it is good to handle unexpected inputs. I've committed this patch that changes the table reader to walk through the table entries and relocations at the same time so that it can deal with entries with no relocations. (It still ignores relocations on the size and/or flags fields, though.) I tested this before I fixed the other bug, since without the bug, this situation doesn't come up.

bfd/
	* elf32-xtensa.c (xtensa_read_table_entries): Step through table
	contents and relocs in parallel.
Index: elf32-xtensa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-xtensa.c,v
retrieving revision 1.87
diff -u -p -r1.87 elf32-xtensa.c
--- elf32-xtensa.c	27 Apr 2007 18:28:22 -0000	1.87
+++ elf32-xtensa.c	27 Apr 2007 19:55:01 -0000
@@ -612,10 +612,10 @@ xtensa_read_table_entries (bfd *abfd,
   property_table_entry *blocks;
   int blk, block_count;
   bfd_size_type num_records;
-  Elf_Internal_Rela *internal_relocs;
-  bfd_vma section_addr;
+  Elf_Internal_Rela *internal_relocs, *irel, *rel_end;
+  bfd_vma section_addr, off;
   flagword predef_flags;
-  bfd_size_type table_entry_size;
+  bfd_size_type table_entry_size, section_limit;
 
   if (!section
       || !(section->flags & SEC_ALLOC)
@@ -651,67 +651,63 @@ xtensa_read_table_entries (bfd *abfd,
   else
     section_addr = section->vma;
 
-  /* If the file has not yet been relocated, process the relocations
-     and sort out the table entries that apply to the specified section.  */
   internal_relocs = retrieve_internal_relocs (abfd, table_section, TRUE);
   if (internal_relocs && !table_section->reloc_done)
     {
-      unsigned i;
+      qsort (internal_relocs, table_section->reloc_count,
+	     sizeof (Elf_Internal_Rela), internal_reloc_compare);
+      irel = internal_relocs;
+    }
+  else
+    irel = NULL;
+
+  section_limit = bfd_get_section_limit (abfd, section);
+  rel_end = internal_relocs + table_section->reloc_count;
+
+  for (off = 0; off < table_size; off += table_entry_size) 
+    {
+      bfd_vma address = bfd_get_32 (abfd, table_data + off);
 
-      for (i = 0; i < table_section->reloc_count; i++)
+      /* Skip any relocations before the current offset.  This should help
+	 avoid confusion caused by unexpected relocations for the preceding
+	 table entry.  */
+      while (irel &&
+	     (irel->r_offset < off
+	      || (irel->r_offset == off
+		  && ELF32_R_TYPE (irel->r_info) == R_XTENSA_NONE)))
 	{
-	  Elf_Internal_Rela *rel = &internal_relocs[i];
-	  unsigned long r_symndx;
+	  irel += 1;
+	  if (irel >= rel_end)
+	    irel = 0;
+	}
 
-	  if (ELF32_R_TYPE (rel->r_info) == R_XTENSA_NONE)
-	    continue;
+      if (irel && irel->r_offset == off)
+	{
+	  bfd_vma sym_off;
+	  unsigned long r_symndx = ELF32_R_SYM (irel->r_info);
+	  BFD_ASSERT (ELF32_R_TYPE (irel->r_info) == R_XTENSA_32);
 
-	  BFD_ASSERT (ELF32_R_TYPE (rel->r_info) == R_XTENSA_32);
-	  r_symndx = ELF32_R_SYM (rel->r_info);
+	  if (get_elf_r_symndx_section (abfd, r_symndx) != section)
+	    continue;
 
-	  if (get_elf_r_symndx_section (abfd, r_symndx) == section)
-	    {
-	      bfd_vma sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
-	      BFD_ASSERT (sym_off == 0);
-	      blocks[block_count].address =
-		(section_addr + sym_off + rel->r_addend
-		 + bfd_get_32 (abfd, table_data + rel->r_offset));
-	      blocks[block_count].size =
-		bfd_get_32 (abfd, table_data + rel->r_offset + 4);
-	      if (predef_flags)
-		blocks[block_count].flags = predef_flags;
-	      else
-		blocks[block_count].flags =
-		  bfd_get_32 (abfd, table_data + rel->r_offset + 8);
-	      block_count++;
-	    }
+	  sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
+	  BFD_ASSERT (sym_off == 0);
+	  address += (section_addr + sym_off + irel->r_addend);
 	}
-    }
-  else
-    {
-      /* The file has already been relocated and the addresses are
-	 already in the table.  */
-      bfd_vma off;
-      bfd_size_type section_limit = bfd_get_section_limit (abfd, section);
-
-      for (off = 0; off < table_size; off += table_entry_size) 
-	{
-	  bfd_vma address = bfd_get_32 (abfd, table_data + off);
-
-	  if (address >= section_addr
-	      && address < section_addr + section_limit)
-	    {
-	      blocks[block_count].address = address;
-	      blocks[block_count].size =
-		bfd_get_32 (abfd, table_data + off + 4);
-	      if (predef_flags)
-		blocks[block_count].flags = predef_flags;
-	      else
-		blocks[block_count].flags =
-		  bfd_get_32 (abfd, table_data + off + 8);
-	      block_count++;
-	    }
+      else
+	{
+	  if (address < section_addr
+	      || address >= section_addr + section_limit)
+	    continue;
 	}
+
+      blocks[block_count].address = address;
+      blocks[block_count].size = bfd_get_32 (abfd, table_data + off + 4);
+      if (predef_flags)
+	blocks[block_count].flags = predef_flags;
+      else
+	blocks[block_count].flags = bfd_get_32 (abfd, table_data + off + 8);
+      block_count++;
     }
 
   release_contents (table_section, table_data);

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