]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Direct relocation handling in libdw reader.
authorRoland McGrath <roland@redhat.com>
Sun, 20 Jun 2010 23:36:00 +0000 (16:36 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 21 Jun 2010 10:02:03 +0000 (03:02 -0700)
14 files changed:
libdw/ChangeLog
libdw/Makefile.am
libdw/dwarf_begin_elf.c
libdw/dwarf_end.c
libdw/dwarf_error.c
libdw/dwarf_getsrc_file.c
libdw/dwarf_getsrclines.c
libdw/dwarf_lineaddr.c
libdw/dwarf_linesrc.c
libdw/libdwP.h
libdw/relocate.c [new file with mode: 0644]
libdwfl/ChangeLog
libdwfl/dwfl_lineinfo.c
libdwfl/dwfl_module_getsrc_file.c

index 021996d9447c5f83fd1c2e610cdcfe5e19c6f37a..b6fe88502eb33b7a8fed3aaedc7e332a606c8b79 100644 (file)
@@ -1,5 +1,37 @@
+2010-06-21  Roland McGrath  <roland@redhat.com>
+
+       * libdwP.h (struct Dwarf_Line_s): Replace files with cu.
+       (struct Dwarf_Lines_s): New member reloc.
+       * dwarf_linesrc.c: Update usage.
+       * dwarf_getsrc_file.c: Likewise.
+       * dwarf_getsrclines.c: Record relocatable address locations in
+       parallel array, with Dwarf_Line.addr becoming a relative offset.
+       * dwarf_lineaddr.c: Use __libdw_read_address on demand for a
+       relocatable line address.
+
 2010-06-20  Roland McGrath  <roland@redhat.com>
 
+       * relocate.c: New file.
+       * Makefile.am (libdw_a_SOURCES): Add it.
+       * libdwP.h (struct dwarf_file_reloc): New type.
+       (struct Dwarf): New member relocate.
+       (__libdw_relocate_address, __libdw_relocate_offset): Replace inlines
+       with extern decls.
+       (READ_AND_RELOCATE): Call RELOC_HOOK if DBG->relocate,
+       else read directly.
+       (__libdw_read_address, __libdw_read_offset): Just call *_inc variant.
+       (__libdw_relocate_begin, __libdw_relocate_end): Declare them.
+       * dwarf_begin_elf.c (check_section): Take new args to track reloc
+       sections.
+       (global_read, scngrp_read): Pass new args through to check_section.
+       (dwarf_begin_elf): Track reloc sections in an ET_REL file,
+       call __libdw_relocate_begin.
+
+       * libdwP.h (DWARF_E_RELOC, DWARF_E_RELBADTYPE): New enum constants.
+       (DWARF_E_RELBADADDEND, DWARF_E_RELBADOFF): Likewise.
+       (DWARF_E_RELBADSYM, DWARF_E_RELUNDEF, DWARF_E_RELWRONGSEC): Likewise.
+       * dwarf_error.c (errmsgs): Add them.
+
        * cfi.h (BYTE_ORDER_DUMMY): Macro moved ...
        * memory-access.h: ... here.
 
@@ -7,6 +39,7 @@
        to search TUs instead of CUs.
        * libdwP.h: Update decl.
        (struct Dwarf): New member tu_tree.
+
        * dwarf_end.c (dwarf_end): Clean up tu_tree.
        * dwarf_offdie.c (do_offdie): New function, broken out of ...
        (dwarf_offdie): ... here.
index 530cbf4b26acdf854ad6b93729f3de0375f2718b..6b0c0734b569b9dafb6a1f23eebc9a9cce09c141 100644 (file)
@@ -84,7 +84,8 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
                  dwarf_frame_info.c dwarf_frame_cfa.c dwarf_frame_register.c \
                  dwarf_cfi_addrframe.c \
                  dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \
-                 dwarf_aggregate_size.c
+                 dwarf_aggregate_size.c \
+                 relocate.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
index b5fb7c91f58ff7cf78241bb7b7f36fc5fe306727..c8efc1714c0effbe0c5592fbf15ad2cd50a6c7ff 100644 (file)
@@ -52,6 +52,7 @@
 # include <config.h>
 #endif
 
+#include <assert.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdlib.h>
@@ -81,7 +82,9 @@ static const char dwarf_scnnames[IDX_last][17] =
 
 
 static Dwarf *
-check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
+check_section (Dwarf *result, GElf_Ehdr *ehdr,
+              uint8_t scn_debug[], size_t shnum, Elf_Scn *relscn[IDX_last],
+              Elf_Scn *scn, bool inscngrp)
 {
   GElf_Shdr shdr_mem;
   GElf_Shdr *shdr;
@@ -123,9 +126,40 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
     }
 
 
+  /* This might be a relocation section.  */
+  if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+    {
+      if (scn_debug != NULL
+         && likely (shdr->sh_info != 0)
+         && likely (shdr->sh_info < shnum))
+       {
+         if (scn_debug[shdr->sh_info] < IDX_last)
+           {
+             /* This section has relocations for a debug section
+                we have already noticed.  */
+             relscn[scn_debug[shdr->sh_info]] = scn;
+             if (scn_debug[0] != IDX_debug_info)
+               scn_debug[0] = IDX_debug_abbrev;
+           }
+         else if (unlikely (shdr->sh_info > elf_ndxscn (scn)))
+           {
+             /* A relocation section usually follows its target section.
+                But there is no guarantee.  */
+             GElf_Shdr tshdr_mem;
+             GElf_Shdr *tshdr = gelf_getshdr (elf_getscn (result->elf,
+                                                          shdr->sh_info),
+                                              &tshdr_mem);
+             if (likely (tshdr != NULL))
+               /* Mark that we need a second pass.  */
+               scn_debug[0] = IDX_debug_info;
+           }
+       }
+      return result;
+    }
+
+
   /* Recognize the various sections.  Most names start with .debug_.  */
-  size_t cnt;
-  for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
+  for (uint_fast8_t cnt = 0; cnt < ndwarf_scnnames; ++cnt)
     if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
       {
        /* Found it.  Remember where the data is.  */
@@ -136,8 +170,12 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
        /* Get the section data.  */
        Elf_Data *data = elf_getdata (scn, NULL);
        if (data != NULL && data->d_size != 0)
-         /* Yep, there is actually data available.  */
-         result->sectiondata[cnt] = data;
+         {
+           /* Yep, there is actually data available.  */
+           result->sectiondata[cnt] = data;
+           if (scn_debug != NULL)
+             scn_debug[elf_ndxscn (scn)] = cnt;
+         }
 
        break;
       }
@@ -169,19 +207,22 @@ valid_p (Dwarf *result)
 
 
 static Dwarf *
-global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr)
+global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr,
+            uint8_t scn_debug[], size_t shnum, Elf_Scn *relscn[IDX_last])
 {
   Elf_Scn *scn = NULL;
 
   while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
-    result = check_section (result, ehdr, scn, false);
+    result = check_section (result, ehdr, scn_debug, shnum, relscn, scn, false);
 
   return valid_p (result);
 }
 
 
 static Dwarf *
-scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
+scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr,
+            uint8_t scn_debug[], size_t shnum, Elf_Scn *relscn[IDX_last],
+            Elf_Scn *scngrp)
 {
   /* SCNGRP is the section descriptor for a section group which might
      contain debug sections.  */
@@ -209,7 +250,8 @@ scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
          return NULL;
        }
 
-      result = check_section (result, ehdr, scn, true);
+      result = check_section (result, ehdr, scn_debug, shnum, relscn,
+                             scn, true);
       if (result == NULL)
        break;
     }
@@ -272,15 +314,38 @@ dwarf_begin_elf (elf, cmd, scngrp)
 
   if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
     {
-      /* If the caller provides a section group we get the DWARF
-        sections only from this setion group.  Otherwise we search
-        for the first section with the required name.  Further
-        sections with the name are ignored.  The DWARF specification
-        does not really say this is allowed.  */
-      if (scngrp == NULL)
-       return global_read (result, elf, ehdr);
+      inline void read_it (uint8_t scn_debug[], size_t shnum,
+                          Elf_Scn *relscn[IDX_last])
+      {
+       /* If the caller provides a section group we get the DWARF
+          sections only from this setion group.  Otherwise we search
+          for the first section with the required name.  Further
+          sections with the name are ignored.  The DWARF specification
+          does not really say this is allowed.  */
+       if (scngrp == NULL)
+         result = global_read (result, elf, ehdr, scn_debug, shnum, relscn);
+       else
+         result = scngrp_read (result, elf, ehdr, scn_debug, shnum, relscn,
+                               scngrp);
+      }
+
+      if (ehdr->e_type == ET_REL)
+       {
+         Elf_Scn *relscn[IDX_last] = {};
+         size_t shnum;
+         int ret = elf_getshdrnum (elf, &shnum);
+         assert (ret == 0);
+         uint8_t scn_debug[shnum];
+         memset (scn_debug, IDX_last, shnum);
+         read_it (scn_debug, shnum, relscn);
+         if (result != NULL && scn_debug[0] != IDX_last)
+           /* We saw some relocation sections.  */
+           __libdw_relocate_begin (result, relscn,
+                                   scn_debug[0] == IDX_debug_info);
+       }
       else
-       return scngrp_read (result, elf, ehdr, scngrp);
+       read_it (NULL, 0, NULL);
+      return result;
     }
   else if (cmd == DWARF_C_WRITE)
     {
index ec10542e5c11f3a8e180abddfaa126bd06b78260..94b9b87606e0dcc2f52614c08014751a3d5362d5 100644 (file)
@@ -94,6 +94,10 @@ dwarf_end (dwarf)
       tdestroy (dwarf->cu_tree, cu_free);
       tdestroy (dwarf->tu_tree, cu_free);
 
+      if (dwarf->relocate != NULL)
+       /* Clean up relocation tracking.  */
+       __libdw_relocate_end (dwarf);
+
       struct libdw_memblock *memp = dwarf->mem_tail;
       /* The first block is allocated together with the Dwarf object.  */
       while (memp->prev != NULL)
index 0d95b8d20f718458664cf3ac1f7bbf732ccd5033..503c9c4c19e2e73df477d6cdbb87360a7717af31 100644 (file)
@@ -1,5 +1,5 @@
 /* Retrieve ELF descriptor used for DWARF access.
-   Copyright (C) 2002, 2003, 2004, 2005, 2009 Red Hat, Inc.
+   Copyright (C) 2002-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -112,6 +112,13 @@ static const char *errmsgs[] =
     [DWARF_E_INVALID_OFFSET] = N_("invalid offset"),
     [DWARF_E_NO_DEBUG_RANGES] = N_(".debug_ranges section missing"),
     [DWARF_E_INVALID_CFI] = N_("invalid CFI section"),
+    [DWARF_E_RELOC] = N_("value requires relocation"),
+    [DWARF_E_RELBADTYPE] = N_("unsupported relocation type"),
+    [DWARF_E_RELBADADDEND] = N_("relocation addend overflow"),
+    [DWARF_E_RELBADOFF] = N_("relocation at invalid offset"),
+    [DWARF_E_RELBADSYM] = N_("relocation refers to invalid symbol"),
+    [DWARF_E_RELUNDEF] = N_("relocation refers to undefined symbol"),
+    [DWARF_E_RELWRONGSEC] = N_("relocation refers to wrong DWARF section"),
   };
 #define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0]))
 
index bc612f6c6ca55f8c6bc45c3f69d1a37e0366246e..57a5382ab310e4e373683bcaf3b97851629babc8 100644 (file)
@@ -1,5 +1,5 @@
 /* Find line information for given file/line/column triple.
-   Copyright (C) 2005-2009 Red Hat, Inc.
+   Copyright (C) 2005-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2005.
 
@@ -110,14 +110,14 @@ dwarf_getsrc_file (Dwarf *dbg, const char *fname, int lineno, int column,
          if (lastfile != line->file)
            {
              lastfile = line->file;
-             if (lastfile >= line->files->nfiles)
+             if (lastfile >= line->cu->files->nfiles)
                {
                  __libdw_seterrno (DWARF_E_INVALID_DWARF);
                  return -1;
                }
 
              /* Match the name with the name the user provided.  */
-             const char *fname2 = line->files->info[lastfile].name;
+             const char *fname2 = line->cu->files->info[lastfile].name;
              if (is_basename)
                lastmatch = strcmp (basename (fname2), fname) == 0;
              else
@@ -136,7 +136,7 @@ dwarf_getsrc_file (Dwarf *dbg, const char *fname, int lineno, int column,
          /* Determine whether this is the best match so far.  */
          size_t inner;
          for (inner = 0; inner < cur_match; ++inner)
-           if (match[inner]->files == line->files
+           if (match[inner]->cu->files == line->cu->files
                && match[inner]->file == line->file)
              break;
          if (inner < cur_match
index afdf9dba7e6410f5e31071abca7c50f4c6fa8ef5..bdff80de56dccc867852a6367561e71666e160b2 100644 (file)
@@ -68,6 +68,7 @@ struct filelist
 struct linelist
 {
   Dwarf_Line line;
+  const unsigned char *reloc;
   struct linelist *next;
 };
 
@@ -323,6 +324,7 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
 
         /* We are about to process the statement program.  Initialize the
           state machine registers (see 6.2.2 in the v2.1 specification).  */
+      const unsigned char *addr_reloc = NULL;
       Dwarf_Word addr = 0;
       unsigned int op_index = 0;
       unsigned int file = 1;
@@ -385,6 +387,7 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
 
 #undef SET
 
+       new_line->reloc = addr_reloc;
        new_line->next = linelist;
        linelist = new_line;
        ++nlinelist;
@@ -450,6 +453,7 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
 
                  /* Reset the registers.  */
                  addr = 0;
+                 addr_reloc = NULL;
                  op_index = 0;
                  file = 1;
                  line = 1;
@@ -469,8 +473,19 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
                  op_index = 0;
                  if (unlikely (lineendp - linep < cu->address_size))
                    goto invalid_data;
-                 if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
-                                               cu->address_size, &addr))
+                 if (dbg->relocate != NULL
+                     && dbg->relocate->sectionrel[IDX_debug_line] != NULL)
+                   {
+                     /* We're just recording a relocatable address
+                        and offsets from it.  We'll do the relocation
+                        only lazily in dwarf_lineaddr.  */
+                     addr = 0;
+                     addr_reloc = linep;
+                     linep += cu->address_size;
+                   }
+                 else if (__libdw_read_address_inc (dbg, IDX_debug_line,
+                                                    &linep, cu->address_size,
+                                                    &addr))
                    goto out;
                  break;
 
@@ -703,9 +718,9 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
         We'll write the pointers in the end of the buffer, and then
         copy into the buffer from the beginning so the overlap works.  */
       assert (sizeof (Dwarf_Line) >= sizeof (Dwarf_Line *));
-      Dwarf_Line **sortlines = (buf + sizeof (Dwarf_Lines)
-                               + ((sizeof (Dwarf_Line)
-                                   - sizeof (Dwarf_Line *)) * nlinelist));
+      struct linelist **sortlines = (buf + sizeof (Dwarf_Lines)
+                                    + ((sizeof (Dwarf_Line)
+                                        - sizeof (Dwarf_Line *)) * nlinelist));
 
       /* The list is in LIFO order and usually they come in clumps with
         ascending addresses.  So fill from the back to probably start with
@@ -713,7 +728,7 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
       unsigned int i = nlinelist;
       while (i-- > 0)
        {
-         sortlines[i] = &linelist->line;
+         sortlines[i] = linelist;
          linelist = linelist->next;
        }
       assert (linelist == NULL);
@@ -726,10 +741,24 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
         of SORTLINES by the time we're reading the later ones.  */
       cu->lines = buf;
       cu->lines->nlines = nlinelist;
+
+      if (cu->dbg->relocate != NULL
+         && cu->dbg->relocate->sectionrel[IDX_debug_line] != NULL)
+       {
+         /* Add a parallel table of relocation pointers.  */
+         cu->lines->reloc = libdw_alloc (cu->dbg, const unsigned char *,
+                                         sizeof (const unsigned char *),
+                                         nlinelist);
+         for (i = 0; i < nlinelist; ++i)
+           cu->lines->reloc[i] = sortlines[i]->reloc;
+       }
+      else
+       cu->lines->reloc = NULL;
+
       for (i = 0; i < nlinelist; ++i)
        {
-         cu->lines->info[i] = *sortlines[i];
-         cu->lines->info[i].files = files;
+         cu->lines->info[i] = sortlines[i]->line;
+         cu->lines->info[i].cu = cu;
        }
 
       /* Success.  */
index c59dd5d59c86eefdc278da2b931ff80ecb2378c9..7bfefd6cc4f705f2dacd49e25f90ed47b2a61962 100644 (file)
@@ -1,5 +1,5 @@
 /* Return line address.
-   Copyright (C) 2004 Red Hat, Inc.
+   Copyright (C) 2004-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -61,7 +61,22 @@ dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp)
   if (line == NULL)
     return -1;
 
-  *addrp =  line->addr;
+  if (line->cu->lines->reloc == NULL
+      || line->cu->lines->reloc[line - line->cu->lines->info] == NULL)
+    {
+      *addrp = line->addr;
+      return 0;
+    }
 
-  return 0;
+  /* We have to relocate an address and then adjust it for this line record.  */
+
+  int result = __libdw_read_address
+    (line->cu->dbg, IDX_debug_line,
+     line->cu->lines->reloc[line - line->cu->lines->info],
+     line->cu->address_size, addrp);
+
+  if (result >= 0)
+    *addrp += line->addr;
+
+  return result;
 }
index 6ecce93fe0f49725fca5e4fb6a127f6b079ded7b..ad3a83bf02350c709b942cd010589399a75e6615 100644 (file)
@@ -1,5 +1,5 @@
 /* Find line information for address.
-   Copyright (C) 2004 Red Hat, Inc.
+   Copyright (C) 2004-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -61,17 +61,17 @@ dwarf_linesrc (Dwarf_Line *line, Dwarf_Word *mtime, Dwarf_Word *length)
   if (line == NULL)
     return NULL;
 
-  if (line->file >= line->files->nfiles)
+  if (line->file >= line->cu->files->nfiles)
     {
       __libdw_seterrno (DWARF_E_INVALID_DWARF);
       return NULL;
     }
 
   if (mtime != NULL)
-    *mtime = line->files->info[line->file].mtime;
+    *mtime = line->cu->files->info[line->file].mtime;
 
   if (length != NULL)
-    *length = line->files->info[line->file].length;
+    *length = line->cu->files->info[line->file].length;
 
-  return line->files->info[line->file].name;
+  return line->cu->files->info[line->file].name;
 }
index bb0ae1d119979a80ed17dfb296ade3db0d90b765..6b22d6ee73cbcf06eba63e38bae441e72645eb74 100644 (file)
@@ -136,6 +136,13 @@ enum
   DWARF_E_INVALID_OFFSET,
   DWARF_E_NO_DEBUG_RANGES,
   DWARF_E_INVALID_CFI,
+  DWARF_E_RELOC,
+  DWARF_E_RELBADTYPE,
+  DWARF_E_RELBADADDEND,
+  DWARF_E_RELBADOFF,
+  DWARF_E_RELBADSYM,
+  DWARF_E_RELUNDEF,
+  DWARF_E_RELWRONGSEC,
 };
 
 
@@ -150,6 +157,9 @@ struct Dwarf
   /* The section data.  */
   Elf_Data *sectiondata[IDX_last];
 
+  /* Information for relocating an ET_REL file, or null.  */
+  struct dwarf_file_reloc *relocate;
+
   /* True if the file has a byte order different from the host.  */
   bool other_byte_order;
 
@@ -201,6 +211,19 @@ struct Dwarf
 };
 
 
+/* Hook for relocation information (handled in relocate.c).  */
+struct dwarf_file_reloc
+{
+  struct dwarf_section_reloc *sectionrel[IDX_last];
+
+  struct ebl *ebl;
+
+  int (*resolve_symbol) (bool undef, Dwarf *dbg,
+                        GElf_Sym *sym, GElf_Word shndx)
+    internal_function;
+};
+
+
 /* Abbreviation representation.  */
 struct Dwarf_Abbrev
 {
@@ -236,7 +259,7 @@ typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
 
 struct Dwarf_Line_s
 {
-  Dwarf_Files *files;
+  struct Dwarf_CU *cu;
 
   Dwarf_Addr addr;
   unsigned int file;
@@ -257,6 +280,7 @@ struct Dwarf_Line_s
 
 struct Dwarf_Lines_s
 {
+  const unsigned char **reloc;
   size_t nlines;
   struct Dwarf_Line_s info[0];
 };
@@ -464,29 +488,27 @@ extern int __dwarf_errno_internal (void);
 
 /* Reader hooks.  */
 
+extern void __libdw_relocate_begin (Dwarf *dbg, Elf_Scn *relscn[IDX_last],
+                                   bool incomplete)
+  __nonnull_attribute__ (1, 2) internal_function;
+
+extern void __libdw_relocate_end (Dwarf *dbg)
+  __nonnull_attribute__ (1) internal_function;
+
+
 /* Relocation hooks return -1 on error (in that case the error code
    must already have been set), 0 if there is no relocation and 1 if a
-   relocation was present.*/
+   relocation was present.  */
 
-static inline int
-__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
-                         int sec_index __attribute__ ((unused)),
-                         const void *addr __attribute__ ((unused)),
-                         int width __attribute__ ((unused)),
-                         Dwarf_Addr *val __attribute__ ((unused)))
-{
-  return 0;
-}
+extern int __libdw_relocate_address (Dwarf *dbg, int sec_index,
+                                    const void *addr, int width,
+                                    Dwarf_Addr *val)
+  __nonnull_attribute__ (1, 3, 5) internal_function;
 
-static inline int
-__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
-                        int sec_index __attribute__ ((unused)),
-                        const void *addr __attribute__ ((unused)),
-                        int width __attribute__ ((unused)),
-                        Dwarf_Off *val __attribute__ ((unused)))
-{
-  return 0;
-}
+extern int __libdw_relocate_offset (Dwarf *dbg, int sec_index,
+                                   const void *addr, int width,
+                                   Dwarf_Off *val)
+  __nonnull_attribute__ (1, 3, 5) internal_function;
 
 static inline Elf_Data *
 __libdw_checked_get_data (Dwarf *dbg, int sec_index)
@@ -540,15 +562,19 @@ __libdw_in_section (Dwarf *dbg, int sec_index,
     if (!__libdw_in_section (dbg, sec_index, addr, width))             \
       return -1;                                                       \
                                                                        \
-    const unsigned char *orig_addr = addr;                             \
-    if (width == 4)                                                    \
+    int status = 0;                                                    \
+    if (dbg->relocate != NULL)                                         \
+      {                                                                        \
+       status = RELOC_HOOK (dbg, sec_index, addr, width, &VAL);        \
+       if (status < 0)                                                 \
+         return status;                                                \
+       addr += width;                                                  \
+      }                                                                        \
+    else if (width == 4)                                               \
       VAL = read_4ubyte_unaligned_inc (dbg, addr);                     \
     else                                                               \
       VAL = read_8ubyte_unaligned_inc (dbg, addr);                     \
                                                                        \
-    int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL);  \
-    if (status < 0)                                                    \
-      return status;                                                   \
     status > 0;                                                                \
    })
 
@@ -568,8 +594,7 @@ __libdw_read_address (Dwarf *dbg,
                      int sec_index, const unsigned char *addr,
                      int width, Dwarf_Addr *ret)
 {
-  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
-  return 0;
+  return __libdw_read_address_inc (dbg, sec_index, &addr, width, ret);
 }
 
 static inline int
@@ -590,8 +615,8 @@ __libdw_read_offset (Dwarf *dbg,
                     int width, Dwarf_Off *ret, int sec_ret,
                     size_t size)
 {
-  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
-  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
+  return __libdw_read_offset_inc (dbg, sec_index, &addr, width,
+                                 ret, sec_ret, size);
 }
 
 static inline size_t
diff --git a/libdw/relocate.c b/libdw/relocate.c
new file mode 100644 (file)
index 0000000..a7d57a4
--- /dev/null
@@ -0,0 +1,546 @@
+/* Relocation handling for DWARF reader.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of Red Hat 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.
+
+   Red Hat 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>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include "../libelf/libelfP.h"
+#include "../libebl/libebl.h"
+#include <dwarf.h>
+#include <assert.h>
+#include <stdlib.h>
+
+
+struct dwarf_reloc_table
+{
+  size_t n;                    /* Number of elements in this table.  */
+  const unsigned char **datum; /* Sorted pointers into section data.  */
+  int *symndx;                 /* Corresponding symtab indices.  */
+  size_t hint;                 /* Index of last search.  */
+};
+
+struct dwarf_section_reloc
+{
+  /* This is set only in the laziest state from startup: the reloc
+     section needs to be examined, and the rest is uninitialized.
+     When this is cleared, the rest is initialized and safe to use.  */
+  Elf_Scn *scn;
+
+  Elf_Data *symdata;
+  Elf_Data *symstrdata;
+  Elf_Data *symxndxdata;
+
+  /* Two tables of predigested relocations, segregated by size.  */
+  struct dwarf_reloc_table rel4;
+  struct dwarf_reloc_table rel8;
+
+  /* For SHT_RELA, a parallel table of addends.
+     For SHT_REL, these are null.  */
+  Elf32_Sword *rela4;
+  Elf64_Sxword *rela8;
+};
+
+static int
+internal_function
+noresolve_symbol (bool undef,
+                 Dwarf *dbg __attribute__ ((unused)),
+                 GElf_Sym *sym __attribute__ ((unused)),
+                 GElf_Word shndx __attribute__ ((unused)))
+{
+  __libdw_seterrno (undef ? DWARF_E_RELUNDEF : DWARF_E_RELOC);
+  return -1;
+}
+
+void
+internal_function
+__libdw_relocate_begin (Dwarf *dbg, Elf_Scn *relscn[IDX_last], bool incomplete)
+{
+  if (incomplete)
+    {
+      /* We may need a second pass to identify some relocation sections.  */
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (dbg->elf, scn)) != NULL)
+       {
+         GElf_Shdr shdr_mem;
+         GElf_Shdr *shdr;
+         shdr = gelf_getshdr (scn, &shdr_mem);
+         assert (shdr == &shdr_mem);
+         if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+           for (size_t i = 0; i < IDX_last; ++i)
+             if (relscn[i] == NULL && dbg->sectiondata[i] != NULL
+                 && (((Elf_Data_Scn * ) dbg->sectiondata[i])->s->index
+                     == shdr->sh_link))
+               relscn[i] = scn;
+       }
+    }
+
+  dbg->relocate = libdw_typed_alloc (dbg, struct dwarf_file_reloc);
+  dbg->relocate->ebl = NULL;
+  dbg->relocate->resolve_symbol = &noresolve_symbol;
+
+  /* All we do to start with is cache the section pointers.
+     We'll do the rest on demand in digest_relocs, below.  */
+  for (size_t i = 0; i < IDX_last; ++i)
+    if (relscn[i] == NULL)
+      dbg->relocate->sectionrel[i] = NULL;
+    else
+      (dbg->relocate->sectionrel[i]
+       = libdw_typed_alloc (dbg, struct dwarf_section_reloc))->scn = relscn[i];
+}
+
+void
+internal_function
+__libdw_relocate_end (Dwarf *dbg)
+{
+  // XXX let dwfl preinstall, don't close here
+  ebl_closebackend (dbg->relocate->ebl);
+}
+\f
+struct digested_reloc
+{
+  GElf_Sxword addend;
+  const unsigned char *datum;
+  int symndx;
+  bool rel8;
+};
+
+static bool
+match_r_type (const int *types, int r_type)
+{
+  for (const int *t = types; *t != 0; ++t)
+    if (r_type == *t)
+      return true;
+  return false;
+}
+
+static inline int
+digest_one_reloc (const int *rel8_types, const int *rel4_types,
+                 struct dwarf_section_reloc *r, Elf_Data *data,
+                 struct digested_reloc **digest,
+                 GElf_Addr r_offset, GElf_Xword r_info, GElf_Sxword r_addend)
+{
+  const int r_type = GELF_R_TYPE (r_info);
+  int symndx = GELF_R_SYM (r_info);
+
+  size_t *nrel = &r->rel8.n;
+  if (match_r_type (rel8_types, r_type))
+    (*digest)->rel8 = true;
+  else if (unlikely (!match_r_type (rel4_types, r_type)))
+    return DWARF_E_RELBADTYPE;
+  else if (unlikely ((GElf_Sxword) (GElf_Sword) r_addend != r_addend))
+    return DWARF_E_RELBADADDEND;
+  else
+    {
+      (*digest)->rel8 = false;
+      nrel = &r->rel4.n;
+    }
+
+  if (unlikely (data->d_size - ((*digest)->rel8 ? 8 : 4) < r_offset))
+    return DWARF_E_RELBADOFF;
+
+  /* Fetch the symbol used in the reloc.  STN_UNDEF means no symbol,
+     just an addend in some unallocated target DWARF section.  If the
+     symbol is defined non-weak in another unallocated section, we can
+     adjust the addend now and not bother to record any symbol.  */
+
+  inline bool allocated_scn (GElf_Word shndx)
+  {
+    Elf_Scn *const symscn = ((Elf_Data_Scn *) r->symdata)->s;
+    GElf_Shdr shdr;
+    return (gelf_getshdr (elf_getscn (symscn->elf, shndx), &shdr) == NULL
+           || (shdr.sh_flags & SHF_ALLOC));
+  }
+
+  GElf_Sym sym;
+  Elf32_Word shndx;
+  if (symndx != STN_UNDEF
+      && gelf_getsymshndx (r->symdata, r->symxndxdata, symndx, &sym, &shndx)
+      && GELF_ST_BIND (sym.st_info) < STB_WEAK
+      && (sym.st_shndx == SHN_XINDEX ? !allocated_scn (shndx)
+         : (sym.st_shndx != SHN_UNDEF
+            && sym.st_shndx < SHN_LORESERVE
+            && !allocated_scn (sym.st_shndx))))
+    {
+      r_addend += sym.st_value;
+      symndx = STN_UNDEF;
+    }
+
+#if 0
+  // XXX do in separate pass only for unstrip -R
+  if (modify && symndx == STN_UNDEF)
+    {
+      /* This is fully resolved statically.
+        Modify it in place and record nothing.  */
+
+      unsigned char *datum = (unsigned char *) (*digest)->datum;
+      if ((*digest)->rel8)
+       {
+         Elf64_Xword val = read_8ubyte_unaligned (dbg, datum) + r_addend;
+         if (dbg->other_byte_order)
+           val = bswap_64 (val);
+         memcpy (datum, &val, sizeof val);
+       }
+      else
+       {
+         Elf32_Word val = read_4ubyte_unaligned (dbg, datum) + r_addend;
+         if (dbg->other_byte_order)
+           val = bswap_32 (val);
+         memcpy (datum, &val, sizeof val);
+       }
+      return 0;
+    }
+#endif
+
+  if (r_addend != 0 || symndx != STN_UNDEF)
+    {
+      /* This will require relocating the data dynamically.  Record it.  */
+
+      (*digest)->datum = data->d_buf + r_offset;
+      (*digest)->symndx = symndx;
+      (*digest)->addend = r_addend;
+      ++*digest;
+      ++*nrel;
+    }
+
+  return 0;
+}
+
+static int
+compare_digested_reloc (const void *a, const void *b)
+{
+  const struct digested_reloc *r1 = a;
+  const struct digested_reloc *r2 = b;
+  return r1->datum > r2->datum ? 1 : r1->datum < r2->datum ? -1 : 0;
+}
+
+static int
+digest_relocs (Dwarf *dbg, Elf_Data *data, struct dwarf_section_reloc *r)
+{
+  GElf_Shdr shdr;
+  if (unlikely (gelf_getshdr (r->scn, &shdr) == NULL))
+    assert (!"impossible gelf_getshdr failure");
+
+  /* XXX let dwfl supply defaults from main file for separate debug
+     with relocs pointing to SHT_NOBITS symtab
+  r->symdata = dbg->relocate->symdata;
+  r->symstrdata = dbg->relocate->symstrdata;
+  */
+  {
+    GElf_Shdr symshdr;
+    Elf_Scn *const symscn = elf_getscn (r->scn->elf, shdr.sh_link);
+    if (unlikely (gelf_getshdr (symscn, &symshdr) == NULL))
+      return DWARF_E_RELBADSYM;
+    if (symshdr.sh_type != SHT_NOBITS)
+      {
+       r->symdata = elf_getdata (symscn, NULL);
+       if (unlikely (r->symdata == NULL))
+         return DWARF_E_RELBADSYM;
+       r->symstrdata = elf_getdata (elf_getscn (r->scn->elf, symshdr.sh_link),
+                                    NULL);
+       if (unlikely (r->symstrdata == NULL))
+         return DWARF_E_RELBADSYM;
+      }
+  }
+
+  if (dbg->relocate->ebl == NULL)
+    {
+      dbg->relocate->ebl = ebl_openbackend (dbg->elf);
+      if (unlikely (dbg->relocate->ebl == NULL))
+       return DWARF_E_NOMEM;
+    }
+
+  const int *rel8_types;
+  const int *rel4_types;
+  ebl_reloc_simple_types (dbg->relocate->ebl, &rel8_types, &rel4_types);
+
+  Elf_Data *const reldata = elf_getdata (r->scn, NULL);
+
+  const size_t nrel = shdr.sh_size / shdr.sh_entsize;
+  struct digested_reloc digest[nrel];
+  struct digested_reloc *d = digest;
+
+  r->rel4.n = r->rel8.n = 0;
+
+  int ret = 0;
+  if (shdr.sh_type == SHT_RELA)
+    for (size_t i = 0; i < nrel && !ret; ++i)
+      {
+       GElf_Rela rela;
+       if (unlikely (gelf_getrela (reldata, i, &rela) == NULL))
+         assert (!"impossible gelf_getrela failure");
+       ret = digest_one_reloc (rel8_types, rel4_types, r, data, &d,
+                               rela.r_offset, rela.r_info, rela.r_addend);
+      }
+  else
+    for (size_t i = 0; i < nrel && !ret; ++i)
+      {
+       GElf_Rel rel;
+       if (unlikely (gelf_getrel (reldata, i, &rel) == NULL))
+         assert (!"impossible gelf_getrel failure");
+       ret = digest_one_reloc (rel8_types, rel4_types, r, data, &d,
+                               rel.r_offset, rel.r_info, 0);
+      }
+
+  assert (r->rel4.n + r->rel8.n == (size_t) (d - digest));
+
+  if (ret)
+    return ret;
+
+  /* Sort by datum address.  */
+  qsort (digest, d - digest, sizeof digest[0], &compare_digested_reloc);
+
+  if (r->rel8.n > 0)
+    {
+      r->rel8.datum = libdw_alloc (dbg, const unsigned char *,
+                                  sizeof (const unsigned char *),
+                                  r->rel8.n);
+      r->rel8.symndx = libdw_alloc (dbg, int, sizeof (int), r->rel8.n);
+      if (shdr.sh_type == SHT_RELA)
+       r->rela8 = libdw_alloc (dbg, Elf64_Sxword, sizeof (Elf64_Sxword),
+                               r->rel8.n);
+      else
+       r->rela8 = NULL;
+    }
+
+  if (r->rel4.n > 0)
+    {
+      r->rel4.datum = libdw_alloc (dbg, const unsigned char *,
+                                  sizeof (const unsigned char *),
+                                  r->rel4.n);
+      r->rel4.symndx = libdw_alloc (dbg, int, sizeof (int), r->rel4.n);
+      if (shdr.sh_type == SHT_RELA)
+       r->rela4 = libdw_alloc (dbg, Elf32_Sword, sizeof (Elf32_Sword),
+                               r->rel4.n);
+      else
+       r->rela4 = NULL;
+    }
+
+  size_t n8 = 0;
+  size_t n4 = 0;
+  for (struct digested_reloc *dr = digest; dr < d; ++dr)
+    if (dr->rel8)
+      {
+       r->rel8.datum[n8] = dr->datum;
+       r->rel8.symndx[n8] = dr->symndx;
+       if (shdr.sh_type == SHT_RELA)
+         r->rela8[n8] = dr->addend;
+       ++n8;
+      }
+    else
+      {
+       r->rel4.datum[n4] = dr->datum;
+       r->rel4.symndx[n4] = dr->symndx;
+       if (shdr.sh_type == SHT_RELA)
+         r->rela4[n4] = dr->addend;
+       ++n4;
+      }
+  assert (n8 == r->rel8.n);
+  assert (n4 == r->rel4.n);
+
+  /* Clearing this marks that the digested form is set up now.  */
+  r->scn = NULL;
+  return 0;
+}
+\f
+/* Binary search for an exact match on the DATUM address.  */
+static ssize_t
+find_reloc (struct dwarf_reloc_table *table, const unsigned char *datum)
+{
+  size_t l = 0, u = table->n;
+
+  if (u == 0)
+    return -1;
+
+  if (table->hint < u && table->datum[table->hint] <= datum)
+    {
+      l = table->hint;
+      if (table->datum[l] == datum)
+       return l;
+      if (table->datum[l] < datum)
+       ++l;
+    }
+
+  while (l < u)
+    {
+      size_t i = (l + u) / 2;
+      if (table->datum[i] < datum)
+       l = i + 1;
+      else if (table->datum[i] > datum)
+       u = i;
+      else
+       return table->hint = i;
+    }
+
+  table->hint = l;
+  return -1;
+}
+
+static int
+relocatable_datum (Dwarf *dbg, int sec_index, struct dwarf_section_reloc *r,
+                  const unsigned char *datum, int width,
+                  int *symndx, GElf_Sxword *addend)
+{
+  if (r == NULL)
+    return 0;
+
+  if (r->scn != NULL)
+    {
+      int result = digest_relocs (dbg, dbg->sectiondata[sec_index], r);
+      if (unlikely (result != 0))
+       {
+         __libdw_seterrno (result);
+         return -1;
+       }
+    }
+
+  ssize_t i;
+  if (width == 4)
+    {
+      i = find_reloc (&r->rel4, datum);
+      *symndx = i < 0 ? STN_UNDEF : r->rel4.symndx[i];
+      if (addend != NULL)
+       *addend = ((i < 0 || r->rela4 == NULL)
+                  ? read_4sbyte_unaligned (dbg, datum) : r->rela4[i]);
+    }
+  else
+    {
+      assert (width == 8);
+
+      i = find_reloc (&r->rel8, datum);
+      *symndx = i < 0 ? STN_UNDEF : r->rel8.symndx[i];
+      if (addend != NULL)
+       *addend = ((i < 0 || r->rela8 == NULL)
+                  ? read_8sbyte_unaligned (dbg, datum) : r->rela8[i]);
+    }
+
+  return i >= 0;
+}
+
+static int
+reloc_getsym (struct dwarf_section_reloc *r, int symndx,
+             GElf_Sym *sym, GElf_Word *shndx)
+{
+  if (unlikely (gelf_getsymshndx (r->symdata, r->symxndxdata,
+                                 symndx, sym, shndx) == NULL))
+    {
+      __libdw_seterrno (DWARF_E_RELBADSYM);
+      return -1;
+    }
+  return 1;
+}
+
+int
+internal_function
+__libdw_relocate_address (Dwarf *dbg, int sec_index,
+                         const void *datum, int width, Dwarf_Addr *val)
+{
+  struct dwarf_section_reloc *const r = dbg->relocate->sectionrel[sec_index];
+  int symndx;
+  GElf_Sxword addend;
+  int result = relocatable_datum (dbg, sec_index, r, datum, width,
+                                 &symndx, &addend);
+  if (result > 0 && symndx != STN_UNDEF)
+    {
+      GElf_Sym sym;
+      GElf_Word shndx;
+      result = reloc_getsym (r, symndx, &sym, &shndx);
+      if (result > 0)
+       {
+         result = (*dbg->relocate->resolve_symbol)
+           (sym.st_shndx == SHN_UNDEF || sym.st_shndx == SHN_COMMON
+            || GELF_ST_BIND (sym.st_info) > STB_WEAK,
+            dbg, &sym, sym.st_shndx == SHN_XINDEX ? shndx : sym.st_shndx);
+         addend += sym.st_value;
+       }
+    }
+  if (result >= 0)
+    *val = addend;
+  return result;
+}
+
+int
+internal_function
+__libdw_relocate_offset (Dwarf *dbg, int sec_index,
+                        const void *datum, int width, Dwarf_Off *val)
+{
+  struct dwarf_section_reloc *const r = dbg->relocate->sectionrel[sec_index];
+  int symndx;
+  GElf_Sxword addend;
+  int result = relocatable_datum (dbg, sec_index, r, datum, width,
+                                 &symndx, &addend);
+  if (result > 0 && symndx != STN_UNDEF)
+    {
+      GElf_Sym sym;
+      GElf_Word shndx;
+      result = reloc_getsym (r, symndx, &sym, &shndx);
+      if (result > 0)
+       {
+         if (unlikely (sym.st_shndx == SHN_UNDEF)
+             || (sym.st_shndx > SHN_LORESERVE
+                 && unlikely (sym.st_shndx != SHN_XINDEX)))
+           {
+             __libdw_seterrno (DWARF_E_RELUNDEF);
+             return -1;
+           }
+         if (unlikely (((Elf_Data_Scn *) dbg->sectiondata[sec_index])->s->index
+                       != (sym.st_shndx == SHN_XINDEX ? shndx : sym.st_shndx)))
+           {
+             __libdw_seterrno (DWARF_E_RELWRONGSEC);
+             return -1;
+           }
+         addend += sym.st_value;
+       }
+    }
+  if (result >= 0)
+    *val = addend;
+  return result;
+}
index f1887aed5cff5dc1032e2df7957dfeab1c86857f..92be9488a9007fa494dbac8ec5f1becee24013c3 100644 (file)
@@ -1,3 +1,8 @@
+2010-06-21  Roland McGrath  <roland@redhat.com>
+
+       * dwfl_module_getsrc_file.: Update for Dwarf_Line member change.
+       * dwfl_lineinfo.c: Likewise.  Use dwarf_lineaddr.
+
 2010-06-20  Roland McGrath  <roland@redhat.com>
 
        * relocate.c (struct reloc_symtab_cache): New members
index 0d8a6887ee40f0e5c7d10a44f64afb07527d0709..920a2de9c1e3ed55fed40f5598d4584b37f9a2f5 100644 (file)
@@ -1,5 +1,5 @@
 /* Get information from a source line record returned by libdwfl.
-   Copyright (C) 2005, 2006 Red Hat, Inc.
+   Copyright (C) 2005-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -67,7 +67,7 @@ dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp,
   if (colp != NULL)
     *colp = info->column;
 
-  struct Dwarf_Fileinfo_s *file = &info->files->info[info->file];
+  struct Dwarf_Fileinfo_s *file = &info->cu->files->info[info->file];
   if (mtime != NULL)
     *mtime = file->mtime;
   if (length != NULL)
index 9d0c786b9a2872cfc375c49287f34e58c667ff56..fe305c682aa24c0ce8d06f92bc88205f9c075328 100644 (file)
@@ -1,5 +1,5 @@
 /* Find matching source locations in a module.
-   Copyright (C) 2005 Red Hat, Inc.
+   Copyright (C) 2005-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -81,7 +81,7 @@ dwfl_module_getsrc_file (Dwfl_Module *mod,
     {
       inline const char *INTUSE(dwarf_line_file) (const Dwarf_Line *line)
        {
-         return line->files->info[line->file].name;
+         return line->cu->files->info[line->file].name;
        }
       inline Dwarf_Line *dwfl_line (const Dwfl_Line *line)
        {
@@ -101,7 +101,7 @@ dwfl_module_getsrc_file (Dwfl_Module *mod,
        {
          Dwarf_Line *line = &cu->die.cu->lines->info[cnt];
 
-         if (unlikely (line->file >= line->files->nfiles))
+         if (unlikely (line->file >= line->cu->files->nfiles))
            {
              __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
              return -1;