roland 079184
libdwfl/
roland 079184
2007-10-17  Roland McGrath  <roland@redhat.com>
roland 079184
roland 079184
	* dwfl_module_getsym.c (dwfl_module_getsym): Apply MOD->symfile->bias
roland 079184
	to relocated st_value.
roland 079184
roland 079184
	* dwfl_report_elf.c (__libdwfl_report_elf): Align initial BASE for
roland 079184
	ET_REL to 0x100.
roland 079184
roland 079184
2007-10-16  Roland McGrath  <roland@redhat.com>
roland 079184
roland 079184
	* dwfl_report_elf.c (__libdwfl_report_elf): Readjust BASE when a later
roland 079184
	section has larger alignment requirements not met by the original BASE,
roland 079184
	rather than padding more between sections.
roland 079184
roland 079184
	* dwfl_report_elf.c (__libdwfl_report_elf): Fix bias calculation.
roland 079184
roland 079184
	* dwfl_module_build_id.c (__libdwfl_find_build_id): Apply module bias
roland 079184
	to sh_addr value.
roland 079184
roland 079184
	* dwfl_report_elf.c (__libdwfl_report_elf): Don't be confused by BASE
roland 079184
	at zero in ET_REL case.  Adjust BASE to necessary alignment.
roland 079184
roland 079184
	* dwfl_module_build_id.c (check_notes): Take -1, not 0, as stub value
roland 079184
	for DATA_VADDR.
roland 079184
	(__libdwfl_find_build_id): Update caller.
roland 079184
roland 079184
	* relocate.c (__libdwfl_relocate_value): Don't use sh_offset.
roland 079184
	* dwfl_report_elf.c (__libdwfl_report_elf): Likewise.
roland 079184
	* offline.c (dwfl_offline_section_address): Bail early if there is
roland 079184
	separate debug file.
roland 079184
roland 079184
	* relocate.c (__libdwfl_relocate): Don't return DWFL_E_NO_DWARF.
roland 079184
roland 079184
src/
roland 079184
2007-10-16  Roland McGrath  <roland@redhat.com>
roland 079184
roland 079184
	* readelf.c (hex_dump): Fix rounding error in whitespace calculation.
roland 079184
roland 079184
tests/
roland 079184
2007-10-16  Roland McGrath  <roland@redhat.com>
roland 079184
roland 079184
	* test-subr.sh (remove_files): Don't pass -Bb to diff.
roland 079184
roland 316b9c
============================================================
roland 316b9c
--- libdwfl/dwfl_module_build_id.c	ae14fc9f3be468ffff14b4f6247ad38898705132
roland 316b9c
+++ libdwfl/dwfl_module_build_id.c	c67b9be68b69c98f6fd1024f521acdab0678ea02
roland 316b9c
@@ -73,6 +73,8 @@ found_build_id (Dwfl_Module *mod, bool s
roland 316b9c
   return len;
roland 316b9c
 }
roland 316b9c
 
roland 316b9c
+#define NO_VADDR	((GElf_Addr) -1l)
roland 316b9c
+
roland 316b9c
 static int
roland 316b9c
 check_notes (Dwfl_Module *mod, bool set, Elf_Data *data, GElf_Addr data_vaddr)
roland 316b9c
 {
roland 316b9c
@@ -86,7 +88,7 @@ check_notes (Dwfl_Module *mod, bool set,
roland 316b9c
 						     "GNU", sizeof "GNU"))
roland 316b9c
       return found_build_id (mod, set,
roland 316b9c
 			     data->d_buf + desc_pos, nhdr.n_descsz,
roland 316b9c
-			     data_vaddr == 0 ? 0 : data_vaddr + pos);
roland 316b9c
+			     data_vaddr == NO_VADDR ? 0 : data_vaddr + pos);
roland 316b9c
   return 0;
roland 316b9c
 }
roland 316b9c
 
roland 316b9c
@@ -129,7 +131,7 @@ __libdwfl_find_build_id (Dwfl_Module *mo
roland 316b9c
 	if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
roland 316b9c
 	  result = check_notes (mod, set, elf_getdata (scn, NULL),
roland 316b9c
 				(shdr->sh_flags & SHF_ALLOC)
roland 316b9c
-				? shdr->sh_addr : 0);
roland 316b9c
+				? shdr->sh_addr + mod->main.bias : NO_VADDR);
roland 316b9c
       }
roland 316b9c
     while (result == 0 && (scn = elf_nextscn (elf, scn)) != NULL);
roland 316b9c
 
roland 316b9c
============================================================
roland 316b9c
--- libdwfl/dwfl_module_getsym.c	5596a4a3df363bb27759a0c26519b9818475aa80
roland 316b9c
+++ libdwfl/dwfl_module_getsym.c	c1a0448eecebc039393fb884ff7d0684d1d5001f
roland 316b9c
@@ -85,10 +85,7 @@ dwfl_module_getsym (Dwfl_Module *mod, in
roland 316b9c
       break;
roland 316b9c
 
roland 316b9c
     default:
roland 316b9c
-      if (mod->e_type != ET_REL)
roland 316b9c
-	/* Apply the bias to the symbol value.  */
roland 316b9c
-	sym->st_value += mod->symfile->bias;
roland 316b9c
-      else
roland 316b9c
+      if (mod->e_type == ET_REL)
roland 316b9c
 	{
roland 316b9c
 	  /* In an ET_REL file, the symbol table values are relative
roland 316b9c
 	     to the section, not to the module's load base.  */
roland 316b9c
@@ -102,6 +99,8 @@ dwfl_module_getsym (Dwfl_Module *mod, in
roland 316b9c
 	      return NULL;
roland 316b9c
 	    }
roland 316b9c
 	}
roland 316b9c
+      /* Apply the bias to the symbol value.  */
roland 316b9c
+      sym->st_value += mod->symfile->bias;
roland 316b9c
       break;
roland 316b9c
     }
roland 316b9c
 
roland 316b9c
============================================================
roland 316b9c
--- libdwfl/dwfl_report_elf.c	d9db919b103fc3411d240f3a096af5e57a3adce6
roland 316b9c
+++ libdwfl/dwfl_report_elf.c	ee4a17cd0e3bf27c306b484ab38c34a7de2b7c0e
roland 316b9c
@@ -51,6 +51,14 @@
roland 316b9c
 #include <fcntl.h>
roland 316b9c
 #include <unistd.h>
roland 316b9c
 
roland 316b9c
+
roland 316b9c
+/* We start every ET_REL module at a moderately aligned boundary.
roland 316b9c
+   This keeps the low addresses easy to read compared to a layout
roland 316b9c
+   starting at 0 (as when using -e).  It also makes it unlikely
roland 316b9c
+   that a middle section will have a larger alignment and require
roland 316b9c
+   rejiggering (see below).  */
roland 316b9c
+#define REL_MIN_ALIGN	((GElf_Xword) 0x100)
roland 316b9c
+
roland 316b9c
 Dwfl_Module *
roland 316b9c
 internal_function
roland 316b9c
 __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
roland 316b9c
@@ -72,41 +80,91 @@ __libdwfl_report_elf (Dwfl *dwfl, const 
roland 316b9c
 	 By updating the section header in place, we leave the layout
roland 316b9c
 	 information to be found by relocation.  */
roland 316b9c
 
roland 316b9c
-      start = end = base;
roland 316b9c
+      start = end = base = (base + REL_MIN_ALIGN - 1) & -REL_MIN_ALIGN;
roland 316b9c
 
roland 316b9c
+      bool first = true;
roland 316b9c
       Elf_Scn *scn = NULL;
roland 316b9c
       while ((scn = elf_nextscn (elf, scn)) != NULL)
roland 316b9c
 	{
roland 316b9c
 	  GElf_Shdr shdr_mem;
roland 316b9c
 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
roland 316b9c
-	  if (shdr == NULL)
roland 316b9c
+	  if (unlikely (shdr == NULL))
roland 316b9c
 	    goto elf_error;
roland 316b9c
 
roland 316b9c
 	  if (shdr->sh_flags & SHF_ALLOC)
roland 316b9c
 	    {
roland 316b9c
 	      const GElf_Xword align = shdr->sh_addralign ?: 1;
roland 316b9c
-	      if (shdr->sh_addr == 0 || (bias == 0 && end > start))
roland 316b9c
+	      const GElf_Addr next = (end + align - 1) & -align;
roland 316b9c
+	      if (shdr->sh_addr == 0
roland 316b9c
+		  /* Once we've started doing layout we have to do it all,
roland 316b9c
+		     unless we just layed out the first section at 0 when
roland 316b9c
+		     it already was at 0.  */
roland 316b9c
+		  || (bias == 0 && end > start && end != next))
roland 316b9c
 		{
roland 316b9c
-		  shdr->sh_addr = (end + align - 1) & -align;
roland 316b9c
+		  shdr->sh_addr = next;
roland 316b9c
 		  if (end == base)
roland 316b9c
 		    /* This is the first section assigned a location.
roland 316b9c
 		       Use its aligned address as the module's base.  */
roland 316b9c
-		    start = shdr->sh_addr;
roland 316b9c
+		    start = base = shdr->sh_addr;
roland 316b9c
+		  else if (unlikely (base & (align - 1)))
roland 316b9c
+		    {
roland 316b9c
+		      /* If BASE has less than the maximum alignment of
roland 316b9c
+			 any section, we eat more than the optimal amount
roland 316b9c
+			 of padding and so make the module's apparent
roland 316b9c
+			 size come out larger than it would when placed
roland 316b9c
+			 at zero.  So reset the layout with a better base.  */
roland 316b9c
+
roland 316b9c
+		      start = end = base = (base + align - 1) & -align;
roland 316b9c
+		      Elf_Scn *prev_scn = NULL;
roland 316b9c
+		      do
roland 316b9c
+			{
roland 316b9c
+			  prev_scn = elf_nextscn (elf, prev_scn);
roland 316b9c
+			  GElf_Shdr prev_shdr_mem;
roland 316b9c
+			  GElf_Shdr *prev_shdr = gelf_getshdr (prev_scn,
roland 316b9c
+							       &prev_shdr_mem);
roland 316b9c
+			  if (unlikely (prev_shdr == NULL))
roland 316b9c
+			    goto elf_error;
roland 316b9c
+			  if (prev_shdr->sh_flags & SHF_ALLOC)
roland 316b9c
+			    {
roland 316b9c
+			      const GElf_Xword prev_align
roland 316b9c
+				= prev_shdr->sh_addralign ?: 1;
roland 316b9c
+
roland 316b9c
+			      prev_shdr->sh_addr
roland 316b9c
+				= (end + prev_align - 1) & -prev_align;
roland 316b9c
+			      end = prev_shdr->sh_addr + prev_shdr->sh_size;
roland 316b9c
+
roland 316b9c
+			      if (unlikely (! gelf_update_shdr (prev_scn,
roland 316b9c
+								prev_shdr)))
roland 316b9c
+				goto elf_error;
roland 316b9c
+			    }
roland 316b9c
+			}
roland 316b9c
+		      while (prev_scn != scn);
roland 316b9c
+		      continue;
roland 316b9c
+		    }
roland 316b9c
+
roland 316b9c
 		  end = shdr->sh_addr + shdr->sh_size;
roland 316b9c
-		  if (shdr->sh_addr == 0)
roland 316b9c
-		    /* This is a marker that this was resolved to zero,
roland 316b9c
-		       to prevent a callback.  */
roland 316b9c
-		    shdr->sh_offset = 0;
roland 316b9c
-		  if (! gelf_update_shdr (scn, shdr))
roland 316b9c
+		  if (likely (shdr->sh_addr != 0)
roland 316b9c
+		      && unlikely (! gelf_update_shdr (scn, shdr)))
roland 316b9c
 		    goto elf_error;
roland 316b9c
 		}
roland 316b9c
 	      else
roland 316b9c
 		{
roland 316b9c
-		  if (bias == 0 || end < shdr->sh_addr + shdr->sh_size)
roland 316b9c
+		  /* The address is already assigned.  Just track it.  */
roland 316b9c
+		  if (first || end < shdr->sh_addr + shdr->sh_size)
roland 316b9c
 		    end = shdr->sh_addr + shdr->sh_size;
roland 316b9c
-		  if (bias == 0 || bias > shdr->sh_addr)
roland 316b9c
+		  if (first || bias > shdr->sh_addr)
roland 316b9c
+		    /* This is the lowest address in the module.  */
roland 316b9c
 		    bias = shdr->sh_addr;
roland 316b9c
+
roland 316b9c
+		  if ((shdr->sh_addr - bias + base) & (align - 1))
roland 316b9c
+		    /* This section winds up misaligned using BASE.
roland 316b9c
+		       Adjust BASE upwards to make it congruent to
roland 316b9c
+		       the lowest section address in the file modulo ALIGN.  */
roland 316b9c
+		    base = (((base + align - 1) & -align)
roland 316b9c
+			    + (bias & (align - 1)));
roland 316b9c
 		}
roland 316b9c
+
roland 316b9c
+	      first = false;
roland 316b9c
 	    }
roland 316b9c
 	}
roland 316b9c
 
roland 316b9c
@@ -117,7 +175,7 @@ __libdwfl_report_elf (Dwfl *dwfl, const 
roland 316b9c
 	     Now just compute the bias from the requested base.  */
roland 316b9c
 	  start = base;
roland 316b9c
 	  end = end - bias + start;
roland 316b9c
-	  bias -= start;
roland 316b9c
+	  bias = start - bias;
roland 316b9c
 	}
roland 316b9c
       break;
roland 316b9c
 
roland 316b9c
@@ -133,7 +191,7 @@ __libdwfl_report_elf (Dwfl *dwfl, const 
roland 316b9c
       for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
roland 316b9c
 	{
roland 316b9c
 	  GElf_Phdr phdr_mem, *ph = gelf_getphdr (elf, i, &phdr_mem);
roland 316b9c
-	  if (ph == NULL)
roland 316b9c
+	  if (unlikely (ph == NULL))
roland 316b9c
 	    goto elf_error;
roland 316b9c
 	  if (ph->p_type == PT_LOAD)
roland 316b9c
 	    {
roland 316b9c
@@ -148,7 +206,7 @@ __libdwfl_report_elf (Dwfl *dwfl, const 
roland 316b9c
       for (uint_fast16_t i = ehdr->e_phnum; i-- > 0;)
roland 316b9c
 	{
roland 316b9c
 	  GElf_Phdr phdr_mem, *ph = gelf_getphdr (elf, i, &phdr_mem);
roland 316b9c
-	  if (ph == NULL)
roland 316b9c
+	  if (unlikely (ph == NULL))
roland 316b9c
 	    goto elf_error;
roland 316b9c
 	  if (ph->p_type == PT_LOAD)
roland 316b9c
 	    {
roland 316b9c
============================================================
roland 316b9c
--- libdwfl/offline.c	1508fb5c96e46f5bf3bbdaa0e18921243cf2ab8b
roland 316b9c
+++ libdwfl/offline.c	d8dc43d35ecff3200099ec421a93cfadbd5a2e17
roland 316b9c
@@ -53,8 +53,9 @@
roland 316b9c
 
roland 316b9c
 /* Since dwfl_report_elf lays out the sections already, this will only be
roland 316b9c
    called when the section headers of the debuginfo file are being
roland 316b9c
-   consulted instead.  With binutils strip-to-debug, the symbol table is in
roland 316b9c
-   the debuginfo file and relocation looks there.  */
roland 316b9c
+   consulted instead, or for the section placed at 0.  With binutils
roland 316b9c
+   strip-to-debug, the symbol table is in the debuginfo file and relocation
roland 316b9c
+   looks there.  */
roland 316b9c
 int
roland 316b9c
 dwfl_offline_section_address (Dwfl_Module *mod,
roland 316b9c
 			      void **userdata __attribute__ ((unused)),
roland 316b9c
@@ -69,6 +70,11 @@ dwfl_offline_section_address (Dwfl_Modul
roland 316b9c
   assert (shdr->sh_addr == 0);
roland 316b9c
   assert (shdr->sh_flags & SHF_ALLOC);
roland 316b9c
 
roland 316b9c
+  if (mod->debug.elf == NULL)
roland 316b9c
+    /* We are only here because sh_addr is zero even though layout is complete.
roland 316b9c
+       The first section in the first file under -e is placed at 0.  */
roland 316b9c
+    return 0;
roland 316b9c
+
roland 316b9c
   /* The section numbers might not match between the two files.
roland 316b9c
      The best we can rely on is the order of SHF_ALLOC sections.  */
roland 316b9c
 
roland 316b9c
============================================================
roland 316b9c
--- libdwfl/relocate.c	5a08921fcd4b957b0d768e7a140eb5187dcaf69e
roland 316b9c
+++ libdwfl/relocate.c	51258c3bf6a18602dbd3fd2d8b721d4f7a9aef60
roland 316b9c
@@ -64,9 +64,7 @@ __libdwfl_relocate_value (Dwfl_Module *m
roland 316b9c
   if (refshdr == NULL)
roland 316b9c
     return DWFL_E_LIBELF;
roland 316b9c
 
roland 316b9c
-  if (refshdr->sh_addr == 0
roland 316b9c
-      && (refshdr->sh_flags & SHF_ALLOC)
roland 316b9c
-      && refshdr->sh_offset != 0)
roland 316b9c
+  if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
roland 316b9c
     {
roland 316b9c
       /* This is a loaded section.  Find its actual
roland 316b9c
 	 address and update the section header.  */
roland 316b9c
@@ -89,13 +87,11 @@ __libdwfl_relocate_value (Dwfl_Module *m
roland 316b9c
 	   don't really care.  */
roland 316b9c
 	refshdr->sh_addr = 0;	/* Make no adjustment below.  */
roland 316b9c
 
roland 316b9c
-      /* Mark it so we don't check it again for the next relocation.  */
roland 316b9c
-      refshdr->sh_offset = 0;
roland 316b9c
-
roland 316b9c
       /* Update the in-core file's section header to show the final
roland 316b9c
 	 load address (or unloadedness).  This serves as a cache,
roland 316b9c
 	 so we won't get here again for the same section.  */
roland 316b9c
-      if (unlikely (! gelf_update_shdr (refscn, refshdr)))
roland 316b9c
+      if (likely (refshdr->sh_addr != 0)
roland 316b9c
+	  && unlikely (! gelf_update_shdr (refscn, refshdr)))
roland 316b9c
 	return DWFL_E_LIBELF;
roland 316b9c
     }
roland 316b9c
 
roland 316b9c
@@ -202,7 +198,7 @@ __libdwfl_relocate (Dwfl_Module *mod, El
roland 316b9c
 
roland 316b9c
   /* Look at each section in the debuginfo file, and process the
roland 316b9c
      relocation sections for debugging sections.  */
roland 316b9c
-  Dwfl_Error result = DWFL_E_NO_DWARF;
roland 316b9c
+  Dwfl_Error result = DWFL_E_NOERROR;
roland 316b9c
   Elf_Scn *scn = NULL;
roland 316b9c
   while ((scn = elf_nextscn (debugfile, scn)) != NULL)
roland 316b9c
     {
roland 316b9c
@@ -369,7 +365,6 @@ __libdwfl_relocate (Dwfl_Module *mod, El
roland 316b9c
 	  if (reldata == NULL)
roland 316b9c
 	    return DWFL_E_LIBELF;
roland 316b9c
 
roland 316b9c
-	  result = DWFL_E_NOERROR;
roland 316b9c
 	  size_t nrels = shdr->sh_size / shdr->sh_entsize;
roland 316b9c
 	  if (shdr->sh_type == SHT_REL)
roland 316b9c
 	    for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
roland 316b9c
============================================================
roland 316b9c
--- src/readelf.c	a0d9bd8c3fb36429895ee314dd3a874af3f8866e
roland 316b9c
+++ src/readelf.c	06970982eff8d85287725619dd9eefc51c1bf1c0
roland 316b9c
@@ -5888,7 +5888,7 @@ hex_dump (const uint8_t *data, size_t le
roland 316b9c
 	  printf ("%02x", data[pos + i]);
roland 316b9c
 
roland 316b9c
       if (chunk < 16)
roland 316b9c
-	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk) / 4), "");
roland 316b9c
+	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
roland 316b9c
 
roland 316b9c
       for (size_t i = 0; i < chunk; ++i)
roland 316b9c
 	{
roland 316b9c
============================================================
roland 316b9c
--- tests/test-subr.sh	5ba4008367c39437a8e8d6ed0b6757d54bc10f4d
roland 316b9c
+++ tests/test-subr.sh	ea1d0339bca3d875076ed15e114e9d47b2ea96e2
roland 316b9c
@@ -1,5 +1,5 @@
roland 316b9c
 #! /bin/sh
roland 316b9c
-# Copyright (C) 2005 Red Hat, Inc.
roland 316b9c
+# Copyright (C) 2005, 2007 Red Hat, Inc.
roland 316b9c
 # This file is part of Red Hat elfutils.
roland 316b9c
 #
roland 316b9c
 # Red Hat elfutils is free software; you can redistribute it and/or modify
roland 316b9c
@@ -58,7 +58,7 @@ testrun_compare()
roland 316b9c
 {
roland 316b9c
   outfile="${1##*/}.out"
roland 316b9c
   testrun_out $outfile "$@"
roland 316b9c
-  diff -Bbu $outfile -
roland 316b9c
+  diff -u $outfile -
roland 316b9c
   # diff's exit status will kill the script.
roland 316b9c
 }
roland 316b9c