Upgrade to elfutils 0.161.

Change-Id: Iee07e1329d9750f092afc6c2fbd6af8db32862b0
diff --git a/src/libdwfl/link_map.c b/src/libdwfl/link_map.c
index 05839b3..eaf43b5 100644
--- a/src/libdwfl/link_map.c
+++ b/src/libdwfl/link_map.c
@@ -1,57 +1,39 @@
 /* Report modules by examining dynamic linker data structures.
-   Copyright (C) 2008-2010 Red Hat, Inc.
-   This file is part of Red Hat elfutils.
+   Copyright (C) 2008-2014 Red Hat, Inc.
+   This file is part of elfutils.
 
-   Red Hat elfutils is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by the
-   Free Software Foundation; version 2 of the License.
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
 
-   Red Hat elfutils is distributed in the hope that it will be useful, but
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License along
-   with Red Hat elfutils; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
-
-   In addition, as a special exception, Red Hat, Inc. gives You the
-   additional right to link the code of Red Hat elfutils with code licensed
-   under any Open Source Initiative certified open source license
-   (http://www.opensource.org/licenses/index.php) which requires the
-   distribution of source code with any binary distribution and to
-   distribute linked combinations of the two.  Non-GPL Code permitted under
-   this exception must only link to the code of Red Hat elfutils through
-   those well defined interfaces identified in the file named EXCEPTION
-   found in the source code files (the "Approved Interfaces").  The files
-   of Non-GPL Code may instantiate templates or use macros or inline
-   functions from the Approved Interfaces without causing the resulting
-   work to be covered by the GNU General Public License.  Only Red Hat,
-   Inc. may make changes or additions to the list of Approved Interfaces.
-   Red Hat's grant of this exception is conditioned upon your not adding
-   any new exceptions.  If you wish to add a new Approved Interface or
-   exception, please contact Red Hat.  You must obey the GNU General Public
-   License in all respects for all of the Red Hat elfutils code and other
-   code used in conjunction with Red Hat elfutils except the Non-GPL Code
-   covered by this exception.  If you modify this file, you may extend this
-   exception to your version of the file, but you are not obligated to do
-   so.  If you do not wish to provide this exception without modification,
-   you must delete this exception statement from your version and license
-   this file solely under the GPL without exception.
-
-   Red Hat elfutils is an included package of the Open Invention Network.
-   An included package of the Open Invention Network is a package for which
-   Open Invention Network licensees cross-license their patents.  No patent
-   license is granted, either expressly or impliedly, by designation as an
-   included package.  Should you wish to participate in the Open Invention
-   Network licensing program, please visit www.openinventionnetwork.com
-   <http://www.openinventionnetwork.com>.  */
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include "libdwflP.h"
+#include "../libdw/memory-access.h"
+#include "system.h"
 
 #include <byteswap.h>
 #include <endian.h>
+#include <fcntl.h>
 
 /* This element is always provided and always has a constant value.
    This makes it an easy thing to scan for to discern the format.  */
@@ -59,18 +41,6 @@
 #define PROBE_VAL32	sizeof (Elf32_Phdr)
 #define PROBE_VAL64	sizeof (Elf64_Phdr)
 
-#if BYTE_ORDER == BIG_ENDIAN
-# define BE32(x)	(x)
-# define BE64(x)	(x)
-# define LE32(x)	bswap_32 (x)
-# define LE64(x)	bswap_64 (x)
-#else
-# define LE32(x)	(x)
-# define LE64(x)	(x)
-# define BE32(x)	bswap_32 (x)
-# define BE64(x)	bswap_64 (x)
-#endif
-
 
 /* Examine an auxv data block and determine its format.
    Return true iff we figured it out.  */
@@ -87,15 +57,22 @@
 
   inline bool check64 (size_t i)
   {
-    if (u->a64[i].a_type == BE64 (PROBE_TYPE)
-	&& u->a64[i].a_un.a_val == BE64 (PROBE_VAL64))
+    /* The AUXV pointer might not even be naturally aligned for 64-bit
+       data, because note payloads in a core file are not aligned.
+       But we assume the data is 32-bit aligned.  */
+
+    uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type);
+    uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val);
+
+    if (type == BE64 (PROBE_TYPE)
+	&& val == BE64 (PROBE_VAL64))
       {
 	*elfdata = ELFDATA2MSB;
 	return true;
       }
 
-    if (u->a64[i].a_type == LE64 (PROBE_TYPE)
-	&& u->a64[i].a_un.a_val == LE64 (PROBE_VAL64))
+    if (type == LE64 (PROBE_TYPE)
+	&& val == LE64 (PROBE_VAL64))
       {
 	*elfdata = ELFDATA2LSB;
 	return true;
@@ -246,7 +223,10 @@
 }
 
 /* Report a module for each struct link_map in the linked list at r_map
-   in the struct r_debug at R_DEBUG_VADDR.
+   in the struct r_debug at R_DEBUG_VADDR.  For r_debug_info description
+   see dwfl_link_map_report in libdwflP.h.  If R_DEBUG_INFO is not NULL then no
+   modules get added to DWFL, caller has to add them from filled in
+   R_DEBUG_INFO.
 
    For each link_map entry, if an existing module resides at its address,
    this just modifies that module's name and suggested file name.  If
@@ -258,7 +238,8 @@
 report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 		Dwfl *dwfl, GElf_Addr r_debug_vaddr,
 		Dwfl_Memory_Callback *memory_callback,
-		void *memory_callback_arg)
+		void *memory_callback_arg,
+		struct r_debug_info *r_debug_info)
 {
   /* Skip r_version, to aligned r_map field.  */
   GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
@@ -340,7 +321,11 @@
       if (read_addrs (next, 4))
 	return release_buffer (-1);
 
-      GElf_Addr l_addr = addrs[0];
+      /* Unused: l_addr is the difference between the address in memory
+         and the ELF file when the core was created. We need to
+         recalculate the difference below because the ELF file we use
+         might be differently pre-linked.  */
+      // GElf_Addr l_addr = addrs[0];
       GElf_Addr l_name = addrs[1];
       GElf_Addr l_ld = addrs[2];
       next = addrs[3];
@@ -373,42 +358,117 @@
       if (name != NULL && name[0] == '\0')
 	name = NULL;
 
-      /* If content-sniffing already reported a module covering
-	 the same area, find that existing module to adjust.
-	 The l_ld address is the only one we know for sure
-	 to be within the module's own segments (its .dynamic).  */
-      Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, l_ld);
-      if (mod != NULL)
+      if (iterations == 1 && dwfl->executable_for_core != NULL)
+	name = dwfl->executable_for_core;
+
+      struct r_debug_info_module *r_debug_info_module = NULL;
+      if (r_debug_info != NULL)
 	{
-	  /* We have a module.  We can give it a better name from l_name.  */
-	  if (name != NULL && mod->name[0] == '[')
+	  /* Save link map information about valid shared library (or
+	     executable) which has not been found on disk.  */
+	  const char *name1 = name == NULL ? "" : name;
+	  r_debug_info_module = malloc (sizeof (*r_debug_info_module)
+					+ strlen (name1) + 1);
+	  if (r_debug_info_module == NULL)
+	    return release_buffer (result);
+	  r_debug_info_module->fd = -1;
+	  r_debug_info_module->elf = NULL;
+	  r_debug_info_module->l_ld = l_ld;
+	  r_debug_info_module->start = 0;
+	  r_debug_info_module->end = 0;
+	  r_debug_info_module->disk_file_has_build_id = false;
+	  strcpy (r_debug_info_module->name, name1);
+	  r_debug_info_module->next = r_debug_info->module;
+	  r_debug_info->module = r_debug_info_module;
+	}
+
+      Dwfl_Module *mod = NULL;
+      if (name != NULL)
+	{
+	  /* This code is mostly inlined dwfl_report_elf.  */
+	  // XXX hook for sysroot
+	  int fd = open64 (name, O_RDONLY);
+	  if (fd >= 0)
 	    {
-	      char *newname = strdup (basename (name));
-	      if (newname != NULL)
+	      Elf *elf;
+	      Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
+	      GElf_Addr elf_dynamic_vaddr;
+	      if (error == DWFL_E_NOERROR
+		  && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr))
 		{
-		  free (mod->name);
-		  mod->name = newname;
+		  const void *build_id_bits;
+		  GElf_Addr build_id_elfaddr;
+		  int build_id_len;
+		  bool valid = true;
+
+		  if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits,
+						   &build_id_elfaddr,
+						   &build_id_len) > 0
+		      && build_id_elfaddr != 0)
+		    {
+		      if (r_debug_info_module != NULL)
+			r_debug_info_module->disk_file_has_build_id = true;
+		      GElf_Addr build_id_vaddr = (build_id_elfaddr
+						  - elf_dynamic_vaddr + l_ld);
+
+		      release_buffer (0);
+		      int segndx = INTUSE(dwfl_addrsegment) (dwfl,
+							     build_id_vaddr,
+							     NULL);
+		      if (! (*memory_callback) (dwfl, segndx,
+						&buffer, &buffer_available,
+						build_id_vaddr, build_id_len,
+						memory_callback_arg))
+			{
+			  /* File has valid build-id which cannot be read from
+			     memory.  This happens for core files without bit 4
+			     (0x10) set in Linux /proc/PID/coredump_filter.  */
+			}
+		      else
+			{
+			  if (memcmp (build_id_bits, buffer, build_id_len) != 0)
+			    /* File has valid build-id which does not match
+			       the one in memory.  */
+			    valid = false;
+			  release_buffer (0);
+			}
+		    }
+
+		  if (valid)
+		    {
+		      // It is like l_addr but it handles differently prelinked
+		      // files at core dumping vs. core loading time.
+		      GElf_Addr base = l_ld - elf_dynamic_vaddr;
+		      if (r_debug_info_module == NULL)
+			{
+			  // XXX hook for sysroot
+			  mod = __libdwfl_report_elf (dwfl, basename (name),
+						      name, fd, elf, base,
+						      true, true);
+			  if (mod != NULL)
+			    {
+			      elf = NULL;
+			      fd = -1;
+			    }
+			}
+		      else if (__libdwfl_elf_address_range (elf, base, true,
+							    true, NULL, NULL,
+						    &r_debug_info_module->start,
+						    &r_debug_info_module->end,
+							    NULL, NULL))
+			{
+			  r_debug_info_module->elf = elf;
+			  r_debug_info_module->fd = fd;
+			  elf = NULL;
+			  fd = -1;
+			}
+		    }
+		  if (elf != NULL)
+		    elf_end (elf);
+		  if (fd != -1)
+		    close (fd);
 		}
 	    }
-
-	  if (name == NULL && mod->name[0] == '/')
-	    name = mod->name;
-
-	  /* If we don't have a file for it already, we can pre-install
-	     the full file name from l_name.  Opening the file by this
-	     name will be the fallback when no build ID match is found.
-	     XXX hook for sysroot */
-	  if (name != NULL && mod->main.name == NULL)
-	    mod->main.name = strdup (name);
-	}
-      else if (name != NULL)
-	{
-	  /* We have to find the file's phdrs to compute along with l_addr
-	     what its runtime address boundaries are.  */
-
-	  // XXX hook for sysroot
-	  mod = INTUSE(dwfl_report_elf) (dwfl, basename (name),
-					 name, -1, l_addr);
 	}
 
       if (mod != NULL)
@@ -473,7 +533,11 @@
      address where &r_debug was written at runtime.  */
   GElf_Xword align = mod->dwfl->segment_align;
   GElf_Addr d_val_vaddr = 0;
-  for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i)
+  size_t phnum;
+  if (elf_getphdrnum (mod->main.elf, &phnum) != 0)
+    return 0;
+
+  for (size_t i = 0; i < phnum; ++i)
     {
       GElf_Phdr phdr_mem;
       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
@@ -625,7 +689,8 @@
 int
 dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 		      Dwfl_Memory_Callback *memory_callback,
-		      void *memory_callback_arg)
+		      void *memory_callback_arg,
+		      struct r_debug_info *r_debug_info)
 {
   GElf_Addr r_debug_vaddr = 0;
 
@@ -639,29 +704,32 @@
       GElf_Xword phent = 0;
       GElf_Xword phnum = 0;
 
-#define AUXV_SCAN(NN, BL) do					\
-	{							\
-	  const Elf##NN##_auxv_t *av = auxv;			\
-	  for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)	\
-	    {							\
-	      Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val);	\
-	      if (av[i].a_type == BL##NN (AT_ENTRY))		\
-		entry = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PHDR))	\
-		phdr = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PHNUM))	\
-		phnum = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PHENT))	\
-		phent = val;					\
-	      else if (av[i].a_type == BL##NN (AT_PAGESZ))	\
-		{						\
-		  if (val > 1					\
-		      && (dwfl->segment_align == 0		\
-			  || val < dwfl->segment_align))	\
-		    dwfl->segment_align = val;			\
-		}						\
-	    }							\
-	}							\
+#define READ_AUXV32(ptr)	read_4ubyte_unaligned_noncvt (ptr)
+#define READ_AUXV64(ptr)	read_8ubyte_unaligned_noncvt (ptr)
+#define AUXV_SCAN(NN, BL) do                                            \
+	{                                                               \
+	  const Elf##NN##_auxv_t *av = auxv;                            \
+	  for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)         \
+	    {                                                           \
+              uint##NN##_t type = READ_AUXV##NN (&av[i].a_type);        \
+              uint##NN##_t val = BL##NN (READ_AUXV##NN (&av[i].a_un.a_val)); \
+	      if (type == BL##NN (AT_ENTRY))                            \
+		entry = val;                                            \
+	      else if (type == BL##NN (AT_PHDR))                        \
+		phdr = val;                                             \
+	      else if (type == BL##NN (AT_PHNUM))                       \
+		phnum = val;                                            \
+	      else if (type == BL##NN (AT_PHENT))                       \
+		phent = val;                                            \
+	      else if (type == BL##NN (AT_PAGESZ))                      \
+		{                                                       \
+		  if (val > 1                                           \
+		      && (dwfl->segment_align == 0                      \
+			  || val < dwfl->segment_align))                \
+		    dwfl->segment_align = val;                          \
+		}                                                       \
+	    }                                                           \
+	}                                                               \
       while (0)
 
       if (elfclass == ELFCLASS32)
@@ -720,8 +788,73 @@
 	      .d_size = phnum * phent,
 	      .d_buf = NULL
 	    };
-	  if ((*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size,
-				  phdr, phnum * phent, memory_callback_arg))
+	  bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
+					   &in.d_size, phdr, phnum * phent,
+					   memory_callback_arg);
+	  if (! in_ok && dwfl->executable_for_core != NULL)
+	    {
+	      /* AUXV -> PHDR -> DYNAMIC
+		 Both AUXV and DYNAMIC should be always present in a core file.
+		 PHDR may be missing in core file, try to read it from
+		 EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the
+		 core file.  */
+
+	      int fd = open (dwfl->executable_for_core, O_RDONLY);
+	      Elf *elf;
+	      Dwfl_Error error = DWFL_E_ERRNO;
+	      if (fd != -1)
+		error = __libdw_open_file (&fd, &elf, true, false);
+	      if (error != DWFL_E_NOERROR)
+		{
+		  __libdwfl_seterrno (error);
+		  return false;
+		}
+	      GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+	      if (ehdr == NULL)
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_LIBELF);
+		  return false;
+		}
+	      size_t e_phnum;
+	      if (elf_getphdrnum (elf, &e_phnum) != 0)
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_LIBELF);
+		  return false;
+		}
+	      if (e_phnum != phnum || ehdr->e_phentsize != phent)
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_BADELF);
+		  return false;
+		}
+	      off_t off = ehdr->e_phoff;
+	      assert (in.d_buf == NULL);
+	      assert (in.d_size == phnum * phent);
+	      in.d_buf = malloc (in.d_size);
+	      if (unlikely (in.d_buf == NULL))
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_NOMEM);
+		  return false;
+		}
+	      ssize_t nread = pread_retry (fd, in.d_buf, in.d_size, off);
+	      elf_end (elf);
+	      close (fd);
+	      if (nread != (ssize_t) in.d_size)
+		{
+		  free (in.d_buf);
+		  __libdwfl_seterrno (DWFL_E_ERRNO);
+		  return false;
+		}
+	      in_ok = true;
+	    }
+	  if (in_ok)
 	    {
 	      union
 	      {
@@ -883,6 +1016,6 @@
 
   /* Now we can follow the dynamic linker's library list.  */
   return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
-			 &integrated_memory_callback, &mcb);
+			 &integrated_memory_callback, &mcb, r_debug_info);
 }
 INTDEF (dwfl_link_map_report)