objdump --disassemble=sym peculiarities

Message ID Zgs4x0UQEuxblziu@squeak.grove.modra.org
State New
Headers
Series objdump --disassemble=sym peculiarities |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm warning Patch is already merged
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 warning Patch is already merged

Commit Message

Alan Modra April 1, 2024, 10:44 p.m. UTC
  Given this testcase:
 .text
 mov $x1,%eax
f1:
 mov $f1,%eax
 .type f1,@function
 .size f1,.-f1

 mov $x2,%eax
f2:
 mov $f2,%eax
 .type f2,@function
 .size f2,.-f2+0x1000 #bad size

objdump --reloc --disassemble=f1 prints
00000000 <f1-0x5>:
   0:	b8 00 00 00 00       	mov    $0x0,%eax

and objdump --reloc --disassemble=f2 prints
0000000f <f2>:
   f:	b8 0f 00 00 00       	mov    $0xf,%eax
			10: R_386_32	.text

It seems for f1 we get the insn before f1 and no reloc whereas, post
159daa36fa, f2 is disassembled correctly.  Some analysis says that
find_symbol_for_address may return a symbol past the current address,
and reloc skipping is broken.  Fix both of these problems.

	* objdump.c (disassemble_jumps, disassemble_bytes): Replace
        relppp with relpp, ie. don't update caller's rel_pp.  Adjust
        calls.
	(disassemble_section): Skip over relocs inside loop rather
        than before loop.  Revert 7e538762c2c1.  If given a symbol,
	don't start disassembling until its address is reached.
	Correct end of function calculation.
  

Patch

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 8293387558f..68da543e905 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2946,7 +2946,7 @@  disassemble_jumps (struct disassemble_info * inf,
 		   bfd_vma                   start_offset,
 		   bfd_vma                   stop_offset,
 		   bfd_vma		     rel_offset,
-		   arelent ***               relppp,
+		   arelent **                relpp,
 		   arelent **                relppend)
 {
   struct objdump_disasm_info *aux;
@@ -2988,11 +2988,11 @@  disassemble_jumps (struct disassemble_info * inf,
       if (inf->disassembler_needs_relocs
 	  && (bfd_get_file_flags (aux->abfd) & EXEC_P) == 0
 	  && (bfd_get_file_flags (aux->abfd) & DYNAMIC) == 0
-	  && *relppp < relppend)
+	  && relpp < relppend)
 	{
 	  bfd_signed_vma distance_to_rel;
 
-	  distance_to_rel = (**relppp)->address - (rel_offset + addr_offset);
+	  distance_to_rel = (*relpp)->address - (rel_offset + addr_offset);
 
 	  /* Check to see if the current reloc is associated with
 	     the instruction that we are about to disassemble.  */
@@ -3205,7 +3205,7 @@  disassemble_bytes (struct disassemble_info *inf,
 		   bfd_vma start_offset,
 		   bfd_vma stop_offset,
 		   bfd_vma rel_offset,
-		   arelent ***relppp,
+		   arelent **relpp,
 		   arelent **relppend)
 {
   struct objdump_disasm_info *aux;
@@ -3377,13 +3377,13 @@  disassemble_bytes (struct disassemble_info *inf,
 	      if (inf->disassembler_needs_relocs
 		  && (bfd_get_file_flags (aux->abfd) & EXEC_P) == 0
 		  && (bfd_get_file_flags (aux->abfd) & DYNAMIC) == 0
-		  && *relppp < relppend)
+		  && relpp < relppend)
 		{
 		  bfd_signed_vma distance_to_rel;
 		  int max_reloc_offset
 		    = aux->abfd->arch_info->max_reloc_offset_into_insn;
 
-		  distance_to_rel = ((**relppp)->address - rel_offset
+		  distance_to_rel = ((*relpp)->address - rel_offset
 				     - addr_offset);
 
 		  insn_size = 0;
@@ -3427,7 +3427,7 @@  disassemble_bytes (struct disassemble_info *inf,
 			  && distance_to_rel < insn_size / (int) opb))
 		    {
 		      inf->flags |= INSN_HAS_RELOC;
-		      aux->reloc = **relppp;
+		      aux->reloc = *relpp;
 		    }
 		}
 
@@ -3600,14 +3600,14 @@  disassemble_bytes (struct disassemble_info *inf,
 	    need_nl = true;
 	}
 
-      while ((*relppp) < relppend
-	     && (**relppp)->address < rel_offset + addr_offset + octets / opb)
+      while (relpp < relppend
+	     && (*relpp)->address < rel_offset + addr_offset + octets / opb)
 	{
 	  if (dump_reloc_info || dump_dynamic_reloc_info)
 	    {
 	      arelent *q;
 
-	      q = **relppp;
+	      q = *relpp;
 
 	      if (wide_output)
 		putchar ('\t');
@@ -3665,7 +3665,7 @@  disassemble_bytes (struct disassemble_info *inf,
 	      printf ("\n");
 	      need_nl = false;
 	    }
-	  ++(*relppp);
+	  ++relpp;
 	}
 
       if (need_nl)
@@ -3809,12 +3809,6 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
   if (sorted_symcount > 1)
     qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols);
 
-  /* Skip over the relocs belonging to addresses below the
-     start address.  */
-  while (rel_pp < rel_ppend
-	 && (*rel_pp)->address < rel_offset + addr_offset)
-    ++rel_pp;
-
   printf (_("\nDisassembly of section %s:\n"), sanitize_string (section->name));
 
   /* Find the nearest symbol forwards from our current position.  */
@@ -3846,6 +3840,12 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
       bfd_vma nextstop_offset;
       bool insns;
 
+      /* Skip over the relocs belonging to addresses below the
+	 start address.  */
+      while (rel_pp < rel_ppend
+	     && (*rel_pp)->address < rel_offset + addr_offset)
+	++rel_pp;
+
       addr = section->vma + addr_offset;
       addr = ((addr & ((sign_adjust << 1) - 1)) ^ sign_adjust) - sign_adjust;
 
@@ -3912,17 +3912,11 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
 
 	      /* We are not currently printing.  Check to see
 		 if the current symbol matches the requested symbol.  */
-	      if (streq (name, paux->symbol))
+	      if (streq (name, paux->symbol)
+		  && bfd_asymbol_value (sym) <= addr)
 		{
 		  do_print = true;
 
-		  /* Skip over the relocs belonging to addresses below the
-		     symbol address.  */
-		  const bfd_vma sym_offset = bfd_asymbol_value (sym) - section->vma;
-		  while (rel_pp < rel_ppend &&
-		   (*rel_pp)->address - rel_offset < sym_offset)
-			  ++rel_pp;
-
 		  loop_until = next_sym;
 		  if (sym->flags & BSF_FUNCTION)
 		    {
@@ -3932,13 +3926,14 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
 			{
 			  bfd_size_type fsize =
 			    ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
-			  if (addr_offset + fsize > addr_offset
-			      && addr_offset + fsize <= stop_offset)
+			  bfd_vma fend =
+			    bfd_asymbol_value (sym) - section->vma + fsize;
+			  if (fend > addr_offset && fend <= stop_offset)
 			    {
 			      /* Sym is a function symbol with a valid
 				 size associated with it.  Disassemble
 				 to the end of the function.  */
-			      stop_offset = addr_offset + fsize;
+			      stop_offset = fend;
 			      loop_until = stop_offset_reached;
 			    }
 			}
@@ -4046,11 +4041,9 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
 	      objdump_print_symname (abfd, &di, sym);
 
 	      /* Fetch jump information.  */
-	      detected_jumps = disassemble_jumps
-		(pinfo, paux->disassemble_fn,
-		 addr_offset, nextstop_offset,
-		 rel_offset, &rel_pp, rel_ppend);
-
+	      detected_jumps = disassemble_jumps (pinfo, paux->disassemble_fn,
+						  addr_offset, nextstop_offset,
+						  rel_offset, rel_pp, rel_ppend);
 	      /* Free symbol name.  */
 	      free (sf.buffer);
 	    }
@@ -4058,7 +4051,7 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
 	  /* Add jumps to output.  */
 	  disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
 			     addr_offset, nextstop_offset,
-			     rel_offset, &rel_pp, rel_ppend);
+			     rel_offset, rel_pp, rel_ppend);
 
 	  /* Free jumps.  */
 	  while (detected_jumps)