Fix resolving ELF symbols for live PIDs with deleted files
[platform/upstream/elfutils.git] / libdwfl / libdwflP.h
index e4c7e7c..30c0f8a 100644 (file)
@@ -1,51 +1,30 @@
 /* Internal definitions for libdwfl.
-   Copyright (C) 2005-2010 Red Hat, Inc.
-   This file is part of Red Hat elfutils.
+   Copyright (C) 2005-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/>.  */
 
 #ifndef _LIBDWFLP_H
 #define _LIBDWFLP_H    1
 #include <libdwfl.h>
 #include <libebl.h>
 #include <assert.h>
+#include <dirent.h>
 #include <errno.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "../libdw/libdwP.h"   /* We need its INTDECLs.  */
+#include "../libdwelf/libdwelfP.h"
+
+typedef struct Dwfl_Process Dwfl_Process;
 
 /* gettext helper macros.  */
 #define _(Str) dgettext ("elfutils", Str)
   DWFL_ERROR (ALREADY_ELF, N_("ELF file opened"))                            \
   DWFL_ERROR (BADELF, N_("not a valid ELF file"))                            \
   DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description"))        \
-  DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID"))
+  DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID"))          \
+  DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data"))      \
+  DWFL_ERROR (LIBEBL_BAD, N_("Internal error due to ebl"))                   \
+  DWFL_ERROR (CORE_MISSING, N_("Missing data in core file"))                 \
+  DWFL_ERROR (INVALID_REGISTER, N_("Invalid register"))                              \
+  DWFL_ERROR (PROCESS_MEMORY_READ, N_("Error reading process memory"))       \
+  DWFL_ERROR (PROCESS_NO_ARCH, N_("Couldn't find architecture of any ELF"))   \
+  DWFL_ERROR (PARSE_PROC, N_("Error parsing /proc filesystem"))                      \
+  DWFL_ERROR (INVALID_DWARF, N_("Invalid DWARF"))                            \
+  DWFL_ERROR (UNSUPPORTED_DWARF, N_("Unsupported DWARF"))                    \
+  DWFL_ERROR (NEXT_THREAD_FAIL, N_("Unable to find more threads"))           \
+  DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state"))   \
+  DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state"))             \
+  DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \
+  DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument"))                              \
+  DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file"))
 
 #define DWFL_ERROR(name, text) DWFL_E_##name,
 typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
@@ -112,6 +110,9 @@ struct Dwfl
 
   Dwfl_Module *modulelist;    /* List in order used by full traversals.  */
 
+  Dwfl_Process *process;
+  Dwfl_Error attacherr;      /* Previous error attaching process.  */
+
   GElf_Addr offline_next_address;
 
   GElf_Addr segment_align;     /* Smallest granularity of segments.  */
@@ -128,6 +129,8 @@ struct Dwfl
   GElf_Off lookup_tail_vaddr;
   GElf_Off lookup_tail_offset;
   int lookup_tail_ndx;
+
+  char *executable_for_core;   /* --executable if --core was specified.  */
 };
 
 #define OFFLINE_REDZONE                0x10000
@@ -140,7 +143,14 @@ struct dwfl_file
   bool relocated;              /* Partial relocation of all sections done.  */
 
   Elf *elf;
-  GElf_Addr bias;              /* Actual load address - p_vaddr.  */
+
+  /* This is the lowest p_vaddr in this ELF file, aligned to p_align.
+     For a file without phdrs, this is zero.  */
+  GElf_Addr vaddr;
+
+  /* This is an address chosen for synchronization between the main file
+     and the debug file.  See dwfl_module_getdwarf.c for how it's chosen.  */
+  GElf_Addr address_sync;
 };
 
 struct Dwfl_Module
@@ -153,7 +163,8 @@ struct Dwfl_Module
   char *name;                  /* Iterator name for this module.  */
   GElf_Addr low_addr, high_addr;
 
-  struct dwfl_file main, debug;
+  struct dwfl_file main, debug, aux_sym;
+  GElf_Addr main_bias;
   Ebl *ebl;
   GElf_Half e_type;            /* GElf_Ehdr.e_type cache.  */
   Dwfl_Error elferr;           /* Previous failure to open main file.  */
@@ -162,11 +173,20 @@ struct Dwfl_Module
 
   struct dwfl_file *symfile;   /* Either main or debug.  */
   Elf_Data *symdata;           /* Data in the ELF symbol table section.  */
+  Elf_Data *aux_symdata;       /* Data in the auxiliary ELF symbol table.  */
   size_t syments;              /* sh_size / sh_entsize of that section.  */
+  size_t aux_syments;          /* sh_size / sh_entsize of aux_sym section.  */
+  int first_global;            /* Index of first global symbol of table.  */
+  int aux_first_global;                /* Index of first global of aux_sym table.  */
   Elf_Data *symstrdata;                /* Data for its string table.  */
+  Elf_Data *aux_symstrdata;    /* Data for aux_sym string table.  */
   Elf_Data *symxndxdata;       /* Data in the extended section index table. */
+  Elf_Data *aux_symxndxdata;   /* Data in the extended auxiliary table. */
 
   Dwarf *dw;                   /* libdw handle for its debugging info.  */
+  Dwarf *alt;                  /* Dwarf used for dwarf_setalt, or NULL.  */
+  int alt_fd;                  /* descriptor, only valid when alt != NULL.  */
+  Elf *alt_elf;                /* Elf for alt Dwarf.  */
 
   Dwfl_Error symerr;           /* Previous failure to load symbols.  */
   Dwfl_Error dwerr;            /* Previous failure to load DWARF.  */
@@ -193,7 +213,72 @@ struct Dwfl_Module
   bool gc;                     /* Mark/sweep flag.  */
 };
 
+/* This holds information common for all the threads/tasks/TIDs of one process
+   for backtraces.  */
+
+struct Dwfl_Process
+{
+  struct Dwfl *dwfl;
+  pid_t pid;
+  const Dwfl_Thread_Callbacks *callbacks;
+  void *callbacks_arg;
+  struct ebl *ebl;
+  bool ebl_close:1;
+};
+
+/* See its typedef in libdwfl.h.  */
+
+struct Dwfl_Thread
+{
+  Dwfl_Process *process;
+  pid_t tid;
+  /* The current frame being unwound.  Initially it is the bottom frame.
+     Later the processed frames get freed and this pointer is updated.  */
+  Dwfl_Frame *unwound;
+  void *callbacks_arg;
+};
+
+/* See its typedef in libdwfl.h.  */
 
+struct Dwfl_Frame
+{
+  Dwfl_Thread *thread;
+  /* Previous (outer) frame.  */
+  Dwfl_Frame *unwound;
+  bool signal_frame : 1;
+  bool initial_frame : 1;
+  enum
+  {
+    /* This structure is still being initialized or there was an error
+       initializing it.  */
+    DWFL_FRAME_STATE_ERROR,
+    /* PC field is valid.  */
+    DWFL_FRAME_STATE_PC_SET,
+    /* PC field is undefined, this means the next (inner) frame was the
+       outermost frame.  */
+    DWFL_FRAME_STATE_PC_UNDEFINED
+  } pc_state;
+  /* Either initialized from appropriate REGS element or on some archs
+     initialized separately as the return address has no DWARF register.  */
+  Dwarf_Addr pc;
+  /* (1 << X) bitmask where 0 <= X < ebl_frame_nregs.  */
+  uint64_t regs_set[3];
+  /* REGS array size is ebl_frame_nregs.
+     REGS_SET tells which of the REGS are valid.  */
+  Dwarf_Addr regs[];
+};
+
+/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO.
+   No error code is set if the function returns FALSE.  */
+bool __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno,
+                             Dwarf_Addr *val)
+  internal_function;
+
+/* Store value to Dwfl_Frame->regs indexed by DWARF REGNO.
+   No error code is set if the function returns FALSE.  */
+bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno,
+                             Dwarf_Addr val)
+  internal_function;
 
 /* Information cached about each CU in Dwfl_Module.dw.  */
 struct dwfl_cu
@@ -236,6 +321,70 @@ dwfl_linecu_inline (const Dwfl_Line *line)
 }
 #define dwfl_linecu dwfl_linecu_inline
 
+static inline GElf_Addr
+dwfl_adjusted_address (Dwfl_Module *mod, GElf_Addr addr)
+{
+  return addr + mod->main_bias;
+}
+
+static inline GElf_Addr
+dwfl_deadjust_address (Dwfl_Module *mod, GElf_Addr addr)
+{
+  return addr - mod->main_bias;
+}
+
+static inline Dwarf_Addr
+dwfl_adjusted_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return dwfl_adjusted_address (mod, (addr
+                                     - mod->debug.address_sync
+                                     + mod->main.address_sync));
+}
+
+static inline Dwarf_Addr
+dwfl_deadjust_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return (dwfl_deadjust_address (mod, addr)
+         - mod->main.address_sync
+         + mod->debug.address_sync);
+}
+
+static inline Dwarf_Addr
+dwfl_adjusted_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return dwfl_adjusted_address (mod, (addr
+                                     - mod->aux_sym.address_sync
+                                     + mod->main.address_sync));
+}
+
+static inline Dwarf_Addr
+dwfl_deadjust_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return (dwfl_deadjust_address (mod, addr)
+         - mod->main.address_sync
+         + mod->aux_sym.address_sync);
+}
+
+static inline GElf_Addr
+dwfl_adjusted_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
+{
+  if (symelf == mod->main.elf)
+    return dwfl_adjusted_address (mod, addr);
+  if (symelf == mod->debug.elf)
+    return dwfl_adjusted_dwarf_addr (mod, addr);
+  return dwfl_adjusted_aux_sym_addr (mod, addr);
+}
+
+static inline GElf_Addr
+dwfl_deadjust_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
+{
+  if (symelf == mod->main.elf)
+    return dwfl_deadjust_address (mod, addr);
+  if (symelf == mod->debug.elf)
+    return dwfl_deadjust_dwarf_addr (mod, addr);
+  return dwfl_deadjust_aux_sym_addr (mod, addr);
+}
+
 /* This describes a contiguous address range that lies in a single CU.
    We condense runs of Dwarf_Arange entries for the same CU into this.  */
 struct dwfl_arange
@@ -245,6 +394,56 @@ struct dwfl_arange
 };
 
 
+/* Structure used for keeping track of ptrace attaching a thread.
+   Shared by linux-pid-attach and linux-proc-maps.  If it has been setup
+   then get the instance through __libdwfl_get_pid_arg.  */
+struct __libdwfl_pid_arg
+{
+  DIR *dir;
+  /* It is 0 if not used.  */
+  pid_t tid_attached;
+  /* Valid only if TID_ATTACHED is not zero.  */
+  bool tid_was_stopped;
+  /* True if threads are ptrace stopped by caller.  */
+  bool assume_ptrace_stopped;
+};
+
+/* If DWfl is not NULL and a Dwfl_Process has been setup that has
+   Dwfl_Thread_Callbacks set to pid_thread_callbacks, then return the
+   callbacks_arg, which will be a struct __libdwfl_pid_arg.  Otherwise
+   returns NULL.  */
+extern struct __libdwfl_pid_arg *__libdwfl_get_pid_arg (Dwfl *dwfl)
+  internal_function;
+
+/* Makes sure the given tid is attached. On success returns true and
+   sets tid_was_stopped.  */
+extern bool __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
+  internal_function;
+
+/* Detaches a tid that was attached through
+   __libdwfl_ptrace_attach. Must be given the tid_was_stopped as set
+   by __libdwfl_ptrace_attach.  */
+extern void __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
+  internal_function;
+
+
+/* Internal wrapper for old dwfl_module_getsym and new dwfl_module_getsym_info.
+   adjust_st_value set to true returns adjusted SYM st_value, set to false
+   it will not adjust SYM at all, but does match against resolved *ADDR. */
+extern const char *__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym,
+                                    GElf_Addr *addr, GElf_Word *shndxp,
+                                    Elf **elfp, Dwarf_Addr *biasp,
+                                    bool *resolved, bool adjust_st_value)
+  internal_function;
+
+/* Internal wrapper for old dwfl_module_addrsym and new dwfl_module_addrinfo.
+   adjust_st_value set to true returns adjusted SYM st_value, set to false
+   it will not adjust SYM at all, but does match against resolved values. */
+extern const char *__libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr,
+                                     GElf_Off *off, GElf_Sym *sym,
+                                     GElf_Word *shndxp, Elf **elfp,
+                                     Dwarf_Addr *bias,
+                                     bool adjust_st_value) internal_function;
 
 extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function;
 
@@ -261,6 +460,12 @@ extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function;
 extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug)
   internal_function;
 
+/* Find the section index in mod->main.elf that contains the given
+   *ADDR.  Adjusts *ADDR to be section relative on success, returns
+   SHN_UNDEF on failure.  */
+extern size_t __libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr)
+  internal_function;
+
 /* Process (simple) relocations in arbitrary section TSCN of an ET_REL file.
    RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section.  */
 extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
@@ -277,7 +482,6 @@ extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf,
                                            GElf_Addr *value)
      internal_function;
 
-
 /* Ensure that MOD->ebl is set up.  */
 extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
 
@@ -300,6 +504,17 @@ extern Dwfl_Error __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr,
 extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu)
   internal_function;
 
+/* Look in ELF for an NT_GNU_BUILD_ID note.  Store it to BUILD_ID_BITS,
+   its vaddr in ELF to BUILD_ID_VADDR (it is unrelocated, even if MOD is not
+   NULL) and store length to BUILD_ID_LEN.  Returns -1 for errors, 1 if it was
+   stored and 0 if no note is found.  MOD may be NULL, MOD must be non-NULL
+   only if ELF is ET_REL.  */
+extern int __libdwfl_find_elf_build_id (Dwfl_Module *mod, Elf *elf,
+                                       const void **build_id_bits,
+                                       GElf_Addr *build_id_elfaddr,
+                                       int *build_id_len)
+  internal_function;
+
 /* Look in ELF for an NT_GNU_BUILD_ID note.  If SET is true, store it
    in MOD and return its length.  If SET is false, instead compare it
    to that stored in MOD and return 2 if they match, 1 if they do not.
@@ -308,19 +523,35 @@ extern int __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
   internal_function;
 
 /* Open a main or debuginfo file by its build ID, returns the fd.  */
+extern int __libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug,
+                                          char **file_name) internal_function;
+
+/* Same, but takes an explicit build_id, can also be used for alt debug.  */
 extern int __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug,
-                                      char **file_name) internal_function;
+                                      char **file_name, const size_t id_len,
+                                      const uint8_t *id) internal_function;
 
 extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len)
   attribute_hidden;
 extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden;
 
 
+/* Given ELF and some parameters return TRUE if the *P return value parameters
+   have been successfully filled in.  Any of the *P parameters can be NULL.  */
+extern bool __libdwfl_elf_address_range (Elf *elf, GElf_Addr base,
+                                        bool add_p_vaddr, bool sanity,
+                                        GElf_Addr *vaddrp,
+                                        GElf_Addr *address_syncp,
+                                        GElf_Addr *startp, GElf_Addr *endp,
+                                        GElf_Addr *biasp, GElf_Half *e_typep)
+  internal_function;
+
 /* Meat of dwfl_report_elf, given elf_begin just called.
    Consumes ELF on success, not on failure.  */
 extern Dwfl_Module *__libdwfl_report_elf (Dwfl *dwfl, const char *name,
                                          const char *file_name, int fd,
-                                         Elf *elf, GElf_Addr base, bool sanity)
+                                         Elf *elf, GElf_Addr base,
+                                         bool add_p_vaddr, bool sanity)
   internal_function;
 
 /* Meat of dwfl_report_offline.  */
@@ -331,6 +562,25 @@ extern Dwfl_Module *__libdwfl_report_offline (Dwfl *dwfl, const char *name,
                                                                const char *))
   internal_function;
 
+/* Free PROCESS.  Unlink and free also any structures it references.  */
+extern void __libdwfl_process_free (Dwfl_Process *process)
+  internal_function;
+
+/* Update STATE->unwound for the unwound frame.
+   On error STATE->unwound == NULL
+   or STATE->unwound->pc_state == DWFL_FRAME_STATE_ERROR;
+   in such case dwfl_errno () is set.
+   If STATE->unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED
+   then STATE was the last valid frame.  */
+extern void __libdwfl_frame_unwind (Dwfl_Frame *state)
+  internal_function;
+
+/* Align segment START downwards or END upwards addresses according to DWFL.  */
+extern GElf_Addr __libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
+  internal_function;
+extern GElf_Addr __libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end)
+  internal_function;
+
 /* Decompression wrappers: decompress whole file into memory.  */
 extern Dwfl_Error __libdw_gunzip  (int fd, off64_t start_offset,
                                   void *mapped, size_t mapped_size,
@@ -358,6 +608,11 @@ extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp,
                                     bool close_on_fail, bool archive_ok)
   internal_function;
 
+/* Fetch PT_DYNAMIC P_VADDR from ELF and store it to *VADDRP.  Return success.
+   *VADDRP is not modified if the function fails.  */
+extern bool __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
+  internal_function;
+
 /* These are working nicely for --core, but are not ready to be
    exported interfaces quite yet.  */
 
@@ -376,13 +631,35 @@ typedef bool Dwfl_Module_Callback (Dwfl_Module *mod, void **userdata,
                                   GElf_Off whole, GElf_Off contiguous,
                                   void *arg, Elf **elfp);
 
+/* One shared library (or executable) info from DT_DEBUG link map.  */
+struct r_debug_info_module
+{
+  struct r_debug_info_module *next;
+  /* FD is -1 iff ELF is NULL.  */
+  int fd;
+  Elf *elf;
+  GElf_Addr l_ld;
+  /* START and END are both zero if not valid.  */
+  GElf_Addr start, end;
+  bool disk_file_has_build_id;
+  char name[0];
+};
+
+/* Information gathered from DT_DEBUG by dwfl_link_map_report hinted to
+   dwfl_segment_report_module.  */
+struct r_debug_info
+{
+  struct r_debug_info_module *module;
+};
+
 /* ...
  */
 extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
                                       Dwfl_Memory_Callback *memory_callback,
                                       void *memory_callback_arg,
                                       Dwfl_Module_Callback *read_eagerly,
-                                      void *read_eagerly_arg);
+                                      void *read_eagerly_arg,
+                                      const struct r_debug_info *r_debug_info);
 
 /* Report a module for entry in the dynamic linker's struct link_map list.
    For each link_map entry, if an existing module resides at its address,
@@ -396,10 +673,16 @@ extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
    only find where to begin if the correct executable file was
    previously reported and preloaded as with dwfl_report_elf.
 
+   Fill in R_DEBUG_INFO if it is not NULL.  It should be cleared by the
+   caller, this function does not touch fields it does not need to modify.
+   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.
+
    Returns the number of modules found, or -1 for errors.  */
 extern 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);
 
 
 /* Avoid PLT entries.  */
@@ -410,16 +693,20 @@ INTDECL (dwfl_addrmodule)
 INTDECL (dwfl_addrsegment)
 INTDECL (dwfl_addrdwarf)
 INTDECL (dwfl_addrdie)
+INTDECL (dwfl_core_file_attach)
 INTDECL (dwfl_core_file_report)
 INTDECL (dwfl_getmodules)
 INTDECL (dwfl_module_addrdie)
 INTDECL (dwfl_module_address_section)
+INTDECL (dwfl_module_addrinfo)
 INTDECL (dwfl_module_addrsym)
 INTDECL (dwfl_module_build_id)
 INTDECL (dwfl_module_getdwarf)
 INTDECL (dwfl_module_getelf)
 INTDECL (dwfl_module_getsym)
+INTDECL (dwfl_module_getsym_info)
 INTDECL (dwfl_module_getsymtab)
+INTDECL (dwfl_module_getsymtab_first_global)
 INTDECL (dwfl_module_getsrc)
 INTDECL (dwfl_module_report_build_id)
 INTDECL (dwfl_report_elf)
@@ -435,6 +722,7 @@ INTDECL (dwfl_standard_find_debuginfo)
 INTDECL (dwfl_link_map_report)
 INTDECL (dwfl_linux_kernel_find_elf)
 INTDECL (dwfl_linux_kernel_module_section_address)
+INTDECL (dwfl_linux_proc_attach)
 INTDECL (dwfl_linux_proc_report)
 INTDECL (dwfl_linux_proc_maps_report)
 INTDECL (dwfl_linux_proc_find_elf)
@@ -445,6 +733,17 @@ INTDECL (dwfl_offline_section_address)
 INTDECL (dwfl_module_relocate_address)
 INTDECL (dwfl_module_dwarf_cfi)
 INTDECL (dwfl_module_eh_cfi)
+INTDECL (dwfl_attach_state)
+INTDECL (dwfl_pid)
+INTDECL (dwfl_thread_dwfl)
+INTDECL (dwfl_thread_tid)
+INTDECL (dwfl_frame_thread)
+INTDECL (dwfl_thread_state_registers)
+INTDECL (dwfl_thread_state_register_pc)
+INTDECL (dwfl_getthread_frames)
+INTDECL (dwfl_getthreads)
+INTDECL (dwfl_thread_getframes)
+INTDECL (dwfl_frame_pc)
 
 /* Leading arguments standard to callbacks passed a Dwfl_Module.  */
 #define MODCB_ARGS(mod)        (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr