Squashed commit of the following:

commit 77abb31cb8d55980ef92260917a7ecdd228b1a44
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Jun 8 15:46:16 2009 +0200

    Fix a bug in offset checking

commit b794eac4f8d3e08101b5d2924523b1259bbc1b17
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Jun 3 16:00:01 2009 +0200

    Cosmetic, get rid of defining several variables per line

commit a23938fe35d515a3d75a51f6204771f3cf6c9ec4
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Jun 3 15:50:03 2009 +0200

    Restructure the code to decrease the binary size

commit 7c301e3d4e8584dfb3174855fb6af3d5791dfeed
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Jun 1 19:43:28 2009 +0200

    Shuffle a couple pieces of code around to make the code smaller

commit 6325323482c2a3e17409d32c7feec9461be26614
Merge: 83ac53d... e94b1b2...
Author: Petr Machata <pmachata@redhat.com>
Date:   Fri May 22 08:49:07 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

    Conflicts:
    	libdw/ChangeLog

commit 83ac53db400945c074e77ec9904efe550903a0e2
Author: Petr Machata <pmachata@redhat.com>
Date:   Fri May 22 08:40:25 2009 +0200

    Call reloc hook with the original address, not incremented

commit f1996388745566abc1ca1c1700b3b7eded208575
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 16:53:03 2009 +0200

    Rewrite boundary checking logic so that it's immune to arithmetic overflow

    * ... also get rid of some code redundancy.

commit 0c1df732822d83548edd0d005f3450281ed1701b
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 16:25:09 2009 +0200

    __libdw_read_offset* take extra argument for header size checks

    * also presence of debug data and buffer is checked in __libdw_in_section

commit 6fb192e360f842cacb34a90c03cd0524cccc3dec
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 15:51:20 2009 +0200

    Check for presence of data before loading the offset

commit a2e7612b165d83dd241225f87075fa4f58d18781
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed May 6 15:04:16 2009 +0200

    Cosmetic changes

commit 8b1aad2c2f6c8dc02b3e704e4f386c1827e385cb
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 15:34:13 2009 +0200

    Improve reader hook functions a bit

    * ... so that they are closer match to what's need on call sites

commit 3854b7fbab2fe331711365f94a295af82164d0d2
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 14:33:50 2009 +0200

    Fixes in use of reader hooks in __libdw_formptr and dwarf_formudata

    * and a bit more

commit 335075596b6acef6e59919155e2b087e690a572d
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 14:32:39 2009 +0200

    Rename __libdw_read_udata_addr to __libdw_formptr

commit 8273a2adaf8cb2ee203926af2849e4f96f8a6eaf
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue May 5 02:53:40 2009 +0200

    Introduce __libdw_read_udata_address

    * the use in dwarf_ranges is iffy, there's a functionality mismatch.
      Need to find some better way

commit 1c897f4abde1530038d332f4fc03a596a24f6aaf
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon May 4 18:09:13 2009 +0200

    ChangeLog entries for previous commit

commit 90d7c39454468b91c0fd6514a4e8d821222d6adb
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon May 4 18:07:54 2009 +0200

    Fix bugs, introduce __libdw_read_begin_end_pair_inc

commit 9b3923f5b69a3e56590769435c4693f057acdc1f
Merge: 6200ba6... 589b3d3...
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon May 4 12:22:21 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

commit 6200ba62aa9ea3cb9318f73a27181907a528dbe4
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Apr 29 15:31:28 2009 +0200

    dwarf_getlocation_addr uses read hooks

commit ecbb8cdd8b500e37dc34fc246b912f704fe31ca4
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Apr 29 15:16:09 2009 +0200

    dwarf_ranges and dwarf_formref use read hooks

commit cb8f67b29a896c2660c10aa1028a9dbb377553e9
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 18:39:04 2009 +0200

    Convert several new functions to use read hooks

commit b130453eb16a8cf042915e312cc5f189b8b92c01
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 18:38:27 2009 +0200

    Add length read hooks

commit bd885ff694817b965231d99f1ab867947998e734
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 18:36:17 2009 +0200

    Constify read hook arguments

commit 66fe03f1e489a88b89a15c9e13f9bd33db2729b1
Author: Petr Machata <pmachata@redhat.com>
Date:   Tue Apr 28 16:11:05 2009 +0200

    Change type of return value of offset read hooks to Dwarf_Off

commit 22b36e00cc228f5a966f84ca3323e5d652923ce8
Merge: 5b3534b... a7cb532...
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Apr 27 19:05:25 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

commit 5b3534b62cbd45fe4f11dd1be3e492237938cce0
Author: Petr Machata <pmachata@redhat.com>
Date:   Mon Apr 27 18:53:06 2009 +0200

    Rewrites in read hooks

    * Have the checking and reading logic itself in the header so that it gets
      optimized out/inlined.  Call external relocating hook from there, there
      will presumably be more work to do, and we presumably don't want to keep
      this in the header.

commit 9e265d71d0eb900e76d6fdb0196ef4fc6507f3a7
Merge: 1783089... 300f3a4...
Author: Petr Machata <pmachata@redhat.com>
Date:   Thu Apr 23 17:45:25 2009 +0200

    Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks

commit 1783089b184ddea2081bbe5ac4e80420cb6b0803
Author: Petr Machata <pmachata@redhat.com>
Date:   Thu Apr 23 17:44:48 2009 +0200

    Use the new reader hooks in several places

commit 11c3d97a5b40ea15edf324092b03da3050610d01
Author: Petr Machata <pmachata@redhat.com>
Date:   Thu Apr 23 17:40:03 2009 +0200

    Introduce reader hooks
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 1d5a9b2..97a2e04 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -419,6 +419,156 @@
 extern int __dwarf_errno_internal (void);
 
 
+/* Reader hooks.  */
+
+/* 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.*/
+
+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;
+}
+
+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;
+}
+
+static inline Elf_Data *
+__libdw_checked_get_data (Dwarf *dbg, int sec_index)
+{
+  Elf_Data *data = dbg->sectiondata[sec_index];
+  if (unlikely (data == NULL)
+      || unlikely (data->d_buf == NULL))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+  return data;
+}
+
+static inline int
+__libdw_offset_in_section (Dwarf *dbg, int sec_index,
+			   Dwarf_Off offset, size_t size)
+{
+  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+  if (data == NULL)
+    return -1;
+  if (unlikely (offset > data->d_size)
+      || unlikely (data->d_size - offset < size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return -1;
+    }
+
+  return 0;
+}
+
+static inline bool
+__libdw_in_section (Dwarf *dbg, int sec_index,
+		    const void *addr, size_t size)
+{
+  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+  if (data == NULL)
+    return false;
+  if (unlikely (addr < data->d_buf)
+      || unlikely (data->d_size - (addr - data->d_buf) < size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return false;
+    }
+
+  return true;
+}
+
+#define READ_AND_RELOCATE(RELOC_HOOK, VAL)				\
+  ({									\
+    if (!__libdw_in_section (dbg, sec_index, addr, width))		\
+      return -1;							\
+									\
+    const unsigned char *orig_addr = addr;				\
+    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;								\
+   })
+
+static inline int
+__libdw_read_address_inc (Dwarf *dbg,
+			  int sec_index, unsigned char **addrp,
+			  int width, Dwarf_Addr *ret)
+{
+  unsigned char *addr = *addrp;
+  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
+  *addrp = addr;
+  return 0;
+}
+
+static inline int
+__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;
+}
+
+static inline int
+__libdw_read_offset_inc (Dwarf *dbg,
+			 int sec_index, unsigned char **addrp,
+			 int width, Dwarf_Off *ret, int sec_ret,
+			 size_t size)
+{
+  unsigned char *addr = *addrp;
+  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
+  *addrp = addr;
+  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
+}
+
+static inline int
+__libdw_read_offset (Dwarf *dbg,
+		     int sec_index, const unsigned char *addr,
+		     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);
+}
+
+/* Read up begin/end pair and increment read pointer.
+    - If it's normal range record, set up *BEGINP and *ENDP and return 0.
+    - If it's base address selection record, set up *BASEP and return 1.
+    - If it's end of rangelist, don't set anything and return 2
+    - If an error occurs, don't set anything and return <0.  */
+int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
+				     unsigned char **addr, int width,
+				     Dwarf_Addr *beginp, Dwarf_Addr *endp,
+				     Dwarf_Addr *basep)
+  internal_function;
+
+unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
+				 int err_nodata, unsigned char **endpp,
+				 Dwarf_Off *offsetp)
+  internal_function;
+
+
+
 /* Aliases to avoid PLTs.  */
 INTDECL (dwarf_attr)
 INTDECL (dwarf_attr_integrate)