Merge r13421:HEAD from branches/DISRV.  This merges the debuginfo-server
stuff into the trunk.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13440 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index d2ac70d..6d0fe83 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -202,6 +202,7 @@
 	m_debuginfo/priv_readdwarf3.h	\
 	m_debuginfo/priv_readelf.h	\
 	m_debuginfo/priv_readmacho.h	\
+	m_debuginfo/priv_image.h	\
 	m_demangle/ansidecl.h	\
 	m_demangle/cp-demangle.h \
 	m_demangle/dyn-string.h	\
@@ -296,6 +297,7 @@
 	m_debuginfo/readstabs.c \
 	m_debuginfo/storage.c \
 	m_debuginfo/tytypes.c \
+	m_debuginfo/image.c \
 	m_demangle/cp-demangle.c \
 	m_demangle/cplus-dem.c \
 	m_demangle/demangle.c \
diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
index 13297fb..9253704 100644
--- a/coregrind/m_debuginfo/d3basics.c
+++ b/coregrind/m_debuginfo/d3basics.c
@@ -38,6 +38,7 @@
 #include "pub_core_debuginfo.h"
 #include "pub_core_libcassert.h"
 #include "pub_core_libcprint.h"
+#include "pub_core_libcbase.h"
 #include "pub_core_options.h"
 #include "pub_core_xarray.h"
 
@@ -45,6 +46,7 @@
 #include "pub_core_aspacemgr.h" /* VG_(is_valid_for_client) */
 
 #include "priv_misc.h"
+#include "priv_image.h"
 #include "priv_d3basics.h"      /* self */
 #include "priv_storage.h"
 
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index e866420..9ebf429 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -51,6 +51,7 @@
 #include "pub_core_ume.h"
 
 #include "priv_misc.h"           /* dinfo_zalloc/free */
+#include "priv_image.h"
 #include "priv_d3basics.h"       /* ML_(pp_GX) */
 #include "priv_tytypes.h"
 #include "priv_storage.h"
diff --git a/coregrind/m_debuginfo/image.c b/coregrind/m_debuginfo/image.c
new file mode 100644
index 0000000..8bb3779
--- /dev/null
+++ b/coregrind/m_debuginfo/image.c
@@ -0,0 +1,1045 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+
+/*--------------------------------------------------------------------*/
+/*--- An abstraction that provides a file-reading mechanism.       ---*/
+/*---                                                      image.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2013-2013 Mozilla Foundation
+
+   This program 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; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Julian Seward <jseward@acm.org> */
+
+/* See the corresponding auxprogs/valgrind-di-server.c for a list of
+   cleanups for this file and itself. */
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_libcfile.h"
+#include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
+#include "priv_image.h"            /* self */
+
+#include "pub_tool_libcproc.h" // RMME
+#include "minilzo.h"
+
+#define CACHE_ENTRY_SIZE_BITS (12+1)
+#define CACHE_N_ENTRIES       32
+
+#define CACHE_ENTRY_SIZE      (1 << CACHE_ENTRY_SIZE_BITS)
+
+/* An entry in the cache. */
+typedef
+   struct {
+      DiOffT off; // file offset for data[0]
+      SizeT  used; // 1 .. sizeof(data), or 0 to denote not-in-use
+      UChar  data[CACHE_ENTRY_SIZE];
+   }
+   CEnt;
+
+/* Source for files */
+typedef
+   struct {
+      // True: img is of local file.  False: img is from a server.
+      Bool  is_local;
+      // The fd for the local file, or sd for a remote server.
+      Int   fd;
+      // The name.  In ML_(dinfo_zalloc)'d space.  Used only for printing
+      // error messages; hence it doesn't really matter what this contains.
+      HChar* name;
+      // The rest of these fields are only valid when using remote files
+      // (that is, using a debuginfo server; hence when is_local==False)
+      // Session ID allocated to us by the server.  Cannot be zero.
+      ULong session_id;
+   }
+   Source;
+
+struct _DiImage {
+   // The source -- how to get hold of the file we are reading
+   Source source;
+   // Total size of the image.
+   SizeT size;
+   // The number of entries used.  0 .. CACHE_N_ENTRIES
+   UInt  ces_used;
+   // Pointers to the entries.  ces[0 .. ces_used-1] are non-NULL.
+   // ces[ces_used .. CACHE_N_ENTRIES-1] are NULL.
+   // The non-NULL entries may be arranged arbitrarily.  We expect to use
+   // a pseudo-LRU scheme though.
+   CEnt* ces[CACHE_N_ENTRIES];
+};
+
+/* A frame.  The first 4 bytes of |data| give the kind of the frame,
+   and the rest of it is kind-specific data. */
+typedef  struct { UChar* data; SizeT n_data; }  Frame;
+
+static void write_UInt_le ( /*OUT*/UChar* dst, UInt n )
+{
+   Int i;
+   for (i = 0; i <= 3; i++) {
+      dst[i] = (UChar)(n & 0xFF);
+      n >>= 8;
+   }
+}
+
+static UInt read_UInt_le ( UChar* src )
+{
+   UInt r = 0;
+   Int i;
+   for (i = 3; i >= 0; i--) {
+      r <<= 8;
+      r += (UInt)src[i];
+   }
+   return r;
+}
+
+static void write_ULong_le ( /*OUT*/UChar* dst, ULong n )
+{
+   Int i;
+   for (i = 0; i <= 7; i++) {
+      dst[i] = (UChar)(n & 0xFF);
+      n >>= 8;
+   }
+}
+
+static ULong read_ULong_le ( UChar* src )
+{
+   ULong r = 0;
+   Int i;
+   for (i = 7; i >= 0; i--) {
+      r <<= 8;
+      r += (ULong)src[i];
+   }
+   return r;
+}
+
+
+/* Set |sd| to be blocking.  Returns True on success. */
+static Bool set_blocking ( int sd )
+{
+   Int res;
+   res = VG_(fcntl)(sd, VKI_F_GETFL, 0/*ignored*/);
+   if (res != -1)
+      res = VG_(fcntl)(sd, VKI_F_SETFL, res & ~VKI_O_NONBLOCK);
+   return (res != -1);
+}
+
+/* Tries to read 'len' bytes from fd, blocking if necessary.  Assumes
+   fd has been set in blocking mode.  If it returns with the number of
+   bytes read < len, it means that either fd was closed, or there was
+   an error on it. */
+static Int my_read ( Int fd, UChar* buf, Int len )
+{
+   Int nRead = 0;
+   while (1) {
+      if (nRead == len) return nRead;
+      vg_assert(nRead < len);
+      Int nNeeded = len - nRead;
+      vg_assert(nNeeded > 0);
+      Int n = VG_(read)(fd, &buf[nRead], nNeeded);
+      if (n <= 0) return nRead; /* error or EOF */
+      nRead += n;
+   }
+}
+
+/* Tries to write 'len' bytes to fd, blocking if necessary.  Assumes
+   fd has been set in blocking mode.  If it returns with the number of
+   bytes written < len, it means that either fd was closed, or there was
+   an error on it. */
+static Int my_write ( Int fd, UChar* buf, Int len )
+{
+   Int nWritten = 0;
+   while (1) {
+      if (nWritten == len) return nWritten;
+      vg_assert(nWritten < len);
+      Int nStillToDo = len - nWritten;
+      vg_assert(nStillToDo > 0);
+      Int n = VG_(write_socket)(fd, &buf[nWritten], nStillToDo);
+      if (n < 0) return nWritten; /* error or EOF */
+      nWritten += n;
+   }
+}
+
+/* If we lost communication with the remote server, just give up.
+   Recovering is too difficult. */
+static void give_up__comms_lost(void)
+{
+   VG_(umsg)("\n");
+   VG_(umsg)(
+      "Valgrind: debuginfo reader: Lost communication with the remote\n");
+   VG_(umsg)(
+      "Valgrind: debuginfo server.  I can't recover.  Giving up.  Sorry.\n");
+   VG_(umsg)("\n");
+   VG_(exit)(1);
+   /*NOTREACHED*/
+}
+
+static void give_up__image_overrun(void)
+{
+   VG_(umsg)("\n");
+   VG_(umsg)(
+      "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n");
+   VG_(umsg)(
+      "Valgrind: I can't recover.  Giving up.  Sorry.\n");
+   VG_(umsg)("\n");
+   VG_(exit)(1);
+   /*NOTREACHED*/
+}
+
+/* "Do" a transaction: that is, send the given frame to the server and
+   return the frame it sends back.  Caller owns the resulting frame
+   and must free it.  A NULL return means the transaction failed for
+   some reason. */
+static Frame* do_transaction ( Int sd, Frame* req )
+{
+   if (0) VG_(printf)("CLIENT: send %c%c%c%c\n",
+                      req->data[0], req->data[1], req->data[2], req->data[3]);
+
+   /* What goes on the wire is:
+         adler(le32) n_data(le32) data[0 .. n_data-1]
+      where the checksum covers n_data as well as data[].
+   */
+   /* The initial Adler-32 value */
+   UInt adler = VG_(adler32)(0, NULL, 0);
+
+   /* Fold in the length field, encoded as le32. */
+   UChar wr_first8[8];
+   write_UInt_le(&wr_first8[4], req->n_data);
+   adler = VG_(adler32)(adler, &wr_first8[4], 4);
+   /* Fold in the data values */
+   adler = VG_(adler32)(adler, req->data, req->n_data);
+   write_UInt_le(&wr_first8[0], adler);
+
+   Int r = my_write(sd, &wr_first8[0], 8);
+   if (r != 8) return NULL;
+   vg_assert(req->n_data >= 4); // else ill formed -- no KIND field
+   r = my_write(sd, req->data, req->n_data);
+   if (r != req->n_data) return NULL;
+
+   /* So, the request is sent.  Now get a request of the same format
+      out of the channel. */
+   UChar rd_first8[8];  // adler32; length32
+   r = my_read(sd, &rd_first8[0], 8);
+   if (r != 8) return NULL;
+   UInt rd_adler = read_UInt_le(&rd_first8[0]);
+   UInt rd_len   = read_UInt_le(&rd_first8[4]);
+   /* Allocate a Frame to hold the result data, and read into it. */
+   // Reject obviously-insane length fields.
+   if (rd_len < 4 || rd_len > 4*1024*1024) return NULL;
+   Frame* res = ML_(dinfo_zalloc)("di.do_transaction.1", sizeof(Frame));
+   res->n_data = rd_len;
+   res->data = ML_(dinfo_zalloc)("di.do_transaction.2", rd_len);
+   r = my_read(sd, res->data, res->n_data);
+   if (r != rd_len) return NULL;
+
+   if (0) VG_(printf)("CLIENT: recv %c%c%c%c\n",
+                      res->data[0], res->data[1], res->data[2], res->data[3]);
+
+   /* Compute the checksum for the received data, and check it. */
+   adler = VG_(adler32)(0, NULL, 0); // initial value
+   adler = VG_(adler32)(adler, &rd_first8[4], 4);
+   if (res->n_data > 0)
+      adler = VG_(adler32)(adler, res->data, res->n_data);
+
+   if (adler/*computed*/ != rd_adler/*expected*/) return NULL;
+   return res;
+}
+
+static void free_Frame ( Frame* fr )
+{
+   vg_assert(fr && fr->data);
+   ML_(dinfo_free)(fr->data);
+   ML_(dinfo_free)(fr);
+}
+
+static Frame* mk_Frame_noargs ( const HChar* tag )
+{
+   vg_assert(VG_(strlen)(tag) == 4);
+   Frame* f = ML_(dinfo_zalloc)("di.mFn.1", sizeof(Frame));
+   f->n_data = 4;
+   f->data = ML_(dinfo_zalloc)("di.mFn.2", f->n_data);
+   VG_(memcpy)(&f->data[0], tag, 4);
+   return f;
+}
+
+static Frame* mk_Frame_le64_le64_le64 ( const HChar* tag,
+                                        ULong n1, ULong n2, ULong n3 )
+{
+   vg_assert(VG_(strlen)(tag) == 4);
+   Frame* f = ML_(dinfo_zalloc)("di.mFlll.1", sizeof(Frame));
+   f->n_data = 4 + 3*8;
+   f->data = ML_(dinfo_zalloc)("di.mFlll.2", f->n_data);
+   VG_(memcpy)(&f->data[0], tag, 4);
+   write_ULong_le(&f->data[4 + 0*8], n1);
+   write_ULong_le(&f->data[4 + 1*8], n2);
+   write_ULong_le(&f->data[4 + 2*8], n3);
+   return f;
+}
+
+static Frame* mk_Frame_asciiz ( const HChar* tag, const HChar* str )
+{
+   vg_assert(VG_(strlen)(tag) == 4);
+   Frame* f = ML_(dinfo_zalloc)("di.mFa.1", sizeof(Frame));
+   SizeT n_str = VG_(strlen)(str);
+   f->n_data = 4 + n_str + 1;
+   f->data = ML_(dinfo_zalloc)("di.mFa.2", f->n_data);
+   VG_(memcpy)(&f->data[0], tag, 4);
+   VG_(memcpy)(&f->data[4], str, n_str);
+   vg_assert(f->data[4 + n_str] == 0);
+   return f;
+}
+
+static Bool parse_Frame_le64 ( Frame* fr, const HChar* tag, /*OUT*/ULong* n1 )
+{
+   vg_assert(VG_(strlen)(tag) == 4);
+   if (!fr || !fr->data) return False;
+   if (fr->n_data < 4) return False;
+   if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
+   if (fr->n_data != 4 + 1*8) return False;
+   *n1 = read_ULong_le(&fr->data[4 + 0*8]);
+   return True;
+}
+
+static Bool parse_Frame_le64_le64 ( Frame* fr, const HChar* tag,
+                                    /*OUT*/ULong* n1, /*OUT*/ULong* n2 )
+{
+   vg_assert(VG_(strlen)(tag) == 4);
+   if (!fr || !fr->data) return False;
+   if (fr->n_data < 4) return False;
+   if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
+   if (fr->n_data != 4 + 2*8) return False;
+   *n1 = read_ULong_le(&fr->data[4 + 0*8]);
+   *n2 = read_ULong_le(&fr->data[4 + 1*8]);
+   return True;
+}
+
+static Bool parse_Frame_asciiz ( Frame* fr, const HChar* tag,
+                                 /*OUT*/UChar** str )
+{
+   vg_assert(VG_(strlen)(tag) == 4);
+   if (!fr || !fr->data) return False;
+   if (fr->n_data < 4) return False;
+   if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
+   if (fr->n_data < 5) return False; // else there isn't even enough
+                                     // space for the terminating zero
+   /* Find the terminating zero and ensure it's right at the end
+      of the data.  If not, the frame is malformed. */
+   SizeT i = 4;
+   while (True) {
+      if (i >= fr->n_data) break;
+      if (fr->data[i] == 0) break;
+      i++;
+   }
+   vg_assert(i <= fr->n_data);
+   if (i == fr->n_data-1 && fr->data[i] == 0) {
+      *str = &fr->data[4];
+      return True;
+   } else {
+      return False;
+   }
+}
+
+static Bool parse_Frame_le64_le64_le64_bytes (
+               Frame* fr, const HChar* tag,
+               /*OUT*/ULong* n1, /*OUT*/ULong* n2, /*OUT*/ULong* n3,
+               /*OUT*/UChar** data, /*OUT*/ULong* n_data 
+            )
+{
+   vg_assert(VG_(strlen)(tag) == 4);
+   if (!fr || !fr->data) return False;
+   if (fr->n_data < 4) return False;
+   if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
+   if (fr->n_data < 4 + 3*8) return False;
+   *n1 = read_ULong_le(&fr->data[4 + 0*8]);
+   *n2 = read_ULong_le(&fr->data[4 + 1*8]);
+   *n3 = read_ULong_le(&fr->data[4 + 2*8]);
+   *data   = &fr->data[4 + 3*8];
+   *n_data = fr->n_data - (4 + 3*8);
+   vg_assert(fr->n_data >= 4 + 3*8);
+   return True;
+}
+
+static DiOffT block_round_down ( DiOffT i )
+{
+   return i & ((DiOffT)~(CACHE_ENTRY_SIZE-1));
+}
+
+/* Is this offset inside this CEnt? */
+static inline Bool is_in_CEnt ( CEnt* cent, DiOffT off )
+{
+   /* This assertion is checked by set_CEnt, so checking it here has
+      no benefit, whereas skipping it does remove it from the hottest
+      path. */
+   /* vg_assert(cent->used > 0 && cent->used <= CACHE_ENTRY_SIZE); */
+   return cent->off <= off && off < cent->off + cent->used;
+}
+
+/* Allocate a new CEnt, connect it to |img|, and return its index. */
+static UInt alloc_CEnt ( DiImage* img )
+{
+   vg_assert(img);
+   vg_assert(img->ces_used < CACHE_N_ENTRIES);
+   UInt entNo = img->ces_used;
+   img->ces_used++;
+   vg_assert(img->ces[entNo] == NULL);
+   img->ces[entNo] = ML_(dinfo_zalloc)("di.alloc_CEnt.1", sizeof(CEnt));
+   return entNo;
+}
+
+/* Move the given entry to the top and slide those above it down by 1,
+   to make space. */
+static void move_CEnt_to_top ( DiImage* img, UInt entNo )
+{
+   vg_assert(img->ces_used <= CACHE_N_ENTRIES);
+   vg_assert(entNo > 0 && entNo < img->ces_used);
+   CEnt* tmp = img->ces[entNo];
+   while (entNo > 0) {
+      img->ces[entNo] = img->ces[entNo-1];
+      entNo--;
+   }
+   img->ces[0] = tmp;
+}
+
+/* Set the given entry so that it has a chunk of the file containing
+   the given offset.  It is this function that brings data into the
+   cache, either by reading the local file or pulling it from the
+   remote server. */
+static void set_CEnt ( DiImage* img, UInt entNo, DiOffT off )
+{
+   SizeT len;
+   DiOffT off_orig = off;
+   vg_assert(img);
+   vg_assert(img->ces_used <= CACHE_N_ENTRIES);
+   vg_assert(entNo >= 0 && entNo < img->ces_used);
+   vg_assert(off < img->size);
+   vg_assert(img->ces[entNo] != NULL);
+   /* Compute [off, +len) as the slice we are going to read. */
+   off = block_round_down(off);
+   len = img->size - off;
+   if (len > CACHE_ENTRY_SIZE) len = CACHE_ENTRY_SIZE;
+   /* It is conceivable that the 'len > 0' bit could fail if we make
+      an image with a zero sized file.  But then no 'get' request on
+      that image would be valid. */
+   vg_assert(len > 0 && len <= CACHE_ENTRY_SIZE);
+   vg_assert(off + len <= img->size);
+   vg_assert(off <= off_orig && off_orig < off+len);
+   /* So, read  off .. off+len-1  into the entry. */
+   CEnt* ce = img->ces[entNo];
+
+   if (0) {
+      static UInt t_last = 0;
+      static ULong nread = 0;
+      UInt now = VG_(read_millisecond_timer)();
+      UInt delay = now - t_last;
+      t_last = now;
+      nread += len;
+      VG_(printf)("XXXXXXXX (tot %lld) read %ld offset %lld  %u\n", 
+                  nread, len, off, delay);
+   }
+
+   if (img->source.is_local) {
+      // Simple: just read it
+      SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off);
+      vg_assert(!sr_isError(sr));
+   } else {
+      // Not so simple: poke the server
+      vg_assert(img->source.session_id > 0);
+      Frame* req
+         = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len);
+      Frame* res = do_transaction(img->source.fd, req);
+      free_Frame(req); req = NULL;
+      if (!res) goto server_fail;
+      ULong  rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0;
+      UChar* rx_data = NULL;
+      /* Pretty confusing.  rx_sessionid, rx_off and rx_len are copies
+         of the values that we requested in the READ frame just above,
+         so we can be sure that the server is responding to the right
+         request.  It just copies them from the request into the
+         response.  rx_data is the actual data, and rx_zdata_len is
+         its compressed length.  Hence rx_len must equal len, but
+         rx_zdata_len can be different -- smaller, hopefully.. */
+      if (!parse_Frame_le64_le64_le64_bytes
+          (res, "RDOK", &rx_session_id, &rx_off,
+                        &rx_len, &rx_data, &rx_zdata_len))
+         goto server_fail;
+      if (rx_session_id != img->source.session_id
+          || rx_off != off || rx_len != len || rx_data == NULL)
+         goto server_fail;
+
+      //VG_(memcpy)(&ce->data[0], rx_data, len);
+      // Decompress into the destination buffer
+      // Tell the lib the max number of output bytes it can write.
+      // After the call, this holds the number of bytes actually written,
+      // and it's an error if it is different.
+      UInt out_len = len;
+      Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len,
+                                         &ce->data[0], (lzo_uint*)&out_len,
+                                         NULL);
+      Bool ok = lzo_rc == LZO_E_OK && out_len == len;
+      if (!ok) goto server_fail;
+
+      free_Frame(res); res = NULL;
+      goto end_of_else_clause;
+     server_fail:
+      /* The server screwed up somehow.  Now what? */
+      if (res) {
+         UChar* reason = NULL;
+         if (parse_Frame_asciiz(res, "FAIL", &reason)) {
+            VG_(umsg)("set_CEnt (reading data from DI server): fail: "
+                      "%s\n", reason);
+         } else {
+            VG_(umsg)("set_CEnt (reading data from DI server): fail: "
+                      "unknown reason\n");
+         }
+         free_Frame(res); res = NULL;
+      } else {
+         VG_(umsg)("set_CEnt (reading data from DI server): fail: "
+                   "server unexpectedly closed the connection\n");
+      }
+      give_up__comms_lost();
+      /* NOTREACHED */
+      vg_assert(0);
+     end_of_else_clause:
+      {}
+   }
+   
+   ce->off  = off;
+   ce->used = len;
+   vg_assert(ce->used > 0 && ce->used <= CACHE_ENTRY_SIZE);
+}
+
+__attribute__((noinline))
+static UChar get_slowcase ( DiImage* img, DiOffT off )
+{
+   /* Stay sane .. */
+   vg_assert(off < img->size);
+   vg_assert(img->ces_used <= CACHE_N_ENTRIES);
+   UInt i;
+   /* Start the search at entry 1, since the fast-case function
+      checked slot zero already. */
+   for (i = 1; i < img->ces_used; i++) {
+      vg_assert(img->ces[i]);
+      if (is_in_CEnt(img->ces[i], off))
+         break;
+   }
+   vg_assert(i <= img->ces_used);
+   if (i == img->ces_used) {
+      /* It's not in any entry.  Either allocate a new entry or
+         recycle the LRU one. */
+      if (img->ces_used == CACHE_N_ENTRIES) {
+         /* All entries in use.  Recycle the (ostensibly) LRU one. */
+         set_CEnt(img, CACHE_N_ENTRIES-1, off);
+         i = CACHE_N_ENTRIES-1;
+      } else {
+         /* Allocate a new one, and fill it in. */
+         UInt entNo = alloc_CEnt(img);
+         set_CEnt(img, entNo, off);
+         i = entNo;
+      }
+   } else {
+      /* We found it at position 'i'. */
+      vg_assert(i > 0);
+   }
+   if (i > 0) {
+      move_CEnt_to_top(img, i);
+      i = 0;
+   }
+   vg_assert(is_in_CEnt(img->ces[i], off));
+   return img->ces[i]->data[ off - img->ces[i]->off ];
+}
+
+// This is called a lot, so do the usual fast/slow split stuff on it. */
+static UChar get ( DiImage* img, DiOffT off )
+{
+   /* Most likely case is, it's in the ces[0] position. */
+   /* ML_(img_from_local_file) requests a read for ces[0] when
+      creating the image.  Hence slot zero is always non-NULL, so we
+      can skip this test. */
+   if (LIKELY(/* img->ces[0] != NULL && */
+              is_in_CEnt(img->ces[0], off))) {
+      return img->ces[0]->data[ off - img->ces[0]->off ];
+   }
+   /* Else we'll have to fish around for it. */
+   return get_slowcase(img, off);
+}
+
+/* Create an image from a file in the local filesystem.  This is
+   relatively straightforward. */
+DiImage* ML_(img_from_local_file)(const HChar* fullpath)
+{
+   SysRes         fd;
+   struct vg_stat stat_buf;
+   DiOffT         size;
+
+   fd = VG_(open)(fullpath, VKI_O_RDONLY, 0);
+   if (sr_isError(fd))
+      return NULL;
+
+   if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
+      VG_(close)(sr_Res(fd));
+      return NULL;
+   }
+
+   size = stat_buf.size;
+   if (size == 0 || size == DiOffT_INVALID
+       || /* size is unrepresentable as a SizeT */
+          size != (DiOffT)(SizeT)(size)) {
+      VG_(close)(sr_Res(fd));
+      return NULL; 
+   }
+
+   DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
+   img->source.is_local = True;
+   img->source.fd       = sr_Res(fd);
+   img->size            = size;
+   img->ces_used        = 0;
+   img->source.name     = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
+   /* img->ces is already zeroed out */
+   vg_assert(img->source.fd >= 0);
+
+   /* Force the zeroth entry to be the first chunk of the file.
+      That's likely to be the first part that's requested anyway, and
+      loading it at this point forcing img->cent[0] to always be
+      non-empty, thereby saving us an is-it-empty check on the fast
+      path in get(). */
+   UInt entNo = alloc_CEnt(img);
+   vg_assert(entNo == 0);
+   set_CEnt(img, 0, 0);
+
+   return img;
+}
+
+
+/* Create an image from a file on a remote debuginfo server.  This is
+   more complex.  There are lots of ways in which it can fail. */
+DiImage* ML_(img_from_di_server)(const HChar* filename,
+                                 const HChar* serverAddr)
+{
+   if (filename == NULL || serverAddr == NULL)
+      return NULL;
+
+   /* The filename must be a plain filename -- no slashes at all. */
+   if (VG_(strchr)(filename, '/') != NULL)
+      return NULL;
+
+   /* Try to connect to the server.  A side effect of this is to parse
+      and reject, if syntactically invalid, |serverAddr|.  Reasons why
+      this could fail:
+      - serverAddr is not of the form d.d.d.d:d or d.d.d.d
+      - attempt to connect to that address:port failed
+   */
+   Int sd = VG_(connect_via_socket)(serverAddr);
+   if (sd < 0)
+      return NULL;
+   if (!set_blocking(sd))
+      return NULL;
+   Int one = 1;
+   Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY, 
+                            &one, sizeof(one));
+   vg_assert(sr == 0);
+
+   /* Ok, we got a connection.  Ask it for version string, so as to be
+      reasonably sure we're talking to an instance of
+      auxprogs/valgrind-di-server and not to some other random program
+      that happens to be listening on that port. */
+   Frame* req = mk_Frame_noargs("VERS");
+   Frame* res = do_transaction(sd, req);
+   if (res == NULL)
+      goto fail; // do_transaction failed?!
+   UChar* vstr = NULL;
+   if (!parse_Frame_asciiz(res, "VEOK", &vstr))
+      goto fail; // unexpected response kind, or invalid ID string
+   vg_assert(vstr);
+   if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1",
+                   (const HChar*)vstr) != 0)
+      goto fail; // wrong version string
+   free_Frame(req);
+   free_Frame(res);
+   req = NULL;
+   res = NULL;
+
+   /* Server seems plausible.  Present it with the name of the file we
+      want and see if it'll give us back a session ID for it. */
+   req = mk_Frame_asciiz("OPEN", filename);
+   res = do_transaction(sd, req);
+   if (res == NULL)
+      goto fail;
+   ULong session_id = 0, size = 0;
+   if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size))
+      goto fail;
+   free_Frame(req);
+   free_Frame(res);
+   req = NULL;
+   res = NULL;
+
+   /* We have a session ID.  We're ready to roll. */
+   DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage));
+   img->source.is_local   = False;
+   img->source.fd         = sd;
+   img->source.session_id = session_id;
+   img->size              = size;
+   img->ces_used          = 0;
+   img->source.name       = ML_(dinfo_zalloc)("di.image.ML_ifds.2",
+                                              20 + VG_(strlen)(filename)
+                                                 + VG_(strlen)(serverAddr));
+   VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr);
+
+   /* img->ces is already zeroed out */
+   vg_assert(img->source.fd >= 0);
+
+   /* See comment on equivalent bit in ML_(img_from_local_file) for
+      rationale. */
+   UInt entNo = alloc_CEnt(img);
+   vg_assert(entNo == 0);
+   set_CEnt(img, 0, 0);
+
+   return img;
+
+  fail:
+   if (req) free_Frame(req);
+   if (res) {
+      UChar* reason = NULL;
+      if (parse_Frame_asciiz(res, "FAIL", &reason)) {
+         // HACK: if it's just telling us that the file can't
+         // be opened, don't print it, else we'll get flooded with
+         // such complaints, one for each main object for which there
+         // isn't a debuginfo file on the server.
+         if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file"))
+            VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason);
+      } else {
+         VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n");
+      }
+      free_Frame(res);
+   }
+   VG_(close)(sd);
+   return NULL;
+}
+
+void ML_(img_done)(DiImage* img)
+{
+   vg_assert(img);
+   if (img->source.is_local) {
+      /* Close the file; nothing else to do. */
+      vg_assert(img->source.session_id == 0);
+      VG_(close)(img->source.fd);
+   } else {
+      /* Close the socket.  The server can detect this and will scrub
+         the connection when it happens, so there's no need to tell it
+         explicitly by sending it a "CLOSE" message, or any such. */
+      vg_assert(img->source.session_id != 0);
+      VG_(close)(img->source.fd);
+   }
+
+   /* Free up the cache entries, ultimately |img| itself. */
+   UInt i;
+   vg_assert(img->ces_used <= CACHE_N_ENTRIES);
+   for (i = 0; i < img->ces_used; i++) {
+      ML_(dinfo_free)(img->ces[i]);
+   }
+   /* Take the opportunity to sanity check the rest. */
+   for (i = i; i < img->ces_used; i++) {
+      vg_assert(img->ces[i] == NULL);
+   }
+   ML_(dinfo_free)(img->source.name);
+   ML_(dinfo_free)(img);
+}
+
+DiOffT ML_(img_size)(DiImage* img)
+{
+   vg_assert(img);
+   return img->size;
+}
+
+inline Bool ML_(img_valid)(DiImage* img, DiOffT offset, SizeT size)
+{
+   vg_assert(img);
+   vg_assert(offset != DiOffT_INVALID);
+   return img->size > 0 && offset + size <= (DiOffT)img->size;
+}
+
+/* Check the given range is valid, and if not, shut down the system.
+   An invalid range would imply that we're trying to read outside the
+   image, which normally means the image is corrupted somehow, or the
+   caller is buggy.  Recovering is too complex, and we have
+   probably-corrupt debuginfo, so just give up. */
+static void ensure_valid(DiImage* img, DiOffT offset, SizeT size,
+                         const HChar* caller)
+{
+   if (LIKELY(ML_(img_valid)(img, offset, size)))
+      return;
+   VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n");
+   VG_(umsg)("Valgrind:   during call to %s\n", caller);
+   VG_(umsg)("Valgrind:   request for range [%llu, +%llu) exceeds\n",
+             (ULong)offset, (ULong)size);
+   VG_(umsg)("Valgrind:   valid image size of %llu for image:\n",
+             (ULong)img->size);
+   VG_(umsg)("Valgrind:   \"%s\"\n", img->source.name);
+   give_up__image_overrun();
+}
+
+
+void ML_(img_get)(/*OUT*/void* dst,
+                  DiImage* img, DiOffT offset, SizeT size)
+{
+   vg_assert(img);
+   vg_assert(size > 0);
+   ensure_valid(img, offset, size, "ML_(img_get)");
+   SizeT i;
+   for (i = 0; i < size; i++) {
+      ((UChar*)dst)[i] = get(img, offset + i);
+   }
+}
+
+SizeT ML_(img_get_some)(/*OUT*/void* dst,
+                        DiImage* img, DiOffT offset, SizeT size)
+{
+   vg_assert(img);
+   vg_assert(size > 0);
+   ensure_valid(img, offset, size, "ML_(img_get_some)");
+   UChar* dstU = (UChar*)dst;
+   /* Use |get| in the normal way to get the first byte of the range.
+      This guarantees to put the cache entry containing |offset| in
+      position zero. */
+   dstU[0] = get(img, offset);
+   /* Now just read as many bytes as we can (or need) directly out of
+      entry zero, without bothering to call |get| each time. */
+   CEnt* ce = img->ces[0];
+   vg_assert(ce && ce->used >= 1);
+   vg_assert(is_in_CEnt(ce, offset));
+   SizeT nToCopy = size - 1;
+   SizeT nAvail  = (SizeT)(ce->used - (offset + 1 - ce->off));
+   vg_assert(nAvail >= 0 && nAvail <= ce->used-1);
+   if (nAvail < nToCopy) nToCopy = nAvail;
+   VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy);
+   return nToCopy + 1;
+}
+
+
+SizeT ML_(img_strlen)(DiImage* img, DiOffT off)
+{
+   ensure_valid(img, off, 1, "ML_(img_strlen)");
+   SizeT i = 0;
+   while (get(img, off + i) != 0) i++;
+   return i;
+}
+
+HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset)
+{
+   ensure_valid(img, offset, 1, "ML_(img_strdup)");
+   SizeT  len = ML_(img_strlen)(img, offset);
+   HChar* res = ML_(dinfo_zalloc)(cc, len+1);
+   SizeT  i;
+   for (i = 0; i < len; i++) {
+      res[i] = get(img, offset+i);
+   }
+   vg_assert(res[len] == 0);
+   return res;
+}
+
+Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2)
+{
+   ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)");
+   ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)");
+   while (True) {
+      UChar c1 = get(img, off1);
+      UChar c2 = get(img, off2);
+      if (c1 < c2) return -1;
+      if (c1 > c2) return 1;
+      if (c1 == 0) return 0;
+      off1++; off2++;
+   }
+}
+
+Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2)
+{
+   ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
+   while (True) {
+      UChar c1 = get(img, off1);
+      UChar c2 = *(UChar*)str2;
+      if (c1 < c2) return -1;
+      if (c1 > c2) return 1;
+      if (c1 == 0) return 0;
+      off1++; str2++;
+   }
+}
+
+UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset)
+{
+   ensure_valid(img, offset, 1, "ML_(img_get_UChar)");
+   return get(img, offset);
+}
+
+UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset)
+{
+   UShort r;
+   ML_(img_get)(&r, img, offset, sizeof(r));
+   return r;
+}
+
+UInt ML_(img_get_UInt)(DiImage* img, DiOffT offset)
+{
+   UInt r;
+   ML_(img_get)(&r, img, offset, sizeof(r));
+   return r;
+}
+
+ULong ML_(img_get_ULong)(DiImage* img, DiOffT offset)
+{
+   ULong r;
+   ML_(img_get)(&r, img, offset, sizeof(r));
+   return r;
+}
+
+
+/*
+ * This routine for calculating the CRC for a separate debug file
+ * is GPLed code borrowed from GNU binutils.
+ */
+UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img)
+{
+  static const UInt crc32_table[256] =
+    {
+      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+      0x2d02ef8d
+    };
+
+   vg_assert(img);
+
+   /* If the image is local, calculate the CRC here directly.  If it's
+      remote, forward the request to the server. */
+   if (img->source.is_local) {
+      /* Work through the image in 1 KB chunks. */
+      UInt   crc      = 0xFFFFFFFF;
+      DiOffT img_szB  = ML_(img_size)(img);
+      DiOffT curr_off = 0;
+      while (1) {
+         vg_assert(curr_off >= 0 && curr_off <= img_szB);
+         if (curr_off == img_szB) break;
+         DiOffT avail = img_szB - curr_off;
+         vg_assert(avail > 0 && avail <= img_szB);
+         if (avail > 1024) avail = 1024;
+         UChar buf[1024];
+         SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail);
+         vg_assert(nGot >= 1 && nGot <= avail);
+         UInt i;
+         for (i = 0; i < (UInt)nGot; i++)
+            crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
+         curr_off += nGot;
+      }
+      return ~crc & 0xFFFFFFFF;
+   } else {
+      Frame* req = mk_Frame_noargs("CRC3");
+      Frame* res = do_transaction(img->source.fd, req);
+      if (!res) goto remote_crc_fail;
+      ULong crc32 = 0;
+      if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail;
+      if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail;
+      if (req) free_Frame(req);
+      if (res) free_Frame(res);
+      return (UInt)crc32;
+     remote_crc_fail:
+
+      // XXXX common this up with the READ diagnostic cases
+      if (res) {
+         UChar* reason = NULL;
+         if (parse_Frame_asciiz(res, "FAIL", &reason)) {
+            VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
+                      "%s\n", reason);
+         } else {
+            VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
+                      "unknown reason\n");
+         }
+      } else {
+         VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
+                   "server unexpectedly closed the connection\n");
+      }
+
+      if (req) free_Frame(req);
+      if (res) free_Frame(res);
+      // FIXME: now what?
+      give_up__comms_lost();
+      /* NOTREACHED */
+      vg_assert(0);
+   }
+   /*NOTREACHED*/
+   vg_assert(0);
+}
+
+////////////////////////////////////////////////////
+#include "minilzo-inl.c"
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                  image.c ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_debuginfo/lzoconf.h b/coregrind/m_debuginfo/lzoconf.h
new file mode 100644
index 0000000..23c6ca9
--- /dev/null
+++ b/coregrind/m_debuginfo/lzoconf.h
@@ -0,0 +1,446 @@
+/* lzoconf.h -- configuration of the LZO data compression library
+
+   This file is part of the LZO real-time data compression library.
+
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+   All Rights Reserved.
+
+   The LZO library 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; either version 2 of
+   the License, or (at your option) any later version.
+
+   The LZO library 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 the LZO library; see the file COPYING.
+   If not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+   Markus F.X.J. Oberhumer
+   <markus@oberhumer.com>
+   http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZOCONF_H_INCLUDED
+#define __LZOCONF_H_INCLUDED 1
+
+#define LZO_VERSION             0x2060
+#define LZO_VERSION_STRING      "2.06"
+#define LZO_VERSION_DATE        "Aug 12 2011"
+
+/* internal Autoconf configuration file - only used when building LZO */
+#if defined(LZO_HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+#include <limits.h>
+#include <stddef.h>
+
+
+/***********************************************************************
+// LZO requires a conforming <limits.h>
+************************************************************************/
+
+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
+#  error "invalid CHAR_BIT"
+#endif
+#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
+#  error "check your compiler installation"
+#endif
+#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
+#  error "your limits.h macros are broken"
+#endif
+
+/* get OS and architecture defines */
+#ifndef __LZODEFS_H_INCLUDED
+#include "lzodefs.h"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// some core defines
+************************************************************************/
+
+#if !defined(LZO_UINT32_C)
+#  if (UINT_MAX < LZO_0xffffffffL)
+#    define LZO_UINT32_C(c)     c ## UL
+#  else
+#    define LZO_UINT32_C(c)     ((c) + 0U)
+#  endif
+#endif
+
+/* memory checkers */
+#if !defined(__LZO_CHECKER)
+#  if defined(__BOUNDS_CHECKING_ON)
+#    define __LZO_CHECKER       1
+#  elif defined(__CHECKER__)
+#    define __LZO_CHECKER       1
+#  elif defined(__INSURE__)
+#    define __LZO_CHECKER       1
+#  elif defined(__PURIFY__)
+#    define __LZO_CHECKER       1
+#  endif
+#endif
+
+
+/***********************************************************************
+// integral and pointer types
+************************************************************************/
+
+/* lzo_uint should match size_t */
+#if !defined(LZO_UINT_MAX)
+#  if defined(LZO_ABI_LLP64) /* WIN64 */
+#    if defined(LZO_OS_WIN64)
+     typedef unsigned __int64   lzo_uint;
+     typedef __int64            lzo_int;
+#    else
+     typedef unsigned long long lzo_uint;
+     typedef long long          lzo_int;
+#    endif
+#    define LZO_UINT_MAX        0xffffffffffffffffull
+#    define LZO_INT_MAX         9223372036854775807LL
+#    define LZO_INT_MIN         (-1LL - LZO_INT_MAX)
+#  elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
+     typedef unsigned int       lzo_uint;
+     typedef int                lzo_int;
+#    define LZO_UINT_MAX        UINT_MAX
+#    define LZO_INT_MAX         INT_MAX
+#    define LZO_INT_MIN         INT_MIN
+#  elif (ULONG_MAX >= LZO_0xffffffffL)
+     typedef unsigned long      lzo_uint;
+     typedef long               lzo_int;
+#    define LZO_UINT_MAX        ULONG_MAX
+#    define LZO_INT_MAX         LONG_MAX
+#    define LZO_INT_MIN         LONG_MIN
+#  else
+#    error "lzo_uint"
+#  endif
+#endif
+
+/* Integral types with 32 bits or more. */
+#if !defined(LZO_UINT32_MAX)
+#  if (UINT_MAX >= LZO_0xffffffffL)
+     typedef unsigned int       lzo_uint32;
+     typedef int                lzo_int32;
+#    define LZO_UINT32_MAX      UINT_MAX
+#    define LZO_INT32_MAX       INT_MAX
+#    define LZO_INT32_MIN       INT_MIN
+#  elif (ULONG_MAX >= LZO_0xffffffffL)
+     typedef unsigned long      lzo_uint32;
+     typedef long               lzo_int32;
+#    define LZO_UINT32_MAX      ULONG_MAX
+#    define LZO_INT32_MAX       LONG_MAX
+#    define LZO_INT32_MIN       LONG_MIN
+#  else
+#    error "lzo_uint32"
+#  endif
+#endif
+
+/* Integral types with exactly 64 bits. */
+#if !defined(LZO_UINT64_MAX)
+#  if (LZO_UINT_MAX >= LZO_0xffffffffL)
+#   if ((((LZO_UINT_MAX) >> 31) >> 31) == 3)
+#    define lzo_uint64          lzo_uint
+#    define lzo_int64           lzo_int
+#    define LZO_UINT64_MAX      LZO_UINT_MAX
+#    define LZO_INT64_MAX       LZO_INT_MAX
+#    define LZO_INT64_MIN       LZO_INT_MIN
+#   endif
+#  elif (ULONG_MAX >= LZO_0xffffffffL)
+#   if ((((ULONG_MAX) >> 31) >> 31) == 3)
+     typedef unsigned long      lzo_uint64;
+     typedef long               lzo_int64;
+#    define LZO_UINT64_MAX      ULONG_MAX
+#    define LZO_INT64_MAX       LONG_MAX
+#    define LZO_INT64_MIN       LONG_MIN
+#   endif
+#  endif
+#endif
+
+/* The larger type of lzo_uint and lzo_uint32. */
+#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
+#  define lzo_xint              lzo_uint
+#else
+#  define lzo_xint              lzo_uint32
+#endif
+
+/* Memory model that allows to access memory at offsets of lzo_uint. */
+#if !defined(__LZO_MMODEL)
+#  if (LZO_UINT_MAX <= UINT_MAX)
+#    define __LZO_MMODEL        /*empty*/
+#  elif defined(LZO_HAVE_MM_HUGE_PTR)
+#    define __LZO_MMODEL_HUGE   1
+#    define __LZO_MMODEL        __huge
+#  else
+#    define __LZO_MMODEL        /*empty*/
+#  endif
+#endif
+
+/* no typedef here because of const-pointer issues */
+#define lzo_bytep               unsigned char __LZO_MMODEL *
+#define lzo_charp               char __LZO_MMODEL *
+#define lzo_voidp               void __LZO_MMODEL *
+#define lzo_shortp              short __LZO_MMODEL *
+#define lzo_ushortp             unsigned short __LZO_MMODEL *
+#define lzo_uint32p             lzo_uint32 __LZO_MMODEL *
+#define lzo_int32p              lzo_int32 __LZO_MMODEL *
+#if defined(LZO_UINT64_MAX)
+#define lzo_uint64p             lzo_uint64 __LZO_MMODEL *
+#define lzo_int64p              lzo_int64 __LZO_MMODEL *
+#endif
+#define lzo_uintp               lzo_uint __LZO_MMODEL *
+#define lzo_intp                lzo_int __LZO_MMODEL *
+#define lzo_xintp               lzo_xint __LZO_MMODEL *
+#define lzo_voidpp              lzo_voidp __LZO_MMODEL *
+#define lzo_bytepp              lzo_bytep __LZO_MMODEL *
+/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
+#define lzo_byte                unsigned char __LZO_MMODEL
+
+typedef int lzo_bool;
+
+
+/***********************************************************************
+// function types
+************************************************************************/
+
+/* name mangling */
+#if !defined(__LZO_EXTERN_C)
+#  ifdef __cplusplus
+#    define __LZO_EXTERN_C      extern "C"
+#  else
+#    define __LZO_EXTERN_C      extern
+#  endif
+#endif
+
+/* calling convention */
+#if !defined(__LZO_CDECL)
+#  define __LZO_CDECL           __lzo_cdecl
+#endif
+
+/* DLL export information */
+#if !defined(__LZO_EXPORT1)
+#  define __LZO_EXPORT1         /*empty*/
+#endif
+#if !defined(__LZO_EXPORT2)
+#  define __LZO_EXPORT2         /*empty*/
+#endif
+
+/* __cdecl calling convention for public C and assembly functions */
+#if !defined(LZO_PUBLIC)
+#  define LZO_PUBLIC(_rettype)  __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
+#endif
+#if !defined(LZO_EXTERN)
+#  define LZO_EXTERN(_rettype)  __LZO_EXTERN_C LZO_PUBLIC(_rettype)
+#endif
+#if !defined(LZO_PRIVATE)
+#  define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
+#endif
+
+/* function types */
+typedef int
+(__LZO_CDECL *lzo_compress_t)   ( const lzo_bytep src, lzo_uint  src_len,
+                                        lzo_bytep dst, lzo_uintp dst_len,
+                                        lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint  src_len,
+                                        lzo_bytep dst, lzo_uintp dst_len,
+                                        lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_optimize_t)   (       lzo_bytep src, lzo_uint  src_len,
+                                        lzo_bytep dst, lzo_uintp dst_len,
+                                        lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint  src_len,
+                                         lzo_bytep dst, lzo_uintp dst_len,
+                                         lzo_voidp wrkmem,
+                                   const lzo_bytep dict, lzo_uint dict_len );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint  src_len,
+                                           lzo_bytep dst, lzo_uintp dst_len,
+                                           lzo_voidp wrkmem,
+                                     const lzo_bytep dict, lzo_uint dict_len );
+
+
+/* Callback interface. Currently only the progress indicator ("nprogress")
+ * is used, but this may change in a future release. */
+
+struct lzo_callback_t;
+typedef struct lzo_callback_t lzo_callback_t;
+#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
+
+/* malloc & free function types */
+typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
+    (lzo_callback_p self, lzo_uint items, lzo_uint size);
+typedef void      (__LZO_CDECL *lzo_free_func_t)
+    (lzo_callback_p self, lzo_voidp ptr);
+
+/* a progress indicator callback function */
+typedef void (__LZO_CDECL *lzo_progress_func_t)
+    (lzo_callback_p, lzo_uint, lzo_uint, int);
+
+struct lzo_callback_t
+{
+    /* custom allocators (set to 0 to disable) */
+    lzo_alloc_func_t nalloc;                /* [not used right now] */
+    lzo_free_func_t nfree;                  /* [not used right now] */
+
+    /* a progress indicator callback function (set to 0 to disable) */
+    lzo_progress_func_t nprogress;
+
+    /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
+     * callbacks points back to this struct, so you are free to store
+     * some extra info in the following variables. */
+    lzo_voidp user1;
+    lzo_xint user2;
+    lzo_xint user3;
+};
+
+
+/***********************************************************************
+// error codes and prototypes
+************************************************************************/
+
+/* Error codes for the compression/decompression functions. Negative
+ * values are errors, positive values will be used for special but
+ * normal events.
+ */
+#define LZO_E_OK                    0
+#define LZO_E_ERROR                 (-1)
+#define LZO_E_OUT_OF_MEMORY         (-2)    /* [lzo_alloc_func_t failure] */
+#define LZO_E_NOT_COMPRESSIBLE      (-3)    /* [not used right now] */
+#define LZO_E_INPUT_OVERRUN         (-4)
+#define LZO_E_OUTPUT_OVERRUN        (-5)
+#define LZO_E_LOOKBEHIND_OVERRUN    (-6)
+#define LZO_E_EOF_NOT_FOUND         (-7)
+#define LZO_E_INPUT_NOT_CONSUMED    (-8)
+#define LZO_E_NOT_YET_IMPLEMENTED   (-9)    /* [not used right now] */
+#define LZO_E_INVALID_ARGUMENT      (-10)
+
+
+#ifndef lzo_sizeof_dict_t
+#  define lzo_sizeof_dict_t     ((unsigned)sizeof(lzo_bytep))
+#endif
+
+/* lzo_init() should be the first function you call.
+ * Check the return code !
+ *
+ * lzo_init() is a macro to allow checking that the library and the
+ * compiler's view of various types are consistent.
+ */
+#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
+    (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
+    (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
+    (int)sizeof(lzo_callback_t))
+LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
+
+/* version functions (useful for shared libraries) */
+LZO_EXTERN(unsigned) lzo_version(void);
+LZO_EXTERN(const char *) lzo_version_string(void);
+LZO_EXTERN(const char *) lzo_version_date(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
+
+/* string functions */
+LZO_EXTERN(int)
+    lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
+LZO_EXTERN(lzo_voidp)
+    lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
+LZO_EXTERN(lzo_voidp)
+    lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
+LZO_EXTERN(lzo_voidp)
+    lzo_memset(lzo_voidp buf, int c, lzo_uint len);
+
+/* checksum functions */
+LZO_EXTERN(lzo_uint32)
+    lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
+LZO_EXTERN(lzo_uint32)
+    lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
+LZO_EXTERN(const lzo_uint32p)
+    lzo_get_crc32_table(void);
+
+/* misc. */
+LZO_EXTERN(int) _lzo_config_check(void);
+typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
+typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
+typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t;
+
+/* align a char pointer on a boundary that is a multiple of 'size' */
+LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
+#define LZO_PTR_ALIGN_UP(p,size) \
+    ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
+
+
+/***********************************************************************
+// deprecated macros - only for backward compatibility with LZO v1.xx
+************************************************************************/
+
+#if defined(LZO_CFG_COMPAT)
+
+#define __LZOCONF_H 1
+
+#if defined(LZO_ARCH_I086)
+#  define __LZO_i386 1
+#elif defined(LZO_ARCH_I386)
+#  define __LZO_i386 1
+#endif
+
+#if defined(LZO_OS_DOS16)
+#  define __LZO_DOS 1
+#  define __LZO_DOS16 1
+#elif defined(LZO_OS_DOS32)
+#  define __LZO_DOS 1
+#elif defined(LZO_OS_WIN16)
+#  define __LZO_WIN 1
+#  define __LZO_WIN16 1
+#elif defined(LZO_OS_WIN32)
+#  define __LZO_WIN 1
+#endif
+
+#define __LZO_CMODEL            /*empty*/
+#define __LZO_DMODEL            /*empty*/
+#define __LZO_ENTRY             __LZO_CDECL
+#define LZO_EXTERN_CDECL        LZO_EXTERN
+#define LZO_ALIGN               LZO_PTR_ALIGN_UP
+
+#define lzo_compress_asm_t      lzo_compress_t
+#define lzo_decompress_asm_t    lzo_decompress_t
+
+#endif /* LZO_CFG_COMPAT */
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
diff --git a/coregrind/m_debuginfo/lzodefs.h b/coregrind/m_debuginfo/lzodefs.h
new file mode 100644
index 0000000..0e40e33
--- /dev/null
+++ b/coregrind/m_debuginfo/lzodefs.h
@@ -0,0 +1,1852 @@
+/* lzodefs.h -- architecture, OS and compiler specific defines
+
+   This file is part of the LZO real-time data compression library.
+
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+   All Rights Reserved.
+
+   The LZO library 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; either version 2 of
+   the License, or (at your option) any later version.
+
+   The LZO library 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 the LZO library; see the file COPYING.
+   If not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+   Markus F.X.J. Oberhumer
+   <markus@oberhumer.com>
+   http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZODEFS_H_INCLUDED
+#define __LZODEFS_H_INCLUDED 1
+
+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
+#  define __CYGWIN__ __CYGWIN32__
+#endif
+#if defined(__IBMCPP__) && !defined(__IBMC__)
+#  define __IBMC__ __IBMCPP__
+#endif
+#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
+#  define __INTEL_COMPILER __ICL
+#endif
+#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
+#  define _ALL_SOURCE 1
+#endif
+#if defined(__mips__) && defined(__R5900__)
+#  if !defined(__LONG_MAX__)
+#    define __LONG_MAX__ 9223372036854775807L
+#  endif
+#endif
+#if defined(__INTEL_COMPILER) && defined(__linux__)
+#  pragma warning(disable: 193)
+#endif
+#if defined(__KEIL__) && defined(__C166__)
+#  pragma warning disable = 322
+#elif 0 && defined(__C251__)
+#  pragma warning disable = 322
+#endif
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+#  if (_MSC_VER >= 1300)
+#    pragma warning(disable: 4668)
+#  endif
+#endif
+#if 0 && defined(__WATCOMC__)
+#  if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
+#    pragma warning 203 9
+#  endif
+#endif
+#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
+#  pragma option -h
+#endif
+#if 0
+#define LZO_0xffffL             0xfffful
+#define LZO_0xffffffffL         0xfffffffful
+#else
+#define LZO_0xffffL             65535ul
+#define LZO_0xffffffffL         4294967295ul
+#endif
+#if (LZO_0xffffL == LZO_0xffffffffL)
+#  error "your preprocessor is broken 1"
+#endif
+#if (16ul * 16384ul != 262144ul)
+#  error "your preprocessor is broken 2"
+#endif
+#if 0
+#if (32767 >= 4294967295ul)
+#  error "your preprocessor is broken 3"
+#endif
+#if (65535u >= 4294967295ul)
+#  error "your preprocessor is broken 4"
+#endif
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
+#  if !defined(MSDOS)
+#    define MSDOS 1
+#  endif
+#  if !defined(_MSDOS)
+#    define _MSDOS 1
+#  endif
+#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)
+#  if (__VERSION == 520) && (MB_LEN_MAX == 1)
+#    if !defined(__AZTEC_C__)
+#      define __AZTEC_C__ __VERSION
+#    endif
+#    if !defined(__DOS__)
+#      define __DOS__ 1
+#    endif
+#  endif
+#endif
+#endif
+#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
+#  define ptrdiff_t long
+#  define _PTRDIFF_T_DEFINED 1
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#  undef __LZO_RENAME_A
+#  undef __LZO_RENAME_B
+#  if defined(__AZTEC_C__) && defined(__DOS__)
+#    define __LZO_RENAME_A 1
+#  elif defined(_MSC_VER) && defined(MSDOS)
+#    if (_MSC_VER < 600)
+#      define __LZO_RENAME_A 1
+#    elif (_MSC_VER < 700)
+#      define __LZO_RENAME_B 1
+#    endif
+#  elif defined(__TSC__) && defined(__OS2__)
+#    define __LZO_RENAME_A 1
+#  elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)
+#    define __LZO_RENAME_A 1
+#  elif defined(__PACIFIC__) && defined(DOS)
+#    if !defined(__far)
+#      define __far far
+#    endif
+#    if !defined(__near)
+#      define __near near
+#    endif
+#  endif
+#  if defined(__LZO_RENAME_A)
+#    if !defined(__cdecl)
+#      define __cdecl cdecl
+#    endif
+#    if !defined(__far)
+#      define __far far
+#    endif
+#    if !defined(__huge)
+#      define __huge huge
+#    endif
+#    if !defined(__near)
+#      define __near near
+#    endif
+#    if !defined(__pascal)
+#      define __pascal pascal
+#    endif
+#    if !defined(__huge)
+#      define __huge huge
+#    endif
+#  elif defined(__LZO_RENAME_B)
+#    if !defined(__cdecl)
+#      define __cdecl _cdecl
+#    endif
+#    if !defined(__far)
+#      define __far _far
+#    endif
+#    if !defined(__huge)
+#      define __huge _huge
+#    endif
+#    if !defined(__near)
+#      define __near _near
+#    endif
+#    if !defined(__pascal)
+#      define __pascal _pascal
+#    endif
+#  elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+#    if !defined(__cdecl)
+#      define __cdecl cdecl
+#    endif
+#    if !defined(__pascal)
+#      define __pascal pascal
+#    endif
+#  endif
+#  undef __LZO_RENAME_A
+#  undef __LZO_RENAME_B
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__AZTEC_C__) && defined(__DOS__)
+#  define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#elif defined(_MSC_VER) && defined(MSDOS)
+#  if (_MSC_VER < 600)
+#    define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#  endif
+#  if (_MSC_VER < 700)
+#    define LZO_BROKEN_INTEGRAL_PROMOTION 1
+#    define LZO_BROKEN_SIZEOF 1
+#  endif
+#elif defined(__PACIFIC__) && defined(DOS)
+#  define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#elif defined(__TURBOC__) && defined(__MSDOS__)
+#  if (__TURBOC__ < 0x0150)
+#    define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#    define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#    define LZO_BROKEN_INTEGRAL_PROMOTION 1
+#  endif
+#  if (__TURBOC__ < 0x0200)
+#    define LZO_BROKEN_SIZEOF 1
+#  endif
+#  if (__TURBOC__ < 0x0400) && defined(__cplusplus)
+#    define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#  endif
+#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+#  define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#  define LZO_BROKEN_SIZEOF 1
+#endif
+#endif
+#if defined(__WATCOMC__) && (__WATCOMC__ < 900)
+#  define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#endif
+#if defined(_CRAY) && defined(_CRAY1)
+#  define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1
+#endif
+#define LZO_PP_STRINGIZE(x)             #x
+#define LZO_PP_MACRO_EXPAND(x)          LZO_PP_STRINGIZE(x)
+#define LZO_PP_CONCAT2(a,b)             a ## b
+#define LZO_PP_CONCAT3(a,b,c)           a ## b ## c
+#define LZO_PP_CONCAT4(a,b,c,d)         a ## b ## c ## d
+#define LZO_PP_CONCAT5(a,b,c,d,e)       a ## b ## c ## d ## e
+#define LZO_PP_ECONCAT2(a,b)            LZO_PP_CONCAT2(a,b)
+#define LZO_PP_ECONCAT3(a,b,c)          LZO_PP_CONCAT3(a,b,c)
+#define LZO_PP_ECONCAT4(a,b,c,d)        LZO_PP_CONCAT4(a,b,c,d)
+#define LZO_PP_ECONCAT5(a,b,c,d,e)      LZO_PP_CONCAT5(a,b,c,d,e)
+#if 1
+#define LZO_CPP_STRINGIZE(x)            #x
+#define LZO_CPP_MACRO_EXPAND(x)         LZO_CPP_STRINGIZE(x)
+#define LZO_CPP_CONCAT2(a,b)            a ## b
+#define LZO_CPP_CONCAT3(a,b,c)          a ## b ## c
+#define LZO_CPP_CONCAT4(a,b,c,d)        a ## b ## c ## d
+#define LZO_CPP_CONCAT5(a,b,c,d,e)      a ## b ## c ## d ## e
+#define LZO_CPP_ECONCAT2(a,b)           LZO_CPP_CONCAT2(a,b)
+#define LZO_CPP_ECONCAT3(a,b,c)         LZO_CPP_CONCAT3(a,b,c)
+#define LZO_CPP_ECONCAT4(a,b,c,d)       LZO_CPP_CONCAT4(a,b,c,d)
+#define LZO_CPP_ECONCAT5(a,b,c,d,e)     LZO_CPP_CONCAT5(a,b,c,d,e)
+#endif
+#define __LZO_MASK_GEN(o,b)     (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#if 1 && defined(__cplusplus)
+#  if !defined(__STDC_CONSTANT_MACROS)
+#    define __STDC_CONSTANT_MACROS 1
+#  endif
+#  if !defined(__STDC_LIMIT_MACROS)
+#    define __STDC_LIMIT_MACROS 1
+#  endif
+#endif
+#if defined(__cplusplus)
+#  define LZO_EXTERN_C extern "C"
+#else
+#  define LZO_EXTERN_C extern
+#endif
+#if !defined(__LZO_OS_OVERRIDE)
+#if (LZO_OS_FREESTANDING)
+#  define LZO_INFO_OS           "freestanding"
+#elif (LZO_OS_EMBEDDED)
+#  define LZO_INFO_OS           "embedded"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+#  define LZO_OS_EMBEDDED       1
+#  define LZO_INFO_OS           "embedded"
+#elif defined(__CYGWIN__) && defined(__GNUC__)
+#  define LZO_OS_CYGWIN         1
+#  define LZO_INFO_OS           "cygwin"
+#elif defined(__EMX__) && defined(__GNUC__)
+#  define LZO_OS_EMX            1
+#  define LZO_INFO_OS           "emx"
+#elif defined(__BEOS__)
+#  define LZO_OS_BEOS           1
+#  define LZO_INFO_OS           "beos"
+#elif defined(__Lynx__)
+#  define LZO_OS_LYNXOS         1
+#  define LZO_INFO_OS           "lynxos"
+#elif defined(__OS400__)
+#  define LZO_OS_OS400          1
+#  define LZO_INFO_OS           "os400"
+#elif defined(__QNX__)
+#  define LZO_OS_QNX            1
+#  define LZO_INFO_OS           "qnx"
+#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)
+#  define LZO_OS_DOS32          1
+#  define LZO_INFO_OS           "dos32"
+#elif defined(__BORLANDC__) && defined(__DPMI16__)
+#  define LZO_OS_DOS16          1
+#  define LZO_INFO_OS           "dos16"
+#elif defined(__ZTC__) && defined(DOS386)
+#  define LZO_OS_DOS32          1
+#  define LZO_INFO_OS           "dos32"
+#elif defined(__OS2__) || defined(__OS2V2__)
+#  if (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_OS216        1
+#    define LZO_INFO_OS         "os216"
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_OS_OS2          1
+#    define LZO_INFO_OS         "os2"
+#  else
+#    error "check your limits.h header"
+#  endif
+#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)
+#  define LZO_OS_WIN64          1
+#  define LZO_INFO_OS           "win64"
+#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)
+#  define LZO_OS_WIN32          1
+#  define LZO_INFO_OS           "win32"
+#elif defined(__MWERKS__) && defined(__INTEL__)
+#  define LZO_OS_WIN32          1
+#  define LZO_INFO_OS           "win32"
+#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+#  if (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_WIN16        1
+#    define LZO_INFO_OS         "win16"
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_OS_WIN32        1
+#    define LZO_INFO_OS         "win32"
+#  else
+#    error "check your limits.h header"
+#  endif
+#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))
+#  if (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_DOS16        1
+#    define LZO_INFO_OS         "dos16"
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_OS_DOS32        1
+#    define LZO_INFO_OS         "dos32"
+#  else
+#    error "check your limits.h header"
+#  endif
+#elif defined(__WATCOMC__)
+#  if defined(__NT__) && (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_DOS16        1
+#    define LZO_INFO_OS         "dos16"
+#  elif defined(__NT__) && (__WATCOMC__ < 1100)
+#    define LZO_OS_WIN32        1
+#    define LZO_INFO_OS         "win32"
+#  elif defined(__linux__) || defined(__LINUX__)
+#    define LZO_OS_POSIX        1
+#    define LZO_INFO_OS         "posix"
+#  else
+#    error "please specify a target using the -bt compiler option"
+#  endif
+#elif defined(__palmos__)
+#  define LZO_OS_PALMOS         1
+#  define LZO_INFO_OS           "palmos"
+#elif defined(__TOS__) || defined(__atarist__)
+#  define LZO_OS_TOS            1
+#  define LZO_INFO_OS           "tos"
+#elif defined(macintosh) && !defined(__ppc__)
+#  define LZO_OS_MACCLASSIC     1
+#  define LZO_INFO_OS           "macclassic"
+#elif defined(__VMS)
+#  define LZO_OS_VMS            1
+#  define LZO_INFO_OS           "vms"
+#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+#  define LZO_OS_CONSOLE        1
+#  define LZO_OS_CONSOLE_PS2    1
+#  define LZO_INFO_OS           "console"
+#  define LZO_INFO_OS_CONSOLE   "ps2"
+#elif (defined(__mips__) && defined(__psp__))
+#  define LZO_OS_CONSOLE        1
+#  define LZO_OS_CONSOLE_PSP    1
+#  define LZO_INFO_OS           "console"
+#  define LZO_INFO_OS_CONSOLE   "psp"
+#else
+#  define LZO_OS_POSIX          1
+#  define LZO_INFO_OS           "posix"
+#endif
+#if (LZO_OS_POSIX)
+#  if defined(_AIX) || defined(__AIX__) || defined(__aix__)
+#    define LZO_OS_POSIX_AIX        1
+#    define LZO_INFO_OS_POSIX       "aix"
+#  elif defined(__FreeBSD__)
+#    define LZO_OS_POSIX_FREEBSD    1
+#    define LZO_INFO_OS_POSIX       "freebsd"
+#  elif defined(__hpux__) || defined(__hpux)
+#    define LZO_OS_POSIX_HPUX       1
+#    define LZO_INFO_OS_POSIX       "hpux"
+#  elif defined(__INTERIX)
+#    define LZO_OS_POSIX_INTERIX    1
+#    define LZO_INFO_OS_POSIX       "interix"
+#  elif defined(__IRIX__) || defined(__irix__)
+#    define LZO_OS_POSIX_IRIX       1
+#    define LZO_INFO_OS_POSIX       "irix"
+#  elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
+#    define LZO_OS_POSIX_LINUX      1
+#    define LZO_INFO_OS_POSIX       "linux"
+#  elif defined(__APPLE__) || defined(__MACOS__)
+#    define LZO_OS_POSIX_MACOSX     1
+#    define LZO_INFO_OS_POSIX       "macosx"
+#  elif defined(__minix__) || defined(__minix)
+#    define LZO_OS_POSIX_MINIX      1
+#    define LZO_INFO_OS_POSIX       "minix"
+#  elif defined(__NetBSD__)
+#    define LZO_OS_POSIX_NETBSD     1
+#    define LZO_INFO_OS_POSIX       "netbsd"
+#  elif defined(__OpenBSD__)
+#    define LZO_OS_POSIX_OPENBSD    1
+#    define LZO_INFO_OS_POSIX       "openbsd"
+#  elif defined(__osf__)
+#    define LZO_OS_POSIX_OSF        1
+#    define LZO_INFO_OS_POSIX       "osf"
+#  elif defined(__solaris__) || defined(__sun)
+#    if defined(__SVR4) || defined(__svr4__)
+#      define LZO_OS_POSIX_SOLARIS  1
+#      define LZO_INFO_OS_POSIX     "solaris"
+#    else
+#      define LZO_OS_POSIX_SUNOS    1
+#      define LZO_INFO_OS_POSIX     "sunos"
+#    endif
+#  elif defined(__ultrix__) || defined(__ultrix)
+#    define LZO_OS_POSIX_ULTRIX     1
+#    define LZO_INFO_OS_POSIX       "ultrix"
+#  elif defined(_UNICOS)
+#    define LZO_OS_POSIX_UNICOS     1
+#    define LZO_INFO_OS_POSIX       "unicos"
+#  else
+#    define LZO_OS_POSIX_UNKNOWN    1
+#    define LZO_INFO_OS_POSIX       "unknown"
+#  endif
+#endif
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#  if (UINT_MAX != LZO_0xffffL)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
+#  if (UINT_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
+#  define LZO_CC_CILLY          1
+#  define LZO_INFO_CC           "Cilly"
+#  if defined(__CILLY__)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__CILLY__)
+#  else
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)
+#  define LZO_CC_SDCC           1
+#  define LZO_INFO_CC           "sdcc"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(SDCC)
+#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
+#  define LZO_CC_PATHSCALE      (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+#  define LZO_INFO_CC           "Pathscale C"
+#  define LZO_INFO_CCVER        __PATHSCALE__
+#elif defined(__INTEL_COMPILER)
+#  define LZO_CC_INTELC         1
+#  define LZO_INFO_CC           "Intel C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__INTEL_COMPILER)
+#  if defined(_WIN32) || defined(_WIN64)
+#    define LZO_CC_SYNTAX_MSC 1
+#  else
+#    define LZO_CC_SYNTAX_GNUC 1
+#  endif
+#elif defined(__POCC__) && defined(_WIN32)
+#  define LZO_CC_PELLESC        1
+#  define LZO_INFO_CC           "Pelles C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__POCC__)
+#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+#  if defined(__GNUC_PATCHLEVEL__)
+#    define LZO_CC_CLANG_GNUC   (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#  else
+#    define LZO_CC_CLANG_GNUC   (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+#  endif
+#  if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+#    define LZO_CC_CLANG_CLANG  (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
+#  else
+#    define LZO_CC_CLANG_CLANG  0x010000L
+#  endif
+#  define LZO_CC_CLANG          LZO_CC_CLANG_GNUC
+#  define LZO_INFO_CC           "clang"
+#  define LZO_INFO_CCVER        __VERSION__
+#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+#  if defined(__GNUC_PATCHLEVEL__)
+#    define LZO_CC_LLVM_GNUC    (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#  else
+#    define LZO_CC_LLVM_GNUC    (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+#  endif
+#  define LZO_CC_LLVM           LZO_CC_LLVM_GNUC
+#  define LZO_INFO_CC           "llvm-gcc"
+#  define LZO_INFO_CCVER        __VERSION__
+#elif defined(__GNUC__) && defined(__VERSION__)
+#  if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+#    define LZO_CC_GNUC         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#  elif defined(__GNUC_MINOR__)
+#    define LZO_CC_GNUC         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+#  else
+#    define LZO_CC_GNUC         (__GNUC__ * 0x10000L)
+#  endif
+#  define LZO_INFO_CC           "gcc"
+#  define LZO_INFO_CCVER        __VERSION__
+#elif defined(__ACK__) && defined(_ACK)
+#  define LZO_CC_ACK            1
+#  define LZO_INFO_CC           "Amsterdam Compiler Kit C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__AZTEC_C__)
+#  define LZO_CC_AZTECC         1
+#  define LZO_INFO_CC           "Aztec C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__CODEGEARC__)
+#  define LZO_CC_CODEGEARC      1
+#  define LZO_INFO_CC           "CodeGear C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__CODEGEARC__)
+#elif defined(__BORLANDC__)
+#  define LZO_CC_BORLANDC       1
+#  define LZO_INFO_CC           "Borland C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__BORLANDC__)
+#elif defined(_CRAYC) && defined(_RELEASE)
+#  define LZO_CC_CRAYC          1
+#  define LZO_INFO_CC           "Cray C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(_RELEASE)
+#elif defined(__DMC__) && defined(__SC__)
+#  define LZO_CC_DMC            1
+#  define LZO_INFO_CC           "Digital Mars C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__DMC__)
+#elif defined(__DECC)
+#  define LZO_CC_DECC           1
+#  define LZO_INFO_CC           "DEC C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__DECC)
+#elif defined(__HIGHC__)
+#  define LZO_CC_HIGHC          1
+#  define LZO_INFO_CC           "MetaWare High C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__IAR_SYSTEMS_ICC__)
+#  define LZO_CC_IARC           1
+#  define LZO_INFO_CC           "IAR C"
+#  if defined(__VER__)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__VER__)
+#  else
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(__IBMC__)
+#  define LZO_CC_IBMC           1
+#  define LZO_INFO_CC           "IBM C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__KEIL__) && defined(__C166__)
+#  define LZO_CC_KEILC          1
+#  define LZO_INFO_CC           "Keil C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__C166__)
+#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)
+#  define LZO_CC_LCCWIN32       1
+#  define LZO_INFO_CC           "lcc-win32"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__LCC__)
+#  define LZO_CC_LCC            1
+#  define LZO_INFO_CC           "lcc"
+#  if defined(__LCC_VERSION__)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__LCC_VERSION__)
+#  else
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(_MSC_VER)
+#  define LZO_CC_MSC            1
+#  define LZO_INFO_CC           "Microsoft C"
+#  if defined(_MSC_FULL_VER)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
+#  else
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(_MSC_VER)
+#  endif
+#elif defined(__MWERKS__)
+#  define LZO_CC_MWERKS         1
+#  define LZO_INFO_CC           "Metrowerks C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__MWERKS__)
+#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
+#  define LZO_CC_NDPC           1
+#  define LZO_INFO_CC           "Microway NDP C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__PACIFIC__)
+#  define LZO_CC_PACIFICC       1
+#  define LZO_INFO_CC           "Pacific C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
+#  define LZO_CC_PGI            1
+#  define LZO_INFO_CC           "Portland Group PGI C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__PUREC__) && defined(__TOS__)
+#  define LZO_CC_PUREC          1
+#  define LZO_INFO_CC           "Pure C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__PUREC__)
+#elif defined(__SC__) && defined(__ZTC__)
+#  define LZO_CC_SYMANTECC      1
+#  define LZO_INFO_CC           "Symantec C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__SC__)
+#elif defined(__SUNPRO_C)
+#  define LZO_INFO_CC           "SunPro C"
+#  if ((__SUNPRO_C)+0 > 0)
+#    define LZO_CC_SUNPROC      __SUNPRO_C
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__SUNPRO_C)
+#  else
+#    define LZO_CC_SUNPROC      1
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(__SUNPRO_CC)
+#  define LZO_INFO_CC           "SunPro C"
+#  if ((__SUNPRO_CC)+0 > 0)
+#    define LZO_CC_SUNPROC      __SUNPRO_CC
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__SUNPRO_CC)
+#  else
+#    define LZO_CC_SUNPROC      1
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(__TINYC__)
+#  define LZO_CC_TINYC          1
+#  define LZO_INFO_CC           "Tiny C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__TINYC__)
+#elif defined(__TSC__)
+#  define LZO_CC_TOPSPEEDC      1
+#  define LZO_INFO_CC           "TopSpeed C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__TSC__)
+#elif defined(__WATCOMC__)
+#  define LZO_CC_WATCOMC        1
+#  define LZO_INFO_CC           "Watcom C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__WATCOMC__)
+#elif defined(__TURBOC__)
+#  define LZO_CC_TURBOC         1
+#  define LZO_INFO_CC           "Turbo C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__TURBOC__)
+#elif defined(__ZTC__)
+#  define LZO_CC_ZORTECHC       1
+#  define LZO_INFO_CC           "Zortech C"
+#  if (__ZTC__ == 0x310)
+#    define LZO_INFO_CCVER      "0x310"
+#  else
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__ZTC__)
+#  endif
+#else
+#  define LZO_CC_UNKNOWN        1
+#  define LZO_INFO_CC           "unknown"
+#  define LZO_INFO_CCVER        "unknown"
+#endif
+#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
+#  error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY)
+#  if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY)
+#    if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
+#      define LZO_ARCH_CRAY_MPP     1
+#    elif defined(_CRAY1)
+#      define LZO_ARCH_CRAY_PVP     1
+#    endif
+#  endif
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE)
+#if (LZO_ARCH_GENERIC)
+#  define LZO_INFO_ARCH             "generic"
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#  define LZO_ARCH_I086             1
+#  define LZO_ARCH_IA16             1
+#  define LZO_INFO_ARCH             "i086"
+#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+#  define LZO_ARCH_ALPHA            1
+#  define LZO_INFO_ARCH             "alpha"
+#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E))
+#  define LZO_ARCH_ALPHA            1
+#  define LZO_INFO_ARCH             "alpha"
+#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+#  define LZO_ARCH_AMD64            1
+#  define LZO_INFO_ARCH             "amd64"
+#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
+#  define LZO_ARCH_ARM              1
+#  define LZO_ARCH_ARM_THUMB        1
+#  define LZO_INFO_ARCH             "arm_thumb"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+#  define LZO_ARCH_ARM              1
+#  if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+#    define LZO_ARCH_ARM_THUMB      1
+#    define LZO_INFO_ARCH           "arm_thumb"
+#  elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+#    define LZO_INFO_ARCH           "arm"
+#  else
+#    define LZO_INFO_ARCH           "arm"
+#  endif
+#elif defined(__arm__) || defined(_M_ARM)
+#  define LZO_ARCH_ARM              1
+#  define LZO_INFO_ARCH             "arm"
+#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
+#  define LZO_ARCH_AVR              1
+#  define LZO_INFO_ARCH             "avr"
+#elif defined(__avr32__) || defined(__AVR32__)
+#  define LZO_ARCH_AVR32            1
+#  define LZO_INFO_ARCH             "avr32"
+#elif defined(__bfin__)
+#  define LZO_ARCH_BLACKFIN         1
+#  define LZO_INFO_ARCH             "blackfin"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__)
+#  define LZO_ARCH_C166             1
+#  define LZO_INFO_ARCH             "c166"
+#elif defined(__cris__)
+#  define LZO_ARCH_CRIS             1
+#  define LZO_INFO_ARCH             "cris"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__)
+#  define LZO_ARCH_EZ80             1
+#  define LZO_INFO_ARCH             "ez80"
+#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+#  define LZO_ARCH_H8300            1
+#  define LZO_INFO_ARCH             "h8300"
+#elif defined(__hppa__) || defined(__hppa)
+#  define LZO_ARCH_HPPA             1
+#  define LZO_INFO_ARCH             "hppa"
+#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
+#  define LZO_ARCH_I386             1
+#  define LZO_ARCH_IA32             1
+#  define LZO_INFO_ARCH             "i386"
+#elif (LZO_CC_ZORTECHC && defined(__I86__))
+#  define LZO_ARCH_I386             1
+#  define LZO_ARCH_IA32             1
+#  define LZO_INFO_ARCH             "i386"
+#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386)
+#  define LZO_ARCH_I386             1
+#  define LZO_ARCH_IA32             1
+#  define LZO_INFO_ARCH             "i386"
+#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
+#  define LZO_ARCH_IA64             1
+#  define LZO_INFO_ARCH             "ia64"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__)
+#  define LZO_ARCH_M16C             1
+#  define LZO_INFO_ARCH             "m16c"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__)
+#  define LZO_ARCH_M16C             1
+#  define LZO_INFO_ARCH             "m16c"
+#elif defined(__m32r__)
+#  define LZO_ARCH_M32R             1
+#  define LZO_INFO_ARCH             "m32r"
+#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K)
+#  define LZO_ARCH_M68K             1
+#  define LZO_INFO_ARCH             "m68k"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__)
+#  define LZO_ARCH_MCS251           1
+#  define LZO_INFO_ARCH             "mcs251"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__)
+#  define LZO_ARCH_MCS51            1
+#  define LZO_INFO_ARCH             "mcs51"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__)
+#  define LZO_ARCH_MCS51            1
+#  define LZO_INFO_ARCH             "mcs51"
+#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
+#  define LZO_ARCH_MIPS             1
+#  define LZO_INFO_ARCH             "mips"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__)
+#  define LZO_ARCH_MSP430           1
+#  define LZO_INFO_ARCH             "msp430"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__)
+#  define LZO_ARCH_MSP430           1
+#  define LZO_INFO_ARCH             "msp430"
+#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+#  define LZO_ARCH_POWERPC          1
+#  define LZO_INFO_ARCH             "powerpc"
+#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+#  define LZO_ARCH_S390             1
+#  define LZO_INFO_ARCH             "s390"
+#elif defined(__sh__) || defined(_M_SH)
+#  define LZO_ARCH_SH               1
+#  define LZO_INFO_ARCH             "sh"
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
+#  define LZO_ARCH_SPARC            1
+#  define LZO_INFO_ARCH             "sparc"
+#elif defined(__SPU__)
+#  define LZO_ARCH_SPU              1
+#  define LZO_INFO_ARCH             "spu"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__z80)
+#  define LZO_ARCH_Z80              1
+#  define LZO_INFO_ARCH             "z80"
+#elif (LZO_ARCH_CRAY_PVP)
+#  if defined(_CRAYSV1)
+#    define LZO_ARCH_CRAY_SV1       1
+#    define LZO_INFO_ARCH           "cray_sv1"
+#  elif (_ADDR64)
+#    define LZO_ARCH_CRAY_T90       1
+#    define LZO_INFO_ARCH           "cray_t90"
+#  elif (_ADDR32)
+#    define LZO_ARCH_CRAY_YMP       1
+#    define LZO_INFO_ARCH           "cray_ymp"
+#  else
+#    define LZO_ARCH_CRAY_XMP       1
+#    define LZO_INFO_ARCH           "cray_xmp"
+#  endif
+#else
+#  define LZO_ARCH_UNKNOWN          1
+#  define LZO_INFO_ARCH             "unknown"
+#endif
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
+#  error "FIXME - missing define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
+#  error "FIXME - missing WIN32 define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
+#  error "FIXME - missing WIN64 define for CPU architecture"
+#endif
+#if (LZO_OS_OS216 || LZO_OS_WIN16)
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#endif
+#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
+#  error "this should not happen"
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
+#  error "this should not happen"
+#endif
+#if (LZO_ARCH_I086)
+#  if (UINT_MAX != LZO_0xffffL)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if (LZO_ARCH_I386)
+#  if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
+#    error "this should not happen"
+#  endif
+#  if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if !defined(__LZO_MM_OVERRIDE)
+#if (LZO_ARCH_I086)
+#if (UINT_MAX != LZO_0xffffL)
+#  error "this should not happen"
+#endif
+#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
+#  define LZO_MM_TINY           1
+#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)
+#  define LZO_MM_HUGE           1
+#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)
+#  define LZO_MM_SMALL          1
+#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)
+#  define LZO_MM_MEDIUM         1
+#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)
+#  define LZO_MM_COMPACT        1
+#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)
+#  define LZO_MM_LARGE          1
+#elif (LZO_CC_AZTECC)
+#  if defined(_LARGE_CODE) && defined(_LARGE_DATA)
+#    define LZO_MM_LARGE        1
+#  elif defined(_LARGE_CODE)
+#    define LZO_MM_MEDIUM       1
+#  elif defined(_LARGE_DATA)
+#    define LZO_MM_COMPACT      1
+#  else
+#    define LZO_MM_SMALL        1
+#  endif
+#elif (LZO_CC_ZORTECHC && defined(__VCM__))
+#  define LZO_MM_LARGE          1
+#else
+#  error "unknown memory model"
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#define LZO_HAVE_MM_HUGE_PTR        1
+#define LZO_HAVE_MM_HUGE_ARRAY      1
+#if (LZO_MM_TINY)
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC)
+#  undef LZO_HAVE_MM_HUGE_PTR
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_MSC && defined(_QC))
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#  if (_MSC_VER < 600)
+#    undef LZO_HAVE_MM_HUGE_PTR
+#  endif
+#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
+#  if (LZO_OS_DOS16)
+#    error "this should not happen"
+#  elif (LZO_CC_ZORTECHC)
+#  else
+#    error "this should not happen"
+#  endif
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC)
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295))
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16)
+#  define LZO_MM_AHSHIFT      12
+#elif (LZO_CC_WATCOMC)
+   extern unsigned char _HShift;
+#  define LZO_MM_AHSHIFT      ((unsigned) _HShift)
+#else
+#  error "FIXME - implement LZO_MM_AHSHIFT"
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+#elif (LZO_ARCH_C166)
+#if !defined(__MODEL__)
+#  error "FIXME - C166 __MODEL__"
+#elif ((__MODEL__) == 0)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 1)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 2)
+#  define LZO_MM_LARGE          1
+#elif ((__MODEL__) == 3)
+#  define LZO_MM_TINY           1
+#elif ((__MODEL__) == 4)
+#  define LZO_MM_XTINY          1
+#elif ((__MODEL__) == 5)
+#  define LZO_MM_XSMALL         1
+#else
+#  error "FIXME - C166 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS251)
+#if !defined(__MODEL__)
+#  error "FIXME - MCS251 __MODEL__"
+#elif ((__MODEL__) == 0)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 2)
+#  define LZO_MM_LARGE          1
+#elif ((__MODEL__) == 3)
+#  define LZO_MM_TINY           1
+#elif ((__MODEL__) == 4)
+#  define LZO_MM_XTINY          1
+#elif ((__MODEL__) == 5)
+#  define LZO_MM_XSMALL         1
+#else
+#  error "FIXME - MCS251 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS51)
+#if !defined(__MODEL__)
+#  error "FIXME - MCS51 __MODEL__"
+#elif ((__MODEL__) == 1)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 2)
+#  define LZO_MM_LARGE          1
+#elif ((__MODEL__) == 3)
+#  define LZO_MM_TINY           1
+#elif ((__MODEL__) == 4)
+#  define LZO_MM_XTINY          1
+#elif ((__MODEL__) == 5)
+#  define LZO_MM_XSMALL         1
+#else
+#  error "FIXME - MCS51 __MODEL__"
+#endif
+#elif (LZO_ARCH_CRAY_PVP)
+#  define LZO_MM_PVP            1
+#else
+#  define LZO_MM_FLAT           1
+#endif
+#if (LZO_MM_COMPACT)
+#  define LZO_INFO_MM           "compact"
+#elif (LZO_MM_FLAT)
+#  define LZO_INFO_MM           "flat"
+#elif (LZO_MM_HUGE)
+#  define LZO_INFO_MM           "huge"
+#elif (LZO_MM_LARGE)
+#  define LZO_INFO_MM           "large"
+#elif (LZO_MM_MEDIUM)
+#  define LZO_INFO_MM           "medium"
+#elif (LZO_MM_PVP)
+#  define LZO_INFO_MM           "pvp"
+#elif (LZO_MM_SMALL)
+#  define LZO_INFO_MM           "small"
+#elif (LZO_MM_TINY)
+#  define LZO_INFO_MM           "tiny"
+#else
+#  error "unknown memory model"
+#endif
+#endif
+#if defined(SIZEOF_SHORT)
+#  define LZO_SIZEOF_SHORT          (SIZEOF_SHORT)
+#endif
+#if defined(SIZEOF_INT)
+#  define LZO_SIZEOF_INT            (SIZEOF_INT)
+#endif
+#if defined(SIZEOF_LONG)
+#  define LZO_SIZEOF_LONG           (SIZEOF_LONG)
+#endif
+#if defined(SIZEOF_LONG_LONG)
+#  define LZO_SIZEOF_LONG_LONG      (SIZEOF_LONG_LONG)
+#endif
+#if defined(SIZEOF___INT16)
+#  define LZO_SIZEOF___INT16        (SIZEOF___INT16)
+#endif
+#if defined(SIZEOF___INT32)
+#  define LZO_SIZEOF___INT32        (SIZEOF___INT32)
+#endif
+#if defined(SIZEOF___INT64)
+#  define LZO_SIZEOF___INT64        (SIZEOF___INT64)
+#endif
+#if defined(SIZEOF_VOID_P)
+#  define LZO_SIZEOF_VOID_P         (SIZEOF_VOID_P)
+#endif
+#if defined(SIZEOF_SIZE_T)
+#  define LZO_SIZEOF_SIZE_T         (SIZEOF_SIZE_T)
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+#  define LZO_SIZEOF_PTRDIFF_T      (SIZEOF_PTRDIFF_T)
+#endif
+#define __LZO_LSR(x,b)    (((x)+0ul) >> (b))
+#if !defined(LZO_SIZEOF_SHORT)
+#  if (LZO_ARCH_CRAY_PVP)
+#    define LZO_SIZEOF_SHORT        8
+#  elif (USHRT_MAX == LZO_0xffffL)
+#    define LZO_SIZEOF_SHORT        2
+#  elif (__LZO_LSR(USHRT_MAX,7) == 1)
+#    define LZO_SIZEOF_SHORT        1
+#  elif (__LZO_LSR(USHRT_MAX,15) == 1)
+#    define LZO_SIZEOF_SHORT        2
+#  elif (__LZO_LSR(USHRT_MAX,31) == 1)
+#    define LZO_SIZEOF_SHORT        4
+#  elif (__LZO_LSR(USHRT_MAX,63) == 1)
+#    define LZO_SIZEOF_SHORT        8
+#  elif (__LZO_LSR(USHRT_MAX,127) == 1)
+#    define LZO_SIZEOF_SHORT        16
+#  else
+#    error "LZO_SIZEOF_SHORT"
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_INT)
+#  if (LZO_ARCH_CRAY_PVP)
+#    define LZO_SIZEOF_INT          8
+#  elif (UINT_MAX == LZO_0xffffL)
+#    define LZO_SIZEOF_INT          2
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_SIZEOF_INT          4
+#  elif (__LZO_LSR(UINT_MAX,7) == 1)
+#    define LZO_SIZEOF_INT          1
+#  elif (__LZO_LSR(UINT_MAX,15) == 1)
+#    define LZO_SIZEOF_INT          2
+#  elif (__LZO_LSR(UINT_MAX,31) == 1)
+#    define LZO_SIZEOF_INT          4
+#  elif (__LZO_LSR(UINT_MAX,63) == 1)
+#    define LZO_SIZEOF_INT          8
+#  elif (__LZO_LSR(UINT_MAX,127) == 1)
+#    define LZO_SIZEOF_INT          16
+#  else
+#    error "LZO_SIZEOF_INT"
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_LONG)
+#  if (ULONG_MAX == LZO_0xffffffffL)
+#    define LZO_SIZEOF_LONG         4
+#  elif (__LZO_LSR(ULONG_MAX,7) == 1)
+#    define LZO_SIZEOF_LONG         1
+#  elif (__LZO_LSR(ULONG_MAX,15) == 1)
+#    define LZO_SIZEOF_LONG         2
+#  elif (__LZO_LSR(ULONG_MAX,31) == 1)
+#    define LZO_SIZEOF_LONG         4
+#  elif (__LZO_LSR(ULONG_MAX,63) == 1)
+#    define LZO_SIZEOF_LONG         8
+#  elif (__LZO_LSR(ULONG_MAX,127) == 1)
+#    define LZO_SIZEOF_LONG         16
+#  else
+#    error "LZO_SIZEOF_LONG"
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+#  if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
+#    if (LZO_CC_GNUC >= 0x030300ul)
+#      if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+#        define LZO_SIZEOF_LONG_LONG      LZO_SIZEOF_LONG
+#      elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1)
+#        define LZO_SIZEOF_LONG_LONG      4
+#      endif
+#    endif
+#  endif
+#endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+#if (LZO_ARCH_I086 && LZO_CC_DMC)
+#elif (LZO_CC_CILLY) && defined(__GNUC__)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_OS_WIN64 || defined(_WIN64))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_ARCH_I386 && (LZO_CC_DMC))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700)))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__)))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC))
+#  define LZO_SIZEOF___INT64        8
+#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
+#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#  define LZO_SIZEOF_LONG_LONG      8
+#endif
+#endif
+#endif
+#if defined(__cplusplus) && (LZO_CC_GNUC)
+#  if (LZO_CC_GNUC < 0x020800ul)
+#    undef LZO_SIZEOF_LONG_LONG
+#  endif
+#endif
+#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+#  undef LZO_SIZEOF_LONG_LONG
+#endif
+#if !defined(LZO_SIZEOF_VOID_P)
+#if (LZO_ARCH_I086)
+#  define __LZO_WORDSIZE            2
+#  if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
+#    define LZO_SIZEOF_VOID_P       2
+#  elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
+#    define LZO_SIZEOF_VOID_P       4
+#  else
+#    error "LZO_MM"
+#  endif
+#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
+#  define __LZO_WORDSIZE            1
+#  define LZO_SIZEOF_VOID_P         2
+#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
+#  define LZO_SIZEOF_VOID_P         2
+#elif (LZO_ARCH_H8300)
+#  if defined(__NORMAL_MODE__)
+#    define __LZO_WORDSIZE          4
+#    define LZO_SIZEOF_VOID_P       2
+#  elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+#    define __LZO_WORDSIZE          4
+#    define LZO_SIZEOF_VOID_P       4
+#  else
+#    define __LZO_WORDSIZE          2
+#    define LZO_SIZEOF_VOID_P       2
+#  endif
+#  if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
+#    define LZO_SIZEOF_SIZE_T       LZO_SIZEOF_INT
+#    define LZO_SIZEOF_PTRDIFF_T    LZO_SIZEOF_INT
+#  endif
+#elif (LZO_ARCH_M16C)
+#  define __LZO_WORDSIZE            2
+#  if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
+#    define LZO_SIZEOF_VOID_P       4
+#  else
+#    define LZO_SIZEOF_VOID_P       2
+#  endif
+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+#  define __LZO_WORDSIZE            8
+#  define LZO_SIZEOF_VOID_P         4
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+#  define __LZO_WORDSIZE            8
+#  define LZO_SIZEOF_VOID_P         8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+#  define LZO_SIZEOF_VOID_P         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_LONG
+#elif (LZO_OS_OS400 || defined(__OS400__))
+#  define __LZO_WORDSIZE            LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_VOID_P         16
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_LONG
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+#  define LZO_SIZEOF_VOID_P         8
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_LONG
+#elif (LZO_ARCH_SPU)
+# if 0
+#  define __LZO_WORDSIZE            16
+# endif
+#  define LZO_SIZEOF_VOID_P         4
+#else
+#  define LZO_SIZEOF_VOID_P         LZO_SIZEOF_LONG
+#endif
+#endif
+#if !defined(LZO_WORDSIZE)
+#  if defined(__LZO_WORDSIZE)
+#    define LZO_WORDSIZE            __LZO_WORDSIZE
+#  else
+#    define LZO_WORDSIZE            LZO_SIZEOF_VOID_P
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_SIZE_T)
+#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
+#  define LZO_SIZEOF_SIZE_T         2
+#else
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_VOID_P
+#endif
+#endif
+#if !defined(LZO_SIZEOF_PTRDIFF_T)
+#if (LZO_ARCH_I086)
+#  if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE)
+#    define LZO_SIZEOF_PTRDIFF_T    LZO_SIZEOF_VOID_P
+#  elif (LZO_MM_COMPACT || LZO_MM_LARGE)
+#    if (LZO_CC_BORLANDC || LZO_CC_TURBOC)
+#      define LZO_SIZEOF_PTRDIFF_T  4
+#    else
+#      define LZO_SIZEOF_PTRDIFF_T  2
+#    endif
+#  else
+#    error "LZO_MM"
+#  endif
+#else
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_SIZE_T
+#endif
+#endif
+#if (LZO_ABI_NEUTRAL_ENDIAN)
+#  undef LZO_ABI_BIG_ENDIAN
+#  undef LZO_ABI_LITTLE_ENDIAN
+#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
+#  if (__LITTLE_ENDIAN__ == 1)
+#    define LZO_ABI_LITTLE_ENDIAN   1
+#  else
+#    define LZO_ABI_BIG_ENDIAN      1
+#  endif
+#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#endif
+#endif
+#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
+#  error "this should not happen"
+#endif
+#if (LZO_ABI_BIG_ENDIAN)
+#  define LZO_INFO_ABI_ENDIAN       "be"
+#elif (LZO_ABI_LITTLE_ENDIAN)
+#  define LZO_INFO_ABI_ENDIAN       "le"
+#elif (LZO_ABI_NEUTRAL_ENDIAN)
+#  define LZO_INFO_ABI_ENDIAN       "neutral"
+#endif
+#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+#  define LZO_ABI_I8LP16         1
+#  define LZO_INFO_ABI_PM       "i8lp16"
+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+#  define LZO_ABI_ILP16         1
+#  define LZO_INFO_ABI_PM       "ilp16"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
+#  define LZO_ABI_ILP32         1
+#  define LZO_INFO_ABI_PM       "ilp32"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8)
+#  define LZO_ABI_LLP64         1
+#  define LZO_INFO_ABI_PM       "llp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+#  define LZO_ABI_LP64          1
+#  define LZO_INFO_ABI_PM       "lp64"
+#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+#  define LZO_ABI_ILP64         1
+#  define LZO_INFO_ABI_PM       "ilp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4)
+#  define LZO_ABI_IP32L64       1
+#  define LZO_INFO_ABI_PM       "ip32l64"
+#endif
+#if !defined(__LZO_LIBC_OVERRIDE)
+#if (LZO_LIBC_NAKED)
+#  define LZO_INFO_LIBC         "naked"
+#elif (LZO_LIBC_FREESTANDING)
+#  define LZO_INFO_LIBC         "freestanding"
+#elif (LZO_LIBC_MOSTLY_FREESTANDING)
+#  define LZO_INFO_LIBC         "mfreestanding"
+#elif (LZO_LIBC_ISOC90)
+#  define LZO_INFO_LIBC         "isoc90"
+#elif (LZO_LIBC_ISOC99)
+#  define LZO_INFO_LIBC         "isoc99"
+#elif defined(__dietlibc__)
+#  define LZO_LIBC_DIETLIBC     1
+#  define LZO_INFO_LIBC         "dietlibc"
+#elif defined(_NEWLIB_VERSION)
+#  define LZO_LIBC_NEWLIB       1
+#  define LZO_INFO_LIBC         "newlib"
+#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
+#  if defined(__UCLIBC_SUBLEVEL__)
+#    define LZO_LIBC_UCLIBC     (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+#  else
+#    define LZO_LIBC_UCLIBC     0x00090bL
+#  endif
+#  define LZO_INFO_LIBC         "uclibc"
+#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
+#  define LZO_LIBC_GLIBC        (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+#  define LZO_INFO_LIBC         "glibc"
+#elif (LZO_CC_MWERKS) && defined(__MSL__)
+#  define LZO_LIBC_MSL          __MSL__
+#  define LZO_INFO_LIBC         "msl"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+#  define LZO_LIBC_ISOC90       1
+#  define LZO_INFO_LIBC         "isoc90"
+#else
+#  define LZO_LIBC_DEFAULT      1
+#  define LZO_INFO_LIBC         "default"
+#endif
+#endif
+#if !defined(__lzo_gnuc_extension__)
+#if (LZO_CC_GNUC >= 0x020800ul)
+#  define __lzo_gnuc_extension__    __extension__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_gnuc_extension__    __extension__
+#else
+#  define __lzo_gnuc_extension__    /*empty*/
+#endif
+#endif
+#if !defined(__lzo_ua_volatile)
+#  define __lzo_ua_volatile     volatile
+#endif
+#if !defined(__lzo_alignof)
+#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#  define __lzo_alignof(e)      __alignof__(e)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
+#  define __lzo_alignof(e)      __alignof__(e)
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+#  define __lzo_alignof(e)      __alignof(e)
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_alignof(e)      __alignof__(e)
+#endif
+#endif
+#if defined(__lzo_alignof)
+#  define __lzo_HAVE_alignof 1
+#endif
+#if !defined(__lzo_constructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+#  define __lzo_constructor     __attribute__((__constructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+#  define __lzo_constructor     __attribute__((__constructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_constructor     __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__lzo_constructor)
+#  define __lzo_HAVE_constructor 1
+#endif
+#if !defined(__lzo_destructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+#  define __lzo_destructor      __attribute__((__destructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+#  define __lzo_destructor      __attribute__((__destructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_destructor      __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__lzo_destructor)
+#  define __lzo_HAVE_destructor 1
+#endif
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
+#  error "this should not happen"
+#endif
+#if !defined(__lzo_inline)
+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+#  define __lzo_inline          inline
+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+#  define __lzo_inline          __inline
+#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#  define __lzo_inline          __inline__
+#elif (LZO_CC_DMC)
+#  define __lzo_inline          __inline
+#elif (LZO_CC_INTELC)
+#  define __lzo_inline          __inline
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
+#  define __lzo_inline          __inline
+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
+#  define __lzo_inline          __inline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_inline          __inline__
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#  define __lzo_inline          inline
+#endif
+#endif
+#if defined(__lzo_inline)
+#  define __lzo_HAVE_inline 1
+#else
+#  define __lzo_inline          /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+#if (LZO_CC_GNUC >= 0x030200ul)
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+#  define __lzo_forceinline     __forceinline
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+#  define __lzo_forceinline     __forceinline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#endif
+#endif
+#if defined(__lzo_forceinline)
+#  define __lzo_HAVE_forceinline 1
+#else
+#  define __lzo_forceinline     /*empty*/
+#endif
+#if !defined(__lzo_noinline)
+#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
+#  define __lzo_noinline        __attribute__((__noinline__,__used__))
+#elif (LZO_CC_GNUC >= 0x030200ul)
+#  define __lzo_noinline        __attribute__((__noinline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC)
+#  define __lzo_noinline        __declspec(noinline)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_noinline        __attribute__((__noinline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_noinline        __attribute__((__noinline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+#  define __lzo_noinline        __declspec(noinline)
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
+#  if defined(__cplusplus)
+#  else
+#    define __lzo_noinline      __declspec(noinline)
+#  endif
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_noinline        __attribute__((__noinline__))
+#endif
+#endif
+#if defined(__lzo_noinline)
+#  define __lzo_HAVE_noinline 1
+#else
+#  define __lzo_noinline        /*empty*/
+#endif
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
+#  error "this should not happen"
+#endif
+#if !defined(__lzo_noreturn)
+#if (LZO_CC_GNUC >= 0x020700ul)
+#  define __lzo_noreturn        __attribute__((__noreturn__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+#  define __lzo_noreturn        __declspec(noreturn)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_noreturn        __attribute__((__noreturn__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_noreturn        __attribute__((__noreturn__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+#  define __lzo_noreturn        __declspec(noreturn)
+#endif
+#endif
+#if defined(__lzo_noreturn)
+#  define __lzo_HAVE_noreturn 1
+#else
+#  define __lzo_noreturn        /*empty*/
+#endif
+#if !defined(__lzo_nothrow)
+#if (LZO_CC_GNUC >= 0x030300ul)
+#  define __lzo_nothrow         __attribute__((__nothrow__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus)
+#  define __lzo_nothrow         __declspec(nothrow)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_nothrow         __attribute__((__nothrow__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_nothrow         __attribute__((__nothrow__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+#  define __lzo_nothrow         __declspec(nothrow)
+#endif
+#endif
+#if defined(__lzo_nothrow)
+#  define __lzo_HAVE_nothrow 1
+#else
+#  define __lzo_nothrow         /*empty*/
+#endif
+#if !defined(__lzo_restrict)
+#if (LZO_CC_GNUC >= 0x030400ul)
+#  define __lzo_restrict        __restrict__
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_restrict        __restrict__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM)
+#  define __lzo_restrict        __restrict__
+#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
+#  define __lzo_restrict        __restrict
+#endif
+#endif
+#if defined(__lzo_restrict)
+#  define __lzo_HAVE_restrict 1
+#else
+#  define __lzo_restrict        /*empty*/
+#endif
+#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
+#if (LZO_CC_GNUC >= 0x030200ul)
+#  define __lzo_likely(e)       (__builtin_expect(!!(e),1))
+#  define __lzo_unlikely(e)     (__builtin_expect(!!(e),0))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+#  define __lzo_likely(e)       (__builtin_expect(!!(e),1))
+#  define __lzo_unlikely(e)     (__builtin_expect(!!(e),0))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_likely(e)       (__builtin_expect(!!(e),1))
+#  define __lzo_unlikely(e)     (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__lzo_likely)
+#  define __lzo_HAVE_likely 1
+#else
+#  define __lzo_likely(e)       (e)
+#endif
+#if defined(__lzo_unlikely)
+#  define __lzo_HAVE_unlikely 1
+#else
+#  define __lzo_unlikely(e)     (e)
+#endif
+#if !defined(LZO_UNUSED)
+#  if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+#    define LZO_UNUSED(var)         ((void) &var)
+#  elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
+#    define LZO_UNUSED(var)         if (&var) ; else
+#  elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#    define LZO_UNUSED(var)         ((void) var)
+#  elif (LZO_CC_MSC && (_MSC_VER < 900))
+#    define LZO_UNUSED(var)         if (&var) ; else
+#  elif (LZO_CC_KEILC)
+#    define LZO_UNUSED(var)         {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
+#  elif (LZO_CC_PACIFICC)
+#    define LZO_UNUSED(var)         ((void) sizeof(var))
+#  elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+#    define LZO_UNUSED(var)         ((void) var)
+#  else
+#    define LZO_UNUSED(var)         ((void) &var)
+#  endif
+#endif
+#if !defined(LZO_UNUSED_FUNC)
+#  if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+#    define LZO_UNUSED_FUNC(func)   ((void) func)
+#  elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
+#    define LZO_UNUSED_FUNC(func)   if (func) ; else
+#  elif (LZO_CC_CLANG || LZO_CC_LLVM)
+#    define LZO_UNUSED_FUNC(func)   ((void) &func)
+#  elif (LZO_CC_MSC && (_MSC_VER < 900))
+#    define LZO_UNUSED_FUNC(func)   if (func) ; else
+#  elif (LZO_CC_MSC)
+#    define LZO_UNUSED_FUNC(func)   ((void) &func)
+#  elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+#    define LZO_UNUSED_FUNC(func)   {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
+#  else
+#    define LZO_UNUSED_FUNC(func)   ((void) func)
+#  endif
+#endif
+#if !defined(LZO_UNUSED_LABEL)
+#  if (LZO_CC_WATCOMC) && defined(__cplusplus)
+#    define LZO_UNUSED_LABEL(l)     switch(0) case 1:goto l
+#  elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
+#    define LZO_UNUSED_LABEL(l)     if (0) goto l
+#  else
+#    define LZO_UNUSED_LABEL(l)     switch(0) case 1:goto l
+#  endif
+#endif
+#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
+#  if 0
+#    define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var
+#  elif 0 && (LZO_CC_GNUC)
+#    define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var = var
+#  else
+#    define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var = init
+#  endif
+#endif
+#if !defined(LZO_UNCONST_CAST)
+#  if 0 && defined(__cplusplus)
+#    define LZO_UNCONST_CAST(t,e)   (const_cast<t> (e))
+#  elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#    define LZO_UNCONST_CAST(t,e)   ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e))))))
+#  else
+#    define LZO_UNCONST_CAST(t,e)   ((t) ((void *) ((char *) ((const void *) (e)))))
+#  endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
+#  if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1-!(e)];
+#  elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1u-2*!(e)];
+#  elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1-!(e)];
+#  else
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1-2*!(e)];
+#  endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+#  if (LZO_CC_AZTECC)
+#    define LZO_COMPILE_TIME_ASSERT(e)  {typedef int __lzo_cta_t[1-!(e)];}
+#  elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+#    define LZO_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;
+#  elif (LZO_CC_MSC && (_MSC_VER < 900))
+#    define LZO_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;
+#  elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+#    define LZO_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;
+#  else
+#    define LZO_COMPILE_TIME_ASSERT(e)  {typedef int __lzo_cta_t[1-2*!(e)];}
+#  endif
+#endif
+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+#  if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+#  elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+#    define __lzo_cdecl                 __cdecl
+#    define __lzo_cdecl_atexit          /*empty*/
+#    define __lzo_cdecl_main            __cdecl
+#    if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+#      define __lzo_cdecl_qsort         __pascal
+#    elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+#      define __lzo_cdecl_qsort         _stdcall
+#    else
+#      define __lzo_cdecl_qsort         __cdecl
+#    endif
+#  elif (LZO_CC_WATCOMC)
+#    define __lzo_cdecl                 __cdecl
+#  else
+#    define __lzo_cdecl                 __cdecl
+#    define __lzo_cdecl_atexit          __cdecl
+#    define __lzo_cdecl_main            __cdecl
+#    define __lzo_cdecl_qsort           __cdecl
+#  endif
+#  if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
+#  elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+#    define __lzo_cdecl_sighandler      __pascal
+#  elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+#    define __lzo_cdecl_sighandler      _stdcall
+#  elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+#    define __lzo_cdecl_sighandler      __clrcall
+#  elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+#    if defined(_DLL)
+#      define __lzo_cdecl_sighandler    _far _cdecl _loadds
+#    elif defined(_MT)
+#      define __lzo_cdecl_sighandler    _far _cdecl
+#    else
+#      define __lzo_cdecl_sighandler    _cdecl
+#    endif
+#  else
+#    define __lzo_cdecl_sighandler      __cdecl
+#  endif
+#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
+#  define __lzo_cdecl                   __cdecl
+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
+#  define __lzo_cdecl                   cdecl
+#endif
+#if !defined(__lzo_cdecl)
+#  define __lzo_cdecl                   /*empty*/
+#endif
+#if !defined(__lzo_cdecl_atexit)
+#  define __lzo_cdecl_atexit            /*empty*/
+#endif
+#if !defined(__lzo_cdecl_main)
+#  define __lzo_cdecl_main              /*empty*/
+#endif
+#if !defined(__lzo_cdecl_qsort)
+#  define __lzo_cdecl_qsort             /*empty*/
+#endif
+#if !defined(__lzo_cdecl_sighandler)
+#  define __lzo_cdecl_sighandler        /*empty*/
+#endif
+#if !defined(__lzo_cdecl_va)
+#  define __lzo_cdecl_va                __lzo_cdecl
+#endif
+#if !(LZO_CFG_NO_WINDOWS_H)
+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+#  if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+#  elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
+#  elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+#  else
+#    define LZO_HAVE_WINDOWS_H 1
+#  endif
+#endif
+#endif
+#if (LZO_ARCH_ALPHA)
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#  define LZO_OPT_AVOID_SHORT       1
+#  define LZO_OPT_AVOID_USHORT      1
+#elif (LZO_ARCH_AMD64)
+#  define LZO_OPT_AVOID_INT_INDEX   1
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#  define LZO_OPT_UNALIGNED64       1
+#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
+#elif (LZO_ARCH_ARM)
+#  define LZO_OPT_AVOID_SHORT       1
+#  define LZO_OPT_AVOID_USHORT      1
+#elif (LZO_ARCH_CRIS)
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#elif (LZO_ARCH_I386)
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#elif (LZO_ARCH_IA64)
+#  define LZO_OPT_AVOID_INT_INDEX   1
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#  define LZO_OPT_PREFER_POSTINC    1
+#elif (LZO_ARCH_M68K)
+#  define LZO_OPT_PREFER_POSTINC    1
+#  define LZO_OPT_PREFER_PREDEC     1
+#  if defined(__mc68020__) && !defined(__mcoldfire__)
+#    define LZO_OPT_UNALIGNED16     1
+#    define LZO_OPT_UNALIGNED32     1
+#  endif
+#elif (LZO_ARCH_MIPS)
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#elif (LZO_ARCH_POWERPC)
+#  define LZO_OPT_PREFER_PREINC     1
+#  define LZO_OPT_PREFER_PREDEC     1
+#  if (LZO_ABI_BIG_ENDIAN)
+#    define LZO_OPT_UNALIGNED16     1
+#    define LZO_OPT_UNALIGNED32     1
+#  endif
+#elif (LZO_ARCH_S390)
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#  if (LZO_SIZEOF_SIZE_T == 8)
+#    define LZO_OPT_UNALIGNED64     1
+#  endif
+#elif (LZO_ARCH_SH)
+#  define LZO_OPT_PREFER_POSTINC    1
+#  define LZO_OPT_PREFER_PREDEC     1
+#endif
+#ifndef LZO_CFG_NO_INLINE_ASM
+#if (LZO_CC_LLVM)
+#  define LZO_CFG_NO_INLINE_ASM 1
+#endif
+#endif
+#ifndef LZO_CFG_NO_UNALIGNED
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
+#  define LZO_CFG_NO_UNALIGNED 1
+#endif
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+#  undef LZO_OPT_UNALIGNED16
+#  undef LZO_OPT_UNALIGNED32
+#  undef LZO_OPT_UNALIGNED64
+#endif
+#if (LZO_CFG_NO_INLINE_ASM)
+#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#  define LZO_ASM_SYNTAX_MSC 1
+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
+#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+#  define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+#  define LZO_ASM_SYNTAX_GNUC 1
+#endif
+#if (LZO_ASM_SYNTAX_GNUC)
+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
+#  define __LZO_ASM_CLOBBER         "ax"
+#elif (LZO_CC_INTELC)
+#  define __LZO_ASM_CLOBBER         "memory"
+#else
+#  define __LZO_ASM_CLOBBER         "cc", "memory"
+#endif
+#endif
+#if defined(__LZO_INFOSTR_MM)
+#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
+#  define __LZO_INFOSTR_MM          ""
+#elif defined(LZO_INFO_MM)
+#  define __LZO_INFOSTR_MM          "." LZO_INFO_MM
+#else
+#  define __LZO_INFOSTR_MM          ""
+#endif
+#if defined(__LZO_INFOSTR_PM)
+#elif defined(LZO_INFO_ABI_PM)
+#  define __LZO_INFOSTR_PM          "." LZO_INFO_ABI_PM
+#else
+#  define __LZO_INFOSTR_PM          ""
+#endif
+#if defined(__LZO_INFOSTR_ENDIAN)
+#elif defined(LZO_INFO_ABI_ENDIAN)
+#  define __LZO_INFOSTR_ENDIAN      "." LZO_INFO_ABI_ENDIAN
+#else
+#  define __LZO_INFOSTR_ENDIAN      ""
+#endif
+#if defined(__LZO_INFOSTR_OSNAME)
+#elif defined(LZO_INFO_OS_CONSOLE)
+#  define __LZO_INFOSTR_OSNAME      LZO_INFO_OS "." LZO_INFO_OS_CONSOLE
+#elif defined(LZO_INFO_OS_POSIX)
+#  define __LZO_INFOSTR_OSNAME      LZO_INFO_OS "." LZO_INFO_OS_POSIX
+#else
+#  define __LZO_INFOSTR_OSNAME      LZO_INFO_OS
+#endif
+#if defined(__LZO_INFOSTR_LIBC)
+#elif defined(LZO_INFO_LIBC)
+#  define __LZO_INFOSTR_LIBC        "." LZO_INFO_LIBC
+#else
+#  define __LZO_INFOSTR_LIBC        ""
+#endif
+#if defined(__LZO_INFOSTR_CCVER)
+#elif defined(LZO_INFO_CCVER)
+#  define __LZO_INFOSTR_CCVER       " " LZO_INFO_CCVER
+#else
+#  define __LZO_INFOSTR_CCVER       ""
+#endif
+#define LZO_INFO_STRING \
+    LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
+    " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
+
+#endif /* already included */
+
+/* vim:set ts=4 et: */
diff --git a/coregrind/m_debuginfo/minilzo-inl.c b/coregrind/m_debuginfo/minilzo-inl.c
new file mode 100644
index 0000000..153d008
--- /dev/null
+++ b/coregrind/m_debuginfo/minilzo-inl.c
@@ -0,0 +1,4583 @@
+/* minilzo.c -- mini subset of the LZO real-time data compression library
+
+   This file is part of the LZO real-time data compression library.
+
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+   All Rights Reserved.
+
+   The LZO library 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; either version 2 of
+   the License, or (at your option) any later version.
+
+   The LZO library 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 the LZO library; see the file COPYING.
+   If not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+   Markus F.X.J. Oberhumer
+   <markus@oberhumer.com>
+   http://www.oberhumer.com/opensource/lzo/
+ */
+
+/*
+ * NOTE:
+ *   the full LZO package can be found at
+ *   http://www.oberhumer.com/opensource/lzo/
+ */
+
+// BEGIN JRS added
+#define LZO_CFG_FREESTANDING 1
+// END JRS added
+
+#define __LZO_IN_MINILZO 1
+
+#if defined(LZO_CFG_FREESTANDING)
+#  undef MINILZO_HAVE_CONFIG_H
+#  define LZO_LIBC_FREESTANDING 1
+#  define LZO_OS_FREESTANDING 1
+#endif
+
+#ifdef MINILZO_HAVE_CONFIG_H
+#  include <config.h>
+#endif
+#include <limits.h>
+#include <stddef.h>
+#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS)
+
+#ifndef __LZODEFS_H_INCLUDED
+#define __LZODEFS_H_INCLUDED 1
+
+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
+#  define __CYGWIN__ __CYGWIN32__
+#endif
+#if defined(__IBMCPP__) && !defined(__IBMC__)
+#  define __IBMC__ __IBMCPP__
+#endif
+#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
+#  define __INTEL_COMPILER __ICL
+#endif
+#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
+#  define _ALL_SOURCE 1
+#endif
+#if defined(__mips__) && defined(__R5900__)
+#  if !defined(__LONG_MAX__)
+#    define __LONG_MAX__ 9223372036854775807L
+#  endif
+#endif
+#if defined(__INTEL_COMPILER) && defined(__linux__)
+#  pragma warning(disable: 193)
+#endif
+#if defined(__KEIL__) && defined(__C166__)
+#  pragma warning disable = 322
+#elif 0 && defined(__C251__)
+#  pragma warning disable = 322
+#endif
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+#  if (_MSC_VER >= 1300)
+#    pragma warning(disable: 4668)
+#  endif
+#endif
+#if 0 && defined(__WATCOMC__)
+#  if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
+#    pragma warning 203 9
+#  endif
+#endif
+#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
+#  pragma option -h
+#endif
+#if 0
+#define LZO_0xffffL             0xfffful
+#define LZO_0xffffffffL         0xfffffffful
+#else
+#define LZO_0xffffL             65535ul
+#define LZO_0xffffffffL         4294967295ul
+#endif
+#if (LZO_0xffffL == LZO_0xffffffffL)
+#  error "your preprocessor is broken 1"
+#endif
+#if (16ul * 16384ul != 262144ul)
+#  error "your preprocessor is broken 2"
+#endif
+#if 0
+#if (32767 >= 4294967295ul)
+#  error "your preprocessor is broken 3"
+#endif
+#if (65535u >= 4294967295ul)
+#  error "your preprocessor is broken 4"
+#endif
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
+#  if !defined(MSDOS)
+#    define MSDOS 1
+#  endif
+#  if !defined(_MSDOS)
+#    define _MSDOS 1
+#  endif
+#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)
+#  if (__VERSION == 520) && (MB_LEN_MAX == 1)
+#    if !defined(__AZTEC_C__)
+#      define __AZTEC_C__ __VERSION
+#    endif
+#    if !defined(__DOS__)
+#      define __DOS__ 1
+#    endif
+#  endif
+#endif
+#endif
+#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
+#  define ptrdiff_t long
+#  define _PTRDIFF_T_DEFINED 1
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#  undef __LZO_RENAME_A
+#  undef __LZO_RENAME_B
+#  if defined(__AZTEC_C__) && defined(__DOS__)
+#    define __LZO_RENAME_A 1
+#  elif defined(_MSC_VER) && defined(MSDOS)
+#    if (_MSC_VER < 600)
+#      define __LZO_RENAME_A 1
+#    elif (_MSC_VER < 700)
+#      define __LZO_RENAME_B 1
+#    endif
+#  elif defined(__TSC__) && defined(__OS2__)
+#    define __LZO_RENAME_A 1
+#  elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)
+#    define __LZO_RENAME_A 1
+#  elif defined(__PACIFIC__) && defined(DOS)
+#    if !defined(__far)
+#      define __far far
+#    endif
+#    if !defined(__near)
+#      define __near near
+#    endif
+#  endif
+#  if defined(__LZO_RENAME_A)
+#    if !defined(__cdecl)
+#      define __cdecl cdecl
+#    endif
+#    if !defined(__far)
+#      define __far far
+#    endif
+#    if !defined(__huge)
+#      define __huge huge
+#    endif
+#    if !defined(__near)
+#      define __near near
+#    endif
+#    if !defined(__pascal)
+#      define __pascal pascal
+#    endif
+#    if !defined(__huge)
+#      define __huge huge
+#    endif
+#  elif defined(__LZO_RENAME_B)
+#    if !defined(__cdecl)
+#      define __cdecl _cdecl
+#    endif
+#    if !defined(__far)
+#      define __far _far
+#    endif
+#    if !defined(__huge)
+#      define __huge _huge
+#    endif
+#    if !defined(__near)
+#      define __near _near
+#    endif
+#    if !defined(__pascal)
+#      define __pascal _pascal
+#    endif
+#  elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+#    if !defined(__cdecl)
+#      define __cdecl cdecl
+#    endif
+#    if !defined(__pascal)
+#      define __pascal pascal
+#    endif
+#  endif
+#  undef __LZO_RENAME_A
+#  undef __LZO_RENAME_B
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__AZTEC_C__) && defined(__DOS__)
+#  define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#elif defined(_MSC_VER) && defined(MSDOS)
+#  if (_MSC_VER < 600)
+#    define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#  endif
+#  if (_MSC_VER < 700)
+#    define LZO_BROKEN_INTEGRAL_PROMOTION 1
+#    define LZO_BROKEN_SIZEOF 1
+#  endif
+#elif defined(__PACIFIC__) && defined(DOS)
+#  define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#elif defined(__TURBOC__) && defined(__MSDOS__)
+#  if (__TURBOC__ < 0x0150)
+#    define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#    define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#    define LZO_BROKEN_INTEGRAL_PROMOTION 1
+#  endif
+#  if (__TURBOC__ < 0x0200)
+#    define LZO_BROKEN_SIZEOF 1
+#  endif
+#  if (__TURBOC__ < 0x0400) && defined(__cplusplus)
+#    define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#  endif
+#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+#  define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#  define LZO_BROKEN_SIZEOF 1
+#endif
+#endif
+#if defined(__WATCOMC__) && (__WATCOMC__ < 900)
+#  define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#endif
+#if defined(_CRAY) && defined(_CRAY1)
+#  define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1
+#endif
+#define LZO_PP_STRINGIZE(x)             #x
+#define LZO_PP_MACRO_EXPAND(x)          LZO_PP_STRINGIZE(x)
+#define LZO_PP_CONCAT2(a,b)             a ## b
+#define LZO_PP_CONCAT3(a,b,c)           a ## b ## c
+#define LZO_PP_CONCAT4(a,b,c,d)         a ## b ## c ## d
+#define LZO_PP_CONCAT5(a,b,c,d,e)       a ## b ## c ## d ## e
+#define LZO_PP_ECONCAT2(a,b)            LZO_PP_CONCAT2(a,b)
+#define LZO_PP_ECONCAT3(a,b,c)          LZO_PP_CONCAT3(a,b,c)
+#define LZO_PP_ECONCAT4(a,b,c,d)        LZO_PP_CONCAT4(a,b,c,d)
+#define LZO_PP_ECONCAT5(a,b,c,d,e)      LZO_PP_CONCAT5(a,b,c,d,e)
+#if 1
+#define LZO_CPP_STRINGIZE(x)            #x
+#define LZO_CPP_MACRO_EXPAND(x)         LZO_CPP_STRINGIZE(x)
+#define LZO_CPP_CONCAT2(a,b)            a ## b
+#define LZO_CPP_CONCAT3(a,b,c)          a ## b ## c
+#define LZO_CPP_CONCAT4(a,b,c,d)        a ## b ## c ## d
+#define LZO_CPP_CONCAT5(a,b,c,d,e)      a ## b ## c ## d ## e
+#define LZO_CPP_ECONCAT2(a,b)           LZO_CPP_CONCAT2(a,b)
+#define LZO_CPP_ECONCAT3(a,b,c)         LZO_CPP_CONCAT3(a,b,c)
+#define LZO_CPP_ECONCAT4(a,b,c,d)       LZO_CPP_CONCAT4(a,b,c,d)
+#define LZO_CPP_ECONCAT5(a,b,c,d,e)     LZO_CPP_CONCAT5(a,b,c,d,e)
+#endif
+#define __LZO_MASK_GEN(o,b)     (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#if 1 && defined(__cplusplus)
+#  if !defined(__STDC_CONSTANT_MACROS)
+#    define __STDC_CONSTANT_MACROS 1
+#  endif
+#  if !defined(__STDC_LIMIT_MACROS)
+#    define __STDC_LIMIT_MACROS 1
+#  endif
+#endif
+#if defined(__cplusplus)
+#  define LZO_EXTERN_C extern "C"
+#else
+#  define LZO_EXTERN_C extern
+#endif
+#if !defined(__LZO_OS_OVERRIDE)
+#if (LZO_OS_FREESTANDING)
+#  define LZO_INFO_OS           "freestanding"
+#elif (LZO_OS_EMBEDDED)
+#  define LZO_INFO_OS           "embedded"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+#  define LZO_OS_EMBEDDED       1
+#  define LZO_INFO_OS           "embedded"
+#elif defined(__CYGWIN__) && defined(__GNUC__)
+#  define LZO_OS_CYGWIN         1
+#  define LZO_INFO_OS           "cygwin"
+#elif defined(__EMX__) && defined(__GNUC__)
+#  define LZO_OS_EMX            1
+#  define LZO_INFO_OS           "emx"
+#elif defined(__BEOS__)
+#  define LZO_OS_BEOS           1
+#  define LZO_INFO_OS           "beos"
+#elif defined(__Lynx__)
+#  define LZO_OS_LYNXOS         1
+#  define LZO_INFO_OS           "lynxos"
+#elif defined(__OS400__)
+#  define LZO_OS_OS400          1
+#  define LZO_INFO_OS           "os400"
+#elif defined(__QNX__)
+#  define LZO_OS_QNX            1
+#  define LZO_INFO_OS           "qnx"
+#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)
+#  define LZO_OS_DOS32          1
+#  define LZO_INFO_OS           "dos32"
+#elif defined(__BORLANDC__) && defined(__DPMI16__)
+#  define LZO_OS_DOS16          1
+#  define LZO_INFO_OS           "dos16"
+#elif defined(__ZTC__) && defined(DOS386)
+#  define LZO_OS_DOS32          1
+#  define LZO_INFO_OS           "dos32"
+#elif defined(__OS2__) || defined(__OS2V2__)
+#  if (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_OS216        1
+#    define LZO_INFO_OS         "os216"
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_OS_OS2          1
+#    define LZO_INFO_OS         "os2"
+#  else
+#    error "check your limits.h header"
+#  endif
+#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)
+#  define LZO_OS_WIN64          1
+#  define LZO_INFO_OS           "win64"
+#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)
+#  define LZO_OS_WIN32          1
+#  define LZO_INFO_OS           "win32"
+#elif defined(__MWERKS__) && defined(__INTEL__)
+#  define LZO_OS_WIN32          1
+#  define LZO_INFO_OS           "win32"
+#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+#  if (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_WIN16        1
+#    define LZO_INFO_OS         "win16"
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_OS_WIN32        1
+#    define LZO_INFO_OS         "win32"
+#  else
+#    error "check your limits.h header"
+#  endif
+#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))
+#  if (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_DOS16        1
+#    define LZO_INFO_OS         "dos16"
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_OS_DOS32        1
+#    define LZO_INFO_OS         "dos32"
+#  else
+#    error "check your limits.h header"
+#  endif
+#elif defined(__WATCOMC__)
+#  if defined(__NT__) && (UINT_MAX == LZO_0xffffL)
+#    define LZO_OS_DOS16        1
+#    define LZO_INFO_OS         "dos16"
+#  elif defined(__NT__) && (__WATCOMC__ < 1100)
+#    define LZO_OS_WIN32        1
+#    define LZO_INFO_OS         "win32"
+#  elif defined(__linux__) || defined(__LINUX__)
+#    define LZO_OS_POSIX        1
+#    define LZO_INFO_OS         "posix"
+#  else
+#    error "please specify a target using the -bt compiler option"
+#  endif
+#elif defined(__palmos__)
+#  define LZO_OS_PALMOS         1
+#  define LZO_INFO_OS           "palmos"
+#elif defined(__TOS__) || defined(__atarist__)
+#  define LZO_OS_TOS            1
+#  define LZO_INFO_OS           "tos"
+#elif defined(macintosh) && !defined(__ppc__)
+#  define LZO_OS_MACCLASSIC     1
+#  define LZO_INFO_OS           "macclassic"
+#elif defined(__VMS)
+#  define LZO_OS_VMS            1
+#  define LZO_INFO_OS           "vms"
+#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+#  define LZO_OS_CONSOLE        1
+#  define LZO_OS_CONSOLE_PS2    1
+#  define LZO_INFO_OS           "console"
+#  define LZO_INFO_OS_CONSOLE   "ps2"
+#elif (defined(__mips__) && defined(__psp__))
+#  define LZO_OS_CONSOLE        1
+#  define LZO_OS_CONSOLE_PSP    1
+#  define LZO_INFO_OS           "console"
+#  define LZO_INFO_OS_CONSOLE   "psp"
+#else
+#  define LZO_OS_POSIX          1
+#  define LZO_INFO_OS           "posix"
+#endif
+#if (LZO_OS_POSIX)
+#  if defined(_AIX) || defined(__AIX__) || defined(__aix__)
+#    define LZO_OS_POSIX_AIX        1
+#    define LZO_INFO_OS_POSIX       "aix"
+#  elif defined(__FreeBSD__)
+#    define LZO_OS_POSIX_FREEBSD    1
+#    define LZO_INFO_OS_POSIX       "freebsd"
+#  elif defined(__hpux__) || defined(__hpux)
+#    define LZO_OS_POSIX_HPUX       1
+#    define LZO_INFO_OS_POSIX       "hpux"
+#  elif defined(__INTERIX)
+#    define LZO_OS_POSIX_INTERIX    1
+#    define LZO_INFO_OS_POSIX       "interix"
+#  elif defined(__IRIX__) || defined(__irix__)
+#    define LZO_OS_POSIX_IRIX       1
+#    define LZO_INFO_OS_POSIX       "irix"
+#  elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
+#    define LZO_OS_POSIX_LINUX      1
+#    define LZO_INFO_OS_POSIX       "linux"
+#  elif defined(__APPLE__) || defined(__MACOS__)
+#    define LZO_OS_POSIX_MACOSX     1
+#    define LZO_INFO_OS_POSIX       "macosx"
+#  elif defined(__minix__) || defined(__minix)
+#    define LZO_OS_POSIX_MINIX      1
+#    define LZO_INFO_OS_POSIX       "minix"
+#  elif defined(__NetBSD__)
+#    define LZO_OS_POSIX_NETBSD     1
+#    define LZO_INFO_OS_POSIX       "netbsd"
+#  elif defined(__OpenBSD__)
+#    define LZO_OS_POSIX_OPENBSD    1
+#    define LZO_INFO_OS_POSIX       "openbsd"
+#  elif defined(__osf__)
+#    define LZO_OS_POSIX_OSF        1
+#    define LZO_INFO_OS_POSIX       "osf"
+#  elif defined(__solaris__) || defined(__sun)
+#    if defined(__SVR4) || defined(__svr4__)
+#      define LZO_OS_POSIX_SOLARIS  1
+#      define LZO_INFO_OS_POSIX     "solaris"
+#    else
+#      define LZO_OS_POSIX_SUNOS    1
+#      define LZO_INFO_OS_POSIX     "sunos"
+#    endif
+#  elif defined(__ultrix__) || defined(__ultrix)
+#    define LZO_OS_POSIX_ULTRIX     1
+#    define LZO_INFO_OS_POSIX       "ultrix"
+#  elif defined(_UNICOS)
+#    define LZO_OS_POSIX_UNICOS     1
+#    define LZO_INFO_OS_POSIX       "unicos"
+#  else
+#    define LZO_OS_POSIX_UNKNOWN    1
+#    define LZO_INFO_OS_POSIX       "unknown"
+#  endif
+#endif
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#  if (UINT_MAX != LZO_0xffffL)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
+#  if (UINT_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
+#  define LZO_CC_CILLY          1
+#  define LZO_INFO_CC           "Cilly"
+#  if defined(__CILLY__)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__CILLY__)
+#  else
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)
+#  define LZO_CC_SDCC           1
+#  define LZO_INFO_CC           "sdcc"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(SDCC)
+#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
+#  define LZO_CC_PATHSCALE      (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+#  define LZO_INFO_CC           "Pathscale C"
+#  define LZO_INFO_CCVER        __PATHSCALE__
+#elif defined(__INTEL_COMPILER)
+#  define LZO_CC_INTELC         1
+#  define LZO_INFO_CC           "Intel C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__INTEL_COMPILER)
+#  if defined(_WIN32) || defined(_WIN64)
+#    define LZO_CC_SYNTAX_MSC 1
+#  else
+#    define LZO_CC_SYNTAX_GNUC 1
+#  endif
+#elif defined(__POCC__) && defined(_WIN32)
+#  define LZO_CC_PELLESC        1
+#  define LZO_INFO_CC           "Pelles C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__POCC__)
+#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+#  if defined(__GNUC_PATCHLEVEL__)
+#    define LZO_CC_CLANG_GNUC   (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#  else
+#    define LZO_CC_CLANG_GNUC   (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+#  endif
+#  if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+#    define LZO_CC_CLANG_CLANG  (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
+#  else
+#    define LZO_CC_CLANG_CLANG  0x010000L
+#  endif
+#  define LZO_CC_CLANG          LZO_CC_CLANG_GNUC
+#  define LZO_INFO_CC           "clang"
+#  define LZO_INFO_CCVER        __VERSION__
+#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+#  if defined(__GNUC_PATCHLEVEL__)
+#    define LZO_CC_LLVM_GNUC    (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#  else
+#    define LZO_CC_LLVM_GNUC    (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+#  endif
+#  define LZO_CC_LLVM           LZO_CC_LLVM_GNUC
+#  define LZO_INFO_CC           "llvm-gcc"
+#  define LZO_INFO_CCVER        __VERSION__
+#elif defined(__GNUC__) && defined(__VERSION__)
+#  if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+#    define LZO_CC_GNUC         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#  elif defined(__GNUC_MINOR__)
+#    define LZO_CC_GNUC         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+#  else
+#    define LZO_CC_GNUC         (__GNUC__ * 0x10000L)
+#  endif
+#  define LZO_INFO_CC           "gcc"
+#  define LZO_INFO_CCVER        __VERSION__
+#elif defined(__ACK__) && defined(_ACK)
+#  define LZO_CC_ACK            1
+#  define LZO_INFO_CC           "Amsterdam Compiler Kit C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__AZTEC_C__)
+#  define LZO_CC_AZTECC         1
+#  define LZO_INFO_CC           "Aztec C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__CODEGEARC__)
+#  define LZO_CC_CODEGEARC      1
+#  define LZO_INFO_CC           "CodeGear C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__CODEGEARC__)
+#elif defined(__BORLANDC__)
+#  define LZO_CC_BORLANDC       1
+#  define LZO_INFO_CC           "Borland C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__BORLANDC__)
+#elif defined(_CRAYC) && defined(_RELEASE)
+#  define LZO_CC_CRAYC          1
+#  define LZO_INFO_CC           "Cray C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(_RELEASE)
+#elif defined(__DMC__) && defined(__SC__)
+#  define LZO_CC_DMC            1
+#  define LZO_INFO_CC           "Digital Mars C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__DMC__)
+#elif defined(__DECC)
+#  define LZO_CC_DECC           1
+#  define LZO_INFO_CC           "DEC C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__DECC)
+#elif defined(__HIGHC__)
+#  define LZO_CC_HIGHC          1
+#  define LZO_INFO_CC           "MetaWare High C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__IAR_SYSTEMS_ICC__)
+#  define LZO_CC_IARC           1
+#  define LZO_INFO_CC           "IAR C"
+#  if defined(__VER__)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__VER__)
+#  else
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(__IBMC__)
+#  define LZO_CC_IBMC           1
+#  define LZO_INFO_CC           "IBM C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__KEIL__) && defined(__C166__)
+#  define LZO_CC_KEILC          1
+#  define LZO_INFO_CC           "Keil C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__C166__)
+#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)
+#  define LZO_CC_LCCWIN32       1
+#  define LZO_INFO_CC           "lcc-win32"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__LCC__)
+#  define LZO_CC_LCC            1
+#  define LZO_INFO_CC           "lcc"
+#  if defined(__LCC_VERSION__)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__LCC_VERSION__)
+#  else
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(_MSC_VER)
+#  define LZO_CC_MSC            1
+#  define LZO_INFO_CC           "Microsoft C"
+#  if defined(_MSC_FULL_VER)
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
+#  else
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(_MSC_VER)
+#  endif
+#elif defined(__MWERKS__)
+#  define LZO_CC_MWERKS         1
+#  define LZO_INFO_CC           "Metrowerks C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__MWERKS__)
+#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
+#  define LZO_CC_NDPC           1
+#  define LZO_INFO_CC           "Microway NDP C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__PACIFIC__)
+#  define LZO_CC_PACIFICC       1
+#  define LZO_INFO_CC           "Pacific C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
+#  define LZO_CC_PGI            1
+#  define LZO_INFO_CC           "Portland Group PGI C"
+#  define LZO_INFO_CCVER        "unknown"
+#elif defined(__PUREC__) && defined(__TOS__)
+#  define LZO_CC_PUREC          1
+#  define LZO_INFO_CC           "Pure C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__PUREC__)
+#elif defined(__SC__) && defined(__ZTC__)
+#  define LZO_CC_SYMANTECC      1
+#  define LZO_INFO_CC           "Symantec C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__SC__)
+#elif defined(__SUNPRO_C)
+#  define LZO_INFO_CC           "SunPro C"
+#  if ((__SUNPRO_C)+0 > 0)
+#    define LZO_CC_SUNPROC      __SUNPRO_C
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__SUNPRO_C)
+#  else
+#    define LZO_CC_SUNPROC      1
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(__SUNPRO_CC)
+#  define LZO_INFO_CC           "SunPro C"
+#  if ((__SUNPRO_CC)+0 > 0)
+#    define LZO_CC_SUNPROC      __SUNPRO_CC
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__SUNPRO_CC)
+#  else
+#    define LZO_CC_SUNPROC      1
+#    define LZO_INFO_CCVER      "unknown"
+#  endif
+#elif defined(__TINYC__)
+#  define LZO_CC_TINYC          1
+#  define LZO_INFO_CC           "Tiny C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__TINYC__)
+#elif defined(__TSC__)
+#  define LZO_CC_TOPSPEEDC      1
+#  define LZO_INFO_CC           "TopSpeed C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__TSC__)
+#elif defined(__WATCOMC__)
+#  define LZO_CC_WATCOMC        1
+#  define LZO_INFO_CC           "Watcom C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__WATCOMC__)
+#elif defined(__TURBOC__)
+#  define LZO_CC_TURBOC         1
+#  define LZO_INFO_CC           "Turbo C"
+#  define LZO_INFO_CCVER        LZO_PP_MACRO_EXPAND(__TURBOC__)
+#elif defined(__ZTC__)
+#  define LZO_CC_ZORTECHC       1
+#  define LZO_INFO_CC           "Zortech C"
+#  if (__ZTC__ == 0x310)
+#    define LZO_INFO_CCVER      "0x310"
+#  else
+#    define LZO_INFO_CCVER      LZO_PP_MACRO_EXPAND(__ZTC__)
+#  endif
+#else
+#  define LZO_CC_UNKNOWN        1
+#  define LZO_INFO_CC           "unknown"
+#  define LZO_INFO_CCVER        "unknown"
+#endif
+#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
+#  error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY)
+#  if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY)
+#    if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
+#      define LZO_ARCH_CRAY_MPP     1
+#    elif defined(_CRAY1)
+#      define LZO_ARCH_CRAY_PVP     1
+#    endif
+#  endif
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE)
+#if (LZO_ARCH_GENERIC)
+#  define LZO_INFO_ARCH             "generic"
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#  define LZO_ARCH_I086             1
+#  define LZO_ARCH_IA16             1
+#  define LZO_INFO_ARCH             "i086"
+#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+#  define LZO_ARCH_ALPHA            1
+#  define LZO_INFO_ARCH             "alpha"
+#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E))
+#  define LZO_ARCH_ALPHA            1
+#  define LZO_INFO_ARCH             "alpha"
+#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+#  define LZO_ARCH_AMD64            1
+#  define LZO_INFO_ARCH             "amd64"
+#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
+#  define LZO_ARCH_ARM              1
+#  define LZO_ARCH_ARM_THUMB        1
+#  define LZO_INFO_ARCH             "arm_thumb"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+#  define LZO_ARCH_ARM              1
+#  if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+#    define LZO_ARCH_ARM_THUMB      1
+#    define LZO_INFO_ARCH           "arm_thumb"
+#  elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+#    define LZO_INFO_ARCH           "arm"
+#  else
+#    define LZO_INFO_ARCH           "arm"
+#  endif
+#elif defined(__arm__) || defined(_M_ARM)
+#  define LZO_ARCH_ARM              1
+#  define LZO_INFO_ARCH             "arm"
+#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
+#  define LZO_ARCH_AVR              1
+#  define LZO_INFO_ARCH             "avr"
+#elif defined(__avr32__) || defined(__AVR32__)
+#  define LZO_ARCH_AVR32            1
+#  define LZO_INFO_ARCH             "avr32"
+#elif defined(__bfin__)
+#  define LZO_ARCH_BLACKFIN         1
+#  define LZO_INFO_ARCH             "blackfin"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__)
+#  define LZO_ARCH_C166             1
+#  define LZO_INFO_ARCH             "c166"
+#elif defined(__cris__)
+#  define LZO_ARCH_CRIS             1
+#  define LZO_INFO_ARCH             "cris"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__)
+#  define LZO_ARCH_EZ80             1
+#  define LZO_INFO_ARCH             "ez80"
+#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+#  define LZO_ARCH_H8300            1
+#  define LZO_INFO_ARCH             "h8300"
+#elif defined(__hppa__) || defined(__hppa)
+#  define LZO_ARCH_HPPA             1
+#  define LZO_INFO_ARCH             "hppa"
+#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
+#  define LZO_ARCH_I386             1
+#  define LZO_ARCH_IA32             1
+#  define LZO_INFO_ARCH             "i386"
+#elif (LZO_CC_ZORTECHC && defined(__I86__))
+#  define LZO_ARCH_I386             1
+#  define LZO_ARCH_IA32             1
+#  define LZO_INFO_ARCH             "i386"
+#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386)
+#  define LZO_ARCH_I386             1
+#  define LZO_ARCH_IA32             1
+#  define LZO_INFO_ARCH             "i386"
+#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
+#  define LZO_ARCH_IA64             1
+#  define LZO_INFO_ARCH             "ia64"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__)
+#  define LZO_ARCH_M16C             1
+#  define LZO_INFO_ARCH             "m16c"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__)
+#  define LZO_ARCH_M16C             1
+#  define LZO_INFO_ARCH             "m16c"
+#elif defined(__m32r__)
+#  define LZO_ARCH_M32R             1
+#  define LZO_INFO_ARCH             "m32r"
+#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K)
+#  define LZO_ARCH_M68K             1
+#  define LZO_INFO_ARCH             "m68k"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__)
+#  define LZO_ARCH_MCS251           1
+#  define LZO_INFO_ARCH             "mcs251"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__)
+#  define LZO_ARCH_MCS51            1
+#  define LZO_INFO_ARCH             "mcs51"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__)
+#  define LZO_ARCH_MCS51            1
+#  define LZO_INFO_ARCH             "mcs51"
+#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
+#  define LZO_ARCH_MIPS             1
+#  define LZO_INFO_ARCH             "mips"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__)
+#  define LZO_ARCH_MSP430           1
+#  define LZO_INFO_ARCH             "msp430"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__)
+#  define LZO_ARCH_MSP430           1
+#  define LZO_INFO_ARCH             "msp430"
+#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+#  define LZO_ARCH_POWERPC          1
+#  define LZO_INFO_ARCH             "powerpc"
+#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+#  define LZO_ARCH_S390             1
+#  define LZO_INFO_ARCH             "s390"
+#elif defined(__sh__) || defined(_M_SH)
+#  define LZO_ARCH_SH               1
+#  define LZO_INFO_ARCH             "sh"
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
+#  define LZO_ARCH_SPARC            1
+#  define LZO_INFO_ARCH             "sparc"
+#elif defined(__SPU__)
+#  define LZO_ARCH_SPU              1
+#  define LZO_INFO_ARCH             "spu"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__z80)
+#  define LZO_ARCH_Z80              1
+#  define LZO_INFO_ARCH             "z80"
+#elif (LZO_ARCH_CRAY_PVP)
+#  if defined(_CRAYSV1)
+#    define LZO_ARCH_CRAY_SV1       1
+#    define LZO_INFO_ARCH           "cray_sv1"
+#  elif (_ADDR64)
+#    define LZO_ARCH_CRAY_T90       1
+#    define LZO_INFO_ARCH           "cray_t90"
+#  elif (_ADDR32)
+#    define LZO_ARCH_CRAY_YMP       1
+#    define LZO_INFO_ARCH           "cray_ymp"
+#  else
+#    define LZO_ARCH_CRAY_XMP       1
+#    define LZO_INFO_ARCH           "cray_xmp"
+#  endif
+#else
+#  define LZO_ARCH_UNKNOWN          1
+#  define LZO_INFO_ARCH             "unknown"
+#endif
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
+#  error "FIXME - missing define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
+#  error "FIXME - missing WIN32 define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
+#  error "FIXME - missing WIN64 define for CPU architecture"
+#endif
+#if (LZO_OS_OS216 || LZO_OS_WIN16)
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
+#  define LZO_ARCH_I086PM           1
+#  define LZO_ARCH_IA16PM           1
+#endif
+#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
+#  error "this should not happen"
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
+#  error "this should not happen"
+#endif
+#if (LZO_ARCH_I086)
+#  if (UINT_MAX != LZO_0xffffL)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if (LZO_ARCH_I386)
+#  if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
+#    error "this should not happen"
+#  endif
+#  if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
+#    error "this should not happen"
+#  endif
+#  if (ULONG_MAX != LZO_0xffffffffL)
+#    error "this should not happen"
+#  endif
+#endif
+#if !defined(__LZO_MM_OVERRIDE)
+#if (LZO_ARCH_I086)
+#if (UINT_MAX != LZO_0xffffL)
+#  error "this should not happen"
+#endif
+#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
+#  define LZO_MM_TINY           1
+#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)
+#  define LZO_MM_HUGE           1
+#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)
+#  define LZO_MM_SMALL          1
+#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)
+#  define LZO_MM_MEDIUM         1
+#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)
+#  define LZO_MM_COMPACT        1
+#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)
+#  define LZO_MM_LARGE          1
+#elif (LZO_CC_AZTECC)
+#  if defined(_LARGE_CODE) && defined(_LARGE_DATA)
+#    define LZO_MM_LARGE        1
+#  elif defined(_LARGE_CODE)
+#    define LZO_MM_MEDIUM       1
+#  elif defined(_LARGE_DATA)
+#    define LZO_MM_COMPACT      1
+#  else
+#    define LZO_MM_SMALL        1
+#  endif
+#elif (LZO_CC_ZORTECHC && defined(__VCM__))
+#  define LZO_MM_LARGE          1
+#else
+#  error "unknown memory model"
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#define LZO_HAVE_MM_HUGE_PTR        1
+#define LZO_HAVE_MM_HUGE_ARRAY      1
+#if (LZO_MM_TINY)
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC)
+#  undef LZO_HAVE_MM_HUGE_PTR
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_MSC && defined(_QC))
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#  if (_MSC_VER < 600)
+#    undef LZO_HAVE_MM_HUGE_PTR
+#  endif
+#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
+#  undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
+#  if (LZO_OS_DOS16)
+#    error "this should not happen"
+#  elif (LZO_CC_ZORTECHC)
+#  else
+#    error "this should not happen"
+#  endif
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC)
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295))
+   extern void __near __cdecl _AHSHIFT(void);
+#  define LZO_MM_AHSHIFT      ((unsigned) _AHSHIFT)
+#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16)
+#  define LZO_MM_AHSHIFT      12
+#elif (LZO_CC_WATCOMC)
+   extern unsigned char _HShift;
+#  define LZO_MM_AHSHIFT      ((unsigned) _HShift)
+#else
+#  error "FIXME - implement LZO_MM_AHSHIFT"
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+#elif (LZO_ARCH_C166)
+#if !defined(__MODEL__)
+#  error "FIXME - C166 __MODEL__"
+#elif ((__MODEL__) == 0)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 1)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 2)
+#  define LZO_MM_LARGE          1
+#elif ((__MODEL__) == 3)
+#  define LZO_MM_TINY           1
+#elif ((__MODEL__) == 4)
+#  define LZO_MM_XTINY          1
+#elif ((__MODEL__) == 5)
+#  define LZO_MM_XSMALL         1
+#else
+#  error "FIXME - C166 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS251)
+#if !defined(__MODEL__)
+#  error "FIXME - MCS251 __MODEL__"
+#elif ((__MODEL__) == 0)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 2)
+#  define LZO_MM_LARGE          1
+#elif ((__MODEL__) == 3)
+#  define LZO_MM_TINY           1
+#elif ((__MODEL__) == 4)
+#  define LZO_MM_XTINY          1
+#elif ((__MODEL__) == 5)
+#  define LZO_MM_XSMALL         1
+#else
+#  error "FIXME - MCS251 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS51)
+#if !defined(__MODEL__)
+#  error "FIXME - MCS51 __MODEL__"
+#elif ((__MODEL__) == 1)
+#  define LZO_MM_SMALL          1
+#elif ((__MODEL__) == 2)
+#  define LZO_MM_LARGE          1
+#elif ((__MODEL__) == 3)
+#  define LZO_MM_TINY           1
+#elif ((__MODEL__) == 4)
+#  define LZO_MM_XTINY          1
+#elif ((__MODEL__) == 5)
+#  define LZO_MM_XSMALL         1
+#else
+#  error "FIXME - MCS51 __MODEL__"
+#endif
+#elif (LZO_ARCH_CRAY_PVP)
+#  define LZO_MM_PVP            1
+#else
+#  define LZO_MM_FLAT           1
+#endif
+#if (LZO_MM_COMPACT)
+#  define LZO_INFO_MM           "compact"
+#elif (LZO_MM_FLAT)
+#  define LZO_INFO_MM           "flat"
+#elif (LZO_MM_HUGE)
+#  define LZO_INFO_MM           "huge"
+#elif (LZO_MM_LARGE)
+#  define LZO_INFO_MM           "large"
+#elif (LZO_MM_MEDIUM)
+#  define LZO_INFO_MM           "medium"
+#elif (LZO_MM_PVP)
+#  define LZO_INFO_MM           "pvp"
+#elif (LZO_MM_SMALL)
+#  define LZO_INFO_MM           "small"
+#elif (LZO_MM_TINY)
+#  define LZO_INFO_MM           "tiny"
+#else
+#  error "unknown memory model"
+#endif
+#endif
+#if defined(SIZEOF_SHORT)
+#  define LZO_SIZEOF_SHORT          (SIZEOF_SHORT)
+#endif
+#if defined(SIZEOF_INT)
+#  define LZO_SIZEOF_INT            (SIZEOF_INT)
+#endif
+#if defined(SIZEOF_LONG)
+#  define LZO_SIZEOF_LONG           (SIZEOF_LONG)
+#endif
+#if defined(SIZEOF_LONG_LONG)
+#  define LZO_SIZEOF_LONG_LONG      (SIZEOF_LONG_LONG)
+#endif
+#if defined(SIZEOF___INT16)
+#  define LZO_SIZEOF___INT16        (SIZEOF___INT16)
+#endif
+#if defined(SIZEOF___INT32)
+#  define LZO_SIZEOF___INT32        (SIZEOF___INT32)
+#endif
+#if defined(SIZEOF___INT64)
+#  define LZO_SIZEOF___INT64        (SIZEOF___INT64)
+#endif
+#if defined(SIZEOF_VOID_P)
+#  define LZO_SIZEOF_VOID_P         (SIZEOF_VOID_P)
+#endif
+#if defined(SIZEOF_SIZE_T)
+#  define LZO_SIZEOF_SIZE_T         (SIZEOF_SIZE_T)
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+#  define LZO_SIZEOF_PTRDIFF_T      (SIZEOF_PTRDIFF_T)
+#endif
+#define __LZO_LSR(x,b)    (((x)+0ul) >> (b))
+#if !defined(LZO_SIZEOF_SHORT)
+#  if (LZO_ARCH_CRAY_PVP)
+#    define LZO_SIZEOF_SHORT        8
+#  elif (USHRT_MAX == LZO_0xffffL)
+#    define LZO_SIZEOF_SHORT        2
+#  elif (__LZO_LSR(USHRT_MAX,7) == 1)
+#    define LZO_SIZEOF_SHORT        1
+#  elif (__LZO_LSR(USHRT_MAX,15) == 1)
+#    define LZO_SIZEOF_SHORT        2
+#  elif (__LZO_LSR(USHRT_MAX,31) == 1)
+#    define LZO_SIZEOF_SHORT        4
+#  elif (__LZO_LSR(USHRT_MAX,63) == 1)
+#    define LZO_SIZEOF_SHORT        8
+#  elif (__LZO_LSR(USHRT_MAX,127) == 1)
+#    define LZO_SIZEOF_SHORT        16
+#  else
+#    error "LZO_SIZEOF_SHORT"
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_INT)
+#  if (LZO_ARCH_CRAY_PVP)
+#    define LZO_SIZEOF_INT          8
+#  elif (UINT_MAX == LZO_0xffffL)
+#    define LZO_SIZEOF_INT          2
+#  elif (UINT_MAX == LZO_0xffffffffL)
+#    define LZO_SIZEOF_INT          4
+#  elif (__LZO_LSR(UINT_MAX,7) == 1)
+#    define LZO_SIZEOF_INT          1
+#  elif (__LZO_LSR(UINT_MAX,15) == 1)
+#    define LZO_SIZEOF_INT          2
+#  elif (__LZO_LSR(UINT_MAX,31) == 1)
+#    define LZO_SIZEOF_INT          4
+#  elif (__LZO_LSR(UINT_MAX,63) == 1)
+#    define LZO_SIZEOF_INT          8
+#  elif (__LZO_LSR(UINT_MAX,127) == 1)
+#    define LZO_SIZEOF_INT          16
+#  else
+#    error "LZO_SIZEOF_INT"
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_LONG)
+#  if (ULONG_MAX == LZO_0xffffffffL)
+#    define LZO_SIZEOF_LONG         4
+#  elif (__LZO_LSR(ULONG_MAX,7) == 1)
+#    define LZO_SIZEOF_LONG         1
+#  elif (__LZO_LSR(ULONG_MAX,15) == 1)
+#    define LZO_SIZEOF_LONG         2
+#  elif (__LZO_LSR(ULONG_MAX,31) == 1)
+#    define LZO_SIZEOF_LONG         4
+#  elif (__LZO_LSR(ULONG_MAX,63) == 1)
+#    define LZO_SIZEOF_LONG         8
+#  elif (__LZO_LSR(ULONG_MAX,127) == 1)
+#    define LZO_SIZEOF_LONG         16
+#  else
+#    error "LZO_SIZEOF_LONG"
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+#  if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
+#    if (LZO_CC_GNUC >= 0x030300ul)
+#      if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+#        define LZO_SIZEOF_LONG_LONG      LZO_SIZEOF_LONG
+#      elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1)
+#        define LZO_SIZEOF_LONG_LONG      4
+#      endif
+#    endif
+#  endif
+#endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+#if (LZO_ARCH_I086 && LZO_CC_DMC)
+#elif (LZO_CC_CILLY) && defined(__GNUC__)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_OS_WIN64 || defined(_WIN64))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_ARCH_I386 && (LZO_CC_DMC))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700)))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__)))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC))
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC))
+#  define LZO_SIZEOF___INT64        8
+#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+#  define LZO_SIZEOF___INT64        8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+#  define LZO_SIZEOF_LONG_LONG      8
+#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
+#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#  define LZO_SIZEOF_LONG_LONG      8
+#endif
+#endif
+#endif
+#if defined(__cplusplus) && (LZO_CC_GNUC)
+#  if (LZO_CC_GNUC < 0x020800ul)
+#    undef LZO_SIZEOF_LONG_LONG
+#  endif
+#endif
+#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+#  undef LZO_SIZEOF_LONG_LONG
+#endif
+#if !defined(LZO_SIZEOF_VOID_P)
+#if (LZO_ARCH_I086)
+#  define __LZO_WORDSIZE            2
+#  if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
+#    define LZO_SIZEOF_VOID_P       2
+#  elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
+#    define LZO_SIZEOF_VOID_P       4
+#  else
+#    error "LZO_MM"
+#  endif
+#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
+#  define __LZO_WORDSIZE            1
+#  define LZO_SIZEOF_VOID_P         2
+#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
+#  define LZO_SIZEOF_VOID_P         2
+#elif (LZO_ARCH_H8300)
+#  if defined(__NORMAL_MODE__)
+#    define __LZO_WORDSIZE          4
+#    define LZO_SIZEOF_VOID_P       2
+#  elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+#    define __LZO_WORDSIZE          4
+#    define LZO_SIZEOF_VOID_P       4
+#  else
+#    define __LZO_WORDSIZE          2
+#    define LZO_SIZEOF_VOID_P       2
+#  endif
+#  if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
+#    define LZO_SIZEOF_SIZE_T       LZO_SIZEOF_INT
+#    define LZO_SIZEOF_PTRDIFF_T    LZO_SIZEOF_INT
+#  endif
+#elif (LZO_ARCH_M16C)
+#  define __LZO_WORDSIZE            2
+#  if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
+#    define LZO_SIZEOF_VOID_P       4
+#  else
+#    define LZO_SIZEOF_VOID_P       2
+#  endif
+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+#  define __LZO_WORDSIZE            8
+#  define LZO_SIZEOF_VOID_P         4
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+#  define __LZO_WORDSIZE            8
+#  define LZO_SIZEOF_VOID_P         8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+#  define LZO_SIZEOF_VOID_P         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_LONG
+#elif (LZO_OS_OS400 || defined(__OS400__))
+#  define __LZO_WORDSIZE            LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_VOID_P         16
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_LONG
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+#  define LZO_SIZEOF_VOID_P         8
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_LONG
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_LONG
+#elif (LZO_ARCH_SPU)
+# if 0
+#  define __LZO_WORDSIZE            16
+# endif
+#  define LZO_SIZEOF_VOID_P         4
+#else
+#  define LZO_SIZEOF_VOID_P         LZO_SIZEOF_LONG
+#endif
+#endif
+#if !defined(LZO_WORDSIZE)
+#  if defined(__LZO_WORDSIZE)
+#    define LZO_WORDSIZE            __LZO_WORDSIZE
+#  else
+#    define LZO_WORDSIZE            LZO_SIZEOF_VOID_P
+#  endif
+#endif
+#if !defined(LZO_SIZEOF_SIZE_T)
+#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
+#  define LZO_SIZEOF_SIZE_T         2
+#else
+#  define LZO_SIZEOF_SIZE_T         LZO_SIZEOF_VOID_P
+#endif
+#endif
+#if !defined(LZO_SIZEOF_PTRDIFF_T)
+#if (LZO_ARCH_I086)
+#  if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE)
+#    define LZO_SIZEOF_PTRDIFF_T    LZO_SIZEOF_VOID_P
+#  elif (LZO_MM_COMPACT || LZO_MM_LARGE)
+#    if (LZO_CC_BORLANDC || LZO_CC_TURBOC)
+#      define LZO_SIZEOF_PTRDIFF_T  4
+#    else
+#      define LZO_SIZEOF_PTRDIFF_T  2
+#    endif
+#  else
+#    error "LZO_MM"
+#  endif
+#else
+#  define LZO_SIZEOF_PTRDIFF_T      LZO_SIZEOF_SIZE_T
+#endif
+#endif
+#if (LZO_ABI_NEUTRAL_ENDIAN)
+#  undef LZO_ABI_BIG_ENDIAN
+#  undef LZO_ABI_LITTLE_ENDIAN
+#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
+#  if (__LITTLE_ENDIAN__ == 1)
+#    define LZO_ABI_LITTLE_ENDIAN   1
+#  else
+#    define LZO_ABI_BIG_ENDIAN      1
+#  endif
+#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+#  define LZO_ABI_BIG_ENDIAN        1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+#  define LZO_ABI_LITTLE_ENDIAN     1
+#endif
+#endif
+#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
+#  error "this should not happen"
+#endif
+#if (LZO_ABI_BIG_ENDIAN)
+#  define LZO_INFO_ABI_ENDIAN       "be"
+#elif (LZO_ABI_LITTLE_ENDIAN)
+#  define LZO_INFO_ABI_ENDIAN       "le"
+#elif (LZO_ABI_NEUTRAL_ENDIAN)
+#  define LZO_INFO_ABI_ENDIAN       "neutral"
+#endif
+#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+#  define LZO_ABI_I8LP16         1
+#  define LZO_INFO_ABI_PM       "i8lp16"
+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+#  define LZO_ABI_ILP16         1
+#  define LZO_INFO_ABI_PM       "ilp16"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
+#  define LZO_ABI_ILP32         1
+#  define LZO_INFO_ABI_PM       "ilp32"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8)
+#  define LZO_ABI_LLP64         1
+#  define LZO_INFO_ABI_PM       "llp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+#  define LZO_ABI_LP64          1
+#  define LZO_INFO_ABI_PM       "lp64"
+#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+#  define LZO_ABI_ILP64         1
+#  define LZO_INFO_ABI_PM       "ilp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4)
+#  define LZO_ABI_IP32L64       1
+#  define LZO_INFO_ABI_PM       "ip32l64"
+#endif
+#if !defined(__LZO_LIBC_OVERRIDE)
+#if (LZO_LIBC_NAKED)
+#  define LZO_INFO_LIBC         "naked"
+#elif (LZO_LIBC_FREESTANDING)
+#  define LZO_INFO_LIBC         "freestanding"
+#elif (LZO_LIBC_MOSTLY_FREESTANDING)
+#  define LZO_INFO_LIBC         "mfreestanding"
+#elif (LZO_LIBC_ISOC90)
+#  define LZO_INFO_LIBC         "isoc90"
+#elif (LZO_LIBC_ISOC99)
+#  define LZO_INFO_LIBC         "isoc99"
+#elif defined(__dietlibc__)
+#  define LZO_LIBC_DIETLIBC     1
+#  define LZO_INFO_LIBC         "dietlibc"
+#elif defined(_NEWLIB_VERSION)
+#  define LZO_LIBC_NEWLIB       1
+#  define LZO_INFO_LIBC         "newlib"
+#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
+#  if defined(__UCLIBC_SUBLEVEL__)
+#    define LZO_LIBC_UCLIBC     (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+#  else
+#    define LZO_LIBC_UCLIBC     0x00090bL
+#  endif
+#  define LZO_INFO_LIBC         "uclibc"
+#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
+#  define LZO_LIBC_GLIBC        (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+#  define LZO_INFO_LIBC         "glibc"
+#elif (LZO_CC_MWERKS) && defined(__MSL__)
+#  define LZO_LIBC_MSL          __MSL__
+#  define LZO_INFO_LIBC         "msl"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+#  define LZO_LIBC_ISOC90       1
+#  define LZO_INFO_LIBC         "isoc90"
+#else
+#  define LZO_LIBC_DEFAULT      1
+#  define LZO_INFO_LIBC         "default"
+#endif
+#endif
+#if !defined(__lzo_gnuc_extension__)
+#if (LZO_CC_GNUC >= 0x020800ul)
+#  define __lzo_gnuc_extension__    __extension__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_gnuc_extension__    __extension__
+#else
+#  define __lzo_gnuc_extension__    /*empty*/
+#endif
+#endif
+#if !defined(__lzo_ua_volatile)
+#  define __lzo_ua_volatile     volatile
+#endif
+#if !defined(__lzo_alignof)
+#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#  define __lzo_alignof(e)      __alignof__(e)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
+#  define __lzo_alignof(e)      __alignof__(e)
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+#  define __lzo_alignof(e)      __alignof(e)
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_alignof(e)      __alignof__(e)
+#endif
+#endif
+#if defined(__lzo_alignof)
+#  define __lzo_HAVE_alignof 1
+#endif
+#if !defined(__lzo_constructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+#  define __lzo_constructor     __attribute__((__constructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+#  define __lzo_constructor     __attribute__((__constructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_constructor     __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__lzo_constructor)
+#  define __lzo_HAVE_constructor 1
+#endif
+#if !defined(__lzo_destructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+#  define __lzo_destructor      __attribute__((__destructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+#  define __lzo_destructor      __attribute__((__destructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_destructor      __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__lzo_destructor)
+#  define __lzo_HAVE_destructor 1
+#endif
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
+#  error "this should not happen"
+#endif
+#if !defined(__lzo_inline)
+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+#  define __lzo_inline          inline
+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+#  define __lzo_inline          __inline
+#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#  define __lzo_inline          __inline__
+#elif (LZO_CC_DMC)
+#  define __lzo_inline          __inline
+#elif (LZO_CC_INTELC)
+#  define __lzo_inline          __inline
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
+#  define __lzo_inline          __inline
+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
+#  define __lzo_inline          __inline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_inline          __inline__
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#  define __lzo_inline          inline
+#endif
+#endif
+#if defined(__lzo_inline)
+#  define __lzo_HAVE_inline 1
+#else
+#  define __lzo_inline          /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+#if (LZO_CC_GNUC >= 0x030200ul)
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+#  define __lzo_forceinline     __forceinline
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+#  define __lzo_forceinline     __forceinline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_forceinline     __inline__ __attribute__((__always_inline__))
+#endif
+#endif
+#if defined(__lzo_forceinline)
+#  define __lzo_HAVE_forceinline 1
+#else
+#  define __lzo_forceinline     /*empty*/
+#endif
+#if !defined(__lzo_noinline)
+#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
+#  define __lzo_noinline        __attribute__((__noinline__,__used__))
+#elif (LZO_CC_GNUC >= 0x030200ul)
+#  define __lzo_noinline        __attribute__((__noinline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC)
+#  define __lzo_noinline        __declspec(noinline)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_noinline        __attribute__((__noinline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_noinline        __attribute__((__noinline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+#  define __lzo_noinline        __declspec(noinline)
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
+#  if defined(__cplusplus)
+#  else
+#    define __lzo_noinline      __declspec(noinline)
+#  endif
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+#  define __lzo_noinline        __attribute__((__noinline__))
+#endif
+#endif
+#if defined(__lzo_noinline)
+#  define __lzo_HAVE_noinline 1
+#else
+#  define __lzo_noinline        /*empty*/
+#endif
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
+#  error "this should not happen"
+#endif
+#if !defined(__lzo_noreturn)
+#if (LZO_CC_GNUC >= 0x020700ul)
+#  define __lzo_noreturn        __attribute__((__noreturn__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+#  define __lzo_noreturn        __declspec(noreturn)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_noreturn        __attribute__((__noreturn__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_noreturn        __attribute__((__noreturn__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+#  define __lzo_noreturn        __declspec(noreturn)
+#endif
+#endif
+#if defined(__lzo_noreturn)
+#  define __lzo_HAVE_noreturn 1
+#else
+#  define __lzo_noreturn        /*empty*/
+#endif
+#if !defined(__lzo_nothrow)
+#if (LZO_CC_GNUC >= 0x030300ul)
+#  define __lzo_nothrow         __attribute__((__nothrow__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus)
+#  define __lzo_nothrow         __declspec(nothrow)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_nothrow         __attribute__((__nothrow__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_nothrow         __attribute__((__nothrow__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+#  define __lzo_nothrow         __declspec(nothrow)
+#endif
+#endif
+#if defined(__lzo_nothrow)
+#  define __lzo_HAVE_nothrow 1
+#else
+#  define __lzo_nothrow         /*empty*/
+#endif
+#if !defined(__lzo_restrict)
+#if (LZO_CC_GNUC >= 0x030400ul)
+#  define __lzo_restrict        __restrict__
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+#  define __lzo_restrict        __restrict__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM)
+#  define __lzo_restrict        __restrict__
+#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
+#  define __lzo_restrict        __restrict
+#endif
+#endif
+#if defined(__lzo_restrict)
+#  define __lzo_HAVE_restrict 1
+#else
+#  define __lzo_restrict        /*empty*/
+#endif
+#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
+#if (LZO_CC_GNUC >= 0x030200ul)
+#  define __lzo_likely(e)       (__builtin_expect(!!(e),1))
+#  define __lzo_unlikely(e)     (__builtin_expect(!!(e),0))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+#  define __lzo_likely(e)       (__builtin_expect(!!(e),1))
+#  define __lzo_unlikely(e)     (__builtin_expect(!!(e),0))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#  define __lzo_likely(e)       (__builtin_expect(!!(e),1))
+#  define __lzo_unlikely(e)     (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__lzo_likely)
+#  define __lzo_HAVE_likely 1
+#else
+#  define __lzo_likely(e)       (e)
+#endif
+#if defined(__lzo_unlikely)
+#  define __lzo_HAVE_unlikely 1
+#else
+#  define __lzo_unlikely(e)     (e)
+#endif
+#if !defined(LZO_UNUSED)
+#  if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+#    define LZO_UNUSED(var)         ((void) &var)
+#  elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
+#    define LZO_UNUSED(var)         if (&var) ; else
+#  elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#    define LZO_UNUSED(var)         ((void) var)
+#  elif (LZO_CC_MSC && (_MSC_VER < 900))
+#    define LZO_UNUSED(var)         if (&var) ; else
+#  elif (LZO_CC_KEILC)
+#    define LZO_UNUSED(var)         {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
+#  elif (LZO_CC_PACIFICC)
+#    define LZO_UNUSED(var)         ((void) sizeof(var))
+#  elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+#    define LZO_UNUSED(var)         ((void) var)
+#  else
+#    define LZO_UNUSED(var)         ((void) &var)
+#  endif
+#endif
+#if !defined(LZO_UNUSED_FUNC)
+#  if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+#    define LZO_UNUSED_FUNC(func)   ((void) func)
+#  elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
+#    define LZO_UNUSED_FUNC(func)   if (func) ; else
+#  elif (LZO_CC_CLANG || LZO_CC_LLVM)
+#    define LZO_UNUSED_FUNC(func)   ((void) &func)
+#  elif (LZO_CC_MSC && (_MSC_VER < 900))
+#    define LZO_UNUSED_FUNC(func)   if (func) ; else
+#  elif (LZO_CC_MSC)
+#    define LZO_UNUSED_FUNC(func)   ((void) &func)
+#  elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+#    define LZO_UNUSED_FUNC(func)   {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
+#  else
+#    define LZO_UNUSED_FUNC(func)   ((void) func)
+#  endif
+#endif
+#if !defined(LZO_UNUSED_LABEL)
+#  if (LZO_CC_WATCOMC) && defined(__cplusplus)
+#    define LZO_UNUSED_LABEL(l)     switch(0) case 1:goto l
+#  elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
+#    define LZO_UNUSED_LABEL(l)     if (0) goto l
+#  else
+#    define LZO_UNUSED_LABEL(l)     switch(0) case 1:goto l
+#  endif
+#endif
+#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
+#  if 0
+#    define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var
+#  elif 0 && (LZO_CC_GNUC)
+#    define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var = var
+#  else
+#    define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var = init
+#  endif
+#endif
+#if !defined(LZO_UNCONST_CAST)
+#  if 0 && defined(__cplusplus)
+#    define LZO_UNCONST_CAST(t,e)   (const_cast<t> (e))
+#  elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#    define LZO_UNCONST_CAST(t,e)   ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e))))))
+#  else
+#    define LZO_UNCONST_CAST(t,e)   ((t) ((void *) ((char *) ((const void *) (e)))))
+#  endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
+#  if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1-!(e)];
+#  elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1u-2*!(e)];
+#  elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1-!(e)];
+#  else
+#    define LZO_COMPILE_TIME_ASSERT_HEADER(e)  extern int __lzo_cta[1-2*!(e)];
+#  endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+#  if (LZO_CC_AZTECC)
+#    define LZO_COMPILE_TIME_ASSERT(e)  {typedef int __lzo_cta_t[1-!(e)];}
+#  elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+#    define LZO_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;
+#  elif (LZO_CC_MSC && (_MSC_VER < 900))
+#    define LZO_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;
+#  elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+#    define LZO_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;
+#  else
+#    define LZO_COMPILE_TIME_ASSERT(e)  {typedef int __lzo_cta_t[1-2*!(e)];}
+#  endif
+#endif
+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+#  if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+#  elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+#    define __lzo_cdecl                 __cdecl
+#    define __lzo_cdecl_atexit          /*empty*/
+#    define __lzo_cdecl_main            __cdecl
+#    if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+#      define __lzo_cdecl_qsort         __pascal
+#    elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+#      define __lzo_cdecl_qsort         _stdcall
+#    else
+#      define __lzo_cdecl_qsort         __cdecl
+#    endif
+#  elif (LZO_CC_WATCOMC)
+#    define __lzo_cdecl                 __cdecl
+#  else
+#    define __lzo_cdecl                 __cdecl
+#    define __lzo_cdecl_atexit          __cdecl
+#    define __lzo_cdecl_main            __cdecl
+#    define __lzo_cdecl_qsort           __cdecl
+#  endif
+#  if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
+#  elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+#    define __lzo_cdecl_sighandler      __pascal
+#  elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+#    define __lzo_cdecl_sighandler      _stdcall
+#  elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+#    define __lzo_cdecl_sighandler      __clrcall
+#  elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+#    if defined(_DLL)
+#      define __lzo_cdecl_sighandler    _far _cdecl _loadds
+#    elif defined(_MT)
+#      define __lzo_cdecl_sighandler    _far _cdecl
+#    else
+#      define __lzo_cdecl_sighandler    _cdecl
+#    endif
+#  else
+#    define __lzo_cdecl_sighandler      __cdecl
+#  endif
+#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
+#  define __lzo_cdecl                   __cdecl
+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
+#  define __lzo_cdecl                   cdecl
+#endif
+#if !defined(__lzo_cdecl)
+#  define __lzo_cdecl                   /*empty*/
+#endif
+#if !defined(__lzo_cdecl_atexit)
+#  define __lzo_cdecl_atexit            /*empty*/
+#endif
+#if !defined(__lzo_cdecl_main)
+#  define __lzo_cdecl_main              /*empty*/
+#endif
+#if !defined(__lzo_cdecl_qsort)
+#  define __lzo_cdecl_qsort             /*empty*/
+#endif
+#if !defined(__lzo_cdecl_sighandler)
+#  define __lzo_cdecl_sighandler        /*empty*/
+#endif
+#if !defined(__lzo_cdecl_va)
+#  define __lzo_cdecl_va                __lzo_cdecl
+#endif
+#if !(LZO_CFG_NO_WINDOWS_H)
+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+#  if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+#  elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
+#  elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+#  else
+#    define LZO_HAVE_WINDOWS_H 1
+#  endif
+#endif
+#endif
+#if (LZO_ARCH_ALPHA)
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#  define LZO_OPT_AVOID_SHORT       1
+#  define LZO_OPT_AVOID_USHORT      1
+#elif (LZO_ARCH_AMD64)
+#  define LZO_OPT_AVOID_INT_INDEX   1
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#  define LZO_OPT_UNALIGNED64       1
+#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
+#elif (LZO_ARCH_ARM)
+#  define LZO_OPT_AVOID_SHORT       1
+#  define LZO_OPT_AVOID_USHORT      1
+#elif (LZO_ARCH_CRIS)
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#elif (LZO_ARCH_I386)
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#elif (LZO_ARCH_IA64)
+#  define LZO_OPT_AVOID_INT_INDEX   1
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#  define LZO_OPT_PREFER_POSTINC    1
+#elif (LZO_ARCH_M68K)
+#  define LZO_OPT_PREFER_POSTINC    1
+#  define LZO_OPT_PREFER_PREDEC     1
+#  if defined(__mc68020__) && !defined(__mcoldfire__)
+#    define LZO_OPT_UNALIGNED16     1
+#    define LZO_OPT_UNALIGNED32     1
+#  endif
+#elif (LZO_ARCH_MIPS)
+#  define LZO_OPT_AVOID_UINT_INDEX  1
+#elif (LZO_ARCH_POWERPC)
+#  define LZO_OPT_PREFER_PREINC     1
+#  define LZO_OPT_PREFER_PREDEC     1
+#  if (LZO_ABI_BIG_ENDIAN)
+#    define LZO_OPT_UNALIGNED16     1
+#    define LZO_OPT_UNALIGNED32     1
+#  endif
+#elif (LZO_ARCH_S390)
+#  define LZO_OPT_UNALIGNED16       1
+#  define LZO_OPT_UNALIGNED32       1
+#  if (LZO_SIZEOF_SIZE_T == 8)
+#    define LZO_OPT_UNALIGNED64     1
+#  endif
+#elif (LZO_ARCH_SH)
+#  define LZO_OPT_PREFER_POSTINC    1
+#  define LZO_OPT_PREFER_PREDEC     1
+#endif
+#ifndef LZO_CFG_NO_INLINE_ASM
+#if (LZO_CC_LLVM)
+#  define LZO_CFG_NO_INLINE_ASM 1
+#endif
+#endif
+#ifndef LZO_CFG_NO_UNALIGNED
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
+#  define LZO_CFG_NO_UNALIGNED 1
+#endif
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+#  undef LZO_OPT_UNALIGNED16
+#  undef LZO_OPT_UNALIGNED32
+#  undef LZO_OPT_UNALIGNED64
+#endif
+#if (LZO_CFG_NO_INLINE_ASM)
+#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#  define LZO_ASM_SYNTAX_MSC 1
+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
+#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+#  define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+#  define LZO_ASM_SYNTAX_GNUC 1
+#endif
+#if (LZO_ASM_SYNTAX_GNUC)
+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
+#  define __LZO_ASM_CLOBBER         "ax"
+#elif (LZO_CC_INTELC)
+#  define __LZO_ASM_CLOBBER         "memory"
+#else
+#  define __LZO_ASM_CLOBBER         "cc", "memory"
+#endif
+#endif
+#if defined(__LZO_INFOSTR_MM)
+#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
+#  define __LZO_INFOSTR_MM          ""
+#elif defined(LZO_INFO_MM)
+#  define __LZO_INFOSTR_MM          "." LZO_INFO_MM
+#else
+#  define __LZO_INFOSTR_MM          ""
+#endif
+#if defined(__LZO_INFOSTR_PM)
+#elif defined(LZO_INFO_ABI_PM)
+#  define __LZO_INFOSTR_PM          "." LZO_INFO_ABI_PM
+#else
+#  define __LZO_INFOSTR_PM          ""
+#endif
+#if defined(__LZO_INFOSTR_ENDIAN)
+#elif defined(LZO_INFO_ABI_ENDIAN)
+#  define __LZO_INFOSTR_ENDIAN      "." LZO_INFO_ABI_ENDIAN
+#else
+#  define __LZO_INFOSTR_ENDIAN      ""
+#endif
+#if defined(__LZO_INFOSTR_OSNAME)
+#elif defined(LZO_INFO_OS_CONSOLE)
+#  define __LZO_INFOSTR_OSNAME      LZO_INFO_OS "." LZO_INFO_OS_CONSOLE
+#elif defined(LZO_INFO_OS_POSIX)
+#  define __LZO_INFOSTR_OSNAME      LZO_INFO_OS "." LZO_INFO_OS_POSIX
+#else
+#  define __LZO_INFOSTR_OSNAME      LZO_INFO_OS
+#endif
+#if defined(__LZO_INFOSTR_LIBC)
+#elif defined(LZO_INFO_LIBC)
+#  define __LZO_INFOSTR_LIBC        "." LZO_INFO_LIBC
+#else
+#  define __LZO_INFOSTR_LIBC        ""
+#endif
+#if defined(__LZO_INFOSTR_CCVER)
+#elif defined(LZO_INFO_CCVER)
+#  define __LZO_INFOSTR_CCVER       " " LZO_INFO_CCVER
+#else
+#  define __LZO_INFOSTR_CCVER       ""
+#endif
+#define LZO_INFO_STRING \
+    LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
+    " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
+
+#endif
+
+#endif
+
+#undef LZO_HAVE_CONFIG_H
+#include "minilzo.h"
+
+#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2060)
+#  error "version mismatch in miniLZO source files"
+#endif
+
+#ifdef MINILZO_HAVE_CONFIG_H
+#  define LZO_HAVE_CONFIG_H 1
+#endif
+
+#ifndef __LZO_CONF_H
+#define __LZO_CONF_H 1
+
+#if !defined(__LZO_IN_MINILZO)
+#if (LZO_CFG_FREESTANDING)
+#  define LZO_LIBC_FREESTANDING 1
+#  define LZO_OS_FREESTANDING 1
+#  define ACC_LIBC_FREESTANDING 1
+#  define ACC_OS_FREESTANDING 1
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+#  define ACC_CFG_NO_UNALIGNED 1
+#endif
+#if (LZO_ARCH_GENERIC)
+#  define ACC_ARCH_GENERIC 1
+#endif
+#if (LZO_ABI_NEUTRAL_ENDIAN)
+#  define ACC_ABI_NEUTRAL_ENDIAN 1
+#endif
+#if (LZO_HAVE_CONFIG_H)
+#  define ACC_CONFIG_NO_HEADER 1
+#endif
+#if defined(LZO_CFG_EXTRA_CONFIG_HEADER)
+#  include LZO_CFG_EXTRA_CONFIG_HEADER
+#endif
+#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED)
+#  error "include this file first"
+#endif
+#include "lzo/lzoconf.h"
+#endif
+
+#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED)
+#  error "version mismatch"
+#endif
+
+#if (LZO_CC_BORLANDC && LZO_ARCH_I086)
+#  pragma option -h
+#endif
+
+#if (LZO_CC_MSC && (_MSC_VER >= 1000))
+#  pragma warning(disable: 4127 4701)
+#endif
+#if (LZO_CC_MSC && (_MSC_VER >= 1300))
+#  pragma warning(disable: 4820)
+#  pragma warning(disable: 4514 4710 4711)
+#endif
+
+#if (LZO_CC_SUNPROC)
+#if !defined(__cplusplus)
+#  pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED)
+#  pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP)
+#  pragma error_messages(off,E_STATEMENT_NOT_REACHED)
+#endif
+#endif
+
+#if (__LZO_MMODEL_HUGE) && !(LZO_HAVE_MM_HUGE_PTR)
+#  error "this should not happen - check defines for __huge"
+#endif
+
+#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING)
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#  define ACC_WANT_ACC_INCD_H 1
+#  define ACC_WANT_ACC_INCE_H 1
+#  define ACC_WANT_ACC_INCI_H 1
+#elif 1
+#  include <string.h>
+#else
+#  define ACC_WANT_ACC_INCD_H 1
+#endif
+
+#if (LZO_ARCH_I086)
+#  define ACC_MM_AHSHIFT        LZO_MM_AHSHIFT
+#  define ACC_PTR_FP_OFF(x)     (((const unsigned __far*)&(x))[0])
+#  define ACC_PTR_FP_SEG(x)     (((const unsigned __far*)&(x))[1])
+#  define ACC_PTR_MK_FP(s,o)    ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o)))
+#endif
+
+#if !defined(lzo_uintptr_t)
+#  if defined(__LZO_MMODEL_HUGE)
+#    define lzo_uintptr_t       unsigned long
+#  elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16)
+#    define __LZO_UINTPTR_T_IS_POINTER 1
+     typedef char*              lzo_uintptr_t;
+#    define lzo_uintptr_t       lzo_uintptr_t
+#  elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P)
+#    define lzo_uintptr_t       size_t
+#  elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P)
+#    define lzo_uintptr_t       unsigned long
+#  elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P)
+#    define lzo_uintptr_t       unsigned int
+#  elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P)
+#    define lzo_uintptr_t       unsigned long long
+#  else
+#    define lzo_uintptr_t       size_t
+#  endif
+#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
+
+#if 1 && !defined(LZO_CFG_FREESTANDING)
+#if 1 && !defined(HAVE_STRING_H)
+#define HAVE_STRING_H 1
+#endif
+#if 1 && !defined(HAVE_MEMCMP)
+#define HAVE_MEMCMP 1
+#endif
+#if 1 && !defined(HAVE_MEMCPY)
+#define HAVE_MEMCPY 1
+#endif
+#if 1 && !defined(HAVE_MEMMOVE)
+#define HAVE_MEMMOVE 1
+#endif
+#if 1 && !defined(HAVE_MEMSET)
+#define HAVE_MEMSET 1
+#endif
+#endif
+
+#if 1 && defined(HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#if (LZO_CFG_FREESTANDING)
+#  undef HAVE_MEMCMP
+#  undef HAVE_MEMCPY
+#  undef HAVE_MEMMOVE
+#  undef HAVE_MEMSET
+#endif
+
+#if !(HAVE_MEMCMP)
+#  undef memcmp
+#  define memcmp(a,b,c)         lzo_memcmp(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+#  undef lzo_memcmp
+#  define lzo_memcmp(a,b,c)     memcmp(a,b,c)
+#endif
+#if !(HAVE_MEMCPY)
+#  undef memcpy
+#  define memcpy(a,b,c)         lzo_memcpy(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+#  undef lzo_memcpy
+#  define lzo_memcpy(a,b,c)     memcpy(a,b,c)
+#endif
+#if !(HAVE_MEMMOVE)
+#  undef memmove
+#  define memmove(a,b,c)        lzo_memmove(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+#  undef lzo_memmove
+#  define lzo_memmove(a,b,c)    memmove(a,b,c)
+#endif
+#if !(HAVE_MEMSET)
+#  undef memset
+#  define memset(a,b,c)         lzo_memset(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+#  undef lzo_memset
+#  define lzo_memset(a,b,c)     memset(a,b,c)
+#endif
+
+#undef NDEBUG
+#if (LZO_CFG_FREESTANDING)
+#  undef LZO_DEBUG
+#  define NDEBUG 1
+#  undef assert
+#  define assert(e) ((void)0)
+#else
+#  if !defined(LZO_DEBUG)
+#    define NDEBUG 1
+#  endif
+#  include <assert.h>
+#endif
+
+#if 0 && defined(__BOUNDS_CHECKING_ON)
+#  include <unchecked.h>
+#else
+#  define BOUNDS_CHECKING_OFF_DURING(stmt)      stmt
+#  define BOUNDS_CHECKING_OFF_IN_EXPR(expr)     (expr)
+#endif
+
+#if !defined(__lzo_inline)
+#  define __lzo_inline              /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+#  define __lzo_forceinline         /*empty*/
+#endif
+#if !defined(__lzo_noinline)
+#  define __lzo_noinline            /*empty*/
+#endif
+
+#if (LZO_CFG_PGO)
+#  undef __acc_likely
+#  undef __acc_unlikely
+#  undef __lzo_likely
+#  undef __lzo_unlikely
+#  define __acc_likely(e)       (e)
+#  define __acc_unlikely(e)     (e)
+#  define __lzo_likely(e)       (e)
+#  define __lzo_unlikely(e)     (e)
+#endif
+
+#if 1
+#  define LZO_BYTE(x)       ((unsigned char) (x))
+#else
+#  define LZO_BYTE(x)       ((unsigned char) ((x) & 0xff))
+#endif
+
+#define LZO_MAX(a,b)        ((a) >= (b) ? (a) : (b))
+#define LZO_MIN(a,b)        ((a) <= (b) ? (a) : (b))
+#define LZO_MAX3(a,b,c)     ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
+#define LZO_MIN3(a,b,c)     ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c))
+
+#define lzo_sizeof(type)    ((lzo_uint) (sizeof(type)))
+
+#define LZO_HIGH(array)     ((lzo_uint) (sizeof(array)/sizeof(*(array))))
+
+#define LZO_SIZE(bits)      (1u << (bits))
+#define LZO_MASK(bits)      (LZO_SIZE(bits) - 1)
+
+#define LZO_LSIZE(bits)     (1ul << (bits))
+#define LZO_LMASK(bits)     (LZO_LSIZE(bits) - 1)
+
+#define LZO_USIZE(bits)     ((lzo_uint) 1 << (bits))
+#define LZO_UMASK(bits)     (LZO_USIZE(bits) - 1)
+
+#if !defined(DMUL)
+#if 0
+
+#  define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b)))
+#else
+#  define DMUL(a,b) ((lzo_xint) ((a) * (b)))
+#endif
+#endif
+
+#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386 || LZO_ARCH_POWERPC)
+#  if (LZO_SIZEOF_SHORT == 2)
+#    define LZO_UNALIGNED_OK_2 1
+#  endif
+#  if (LZO_SIZEOF_INT == 4)
+#    define LZO_UNALIGNED_OK_4 1
+#  endif
+#endif
+#if 1 && (LZO_ARCH_AMD64)
+#  if defined(LZO_UINT64_MAX)
+#    define LZO_UNALIGNED_OK_8 1
+#  endif
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+#  undef LZO_UNALIGNED_OK_2
+#  undef LZO_UNALIGNED_OK_4
+#  undef LZO_UNALIGNED_OK_8
+#endif
+
+#undef UA_GET16
+#undef UA_SET16
+#undef UA_COPY16
+#undef UA_GET32
+#undef UA_SET32
+#undef UA_COPY32
+#undef UA_GET64
+#undef UA_SET64
+#undef UA_COPY64
+#if defined(LZO_UNALIGNED_OK_2)
+   LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(unsigned short) == 2)
+#  if 1 && defined(ACC_UA_COPY16)
+#    define UA_GET16        ACC_UA_GET16
+#    define UA_SET16        ACC_UA_SET16
+#    define UA_COPY16       ACC_UA_COPY16
+#  else
+#    define UA_GET16(p)     (* (__lzo_ua_volatile const lzo_ushortp) (__lzo_ua_volatile const lzo_voidp) (p))
+#    define UA_SET16(p,v)   ((* (__lzo_ua_volatile lzo_ushortp) (__lzo_ua_volatile lzo_voidp) (p)) = (unsigned short) (v))
+#    define UA_COPY16(d,s)  UA_SET16(d, UA_GET16(s))
+#  endif
+#endif
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+   LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4)
+#  if 1 && defined(ACC_UA_COPY32)
+#    define UA_GET32        ACC_UA_GET32
+#    define UA_SET32        ACC_UA_SET32
+#    define UA_COPY32       ACC_UA_COPY32
+#  else
+#    define UA_GET32(p)     (* (__lzo_ua_volatile const lzo_uint32p) (__lzo_ua_volatile const lzo_voidp) (p))
+#    define UA_SET32(p,v)   ((* (__lzo_ua_volatile lzo_uint32p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint32) (v))
+#    define UA_COPY32(d,s)  UA_SET32(d, UA_GET32(s))
+#  endif
+#endif
+#if defined(LZO_UNALIGNED_OK_8)
+   LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64) == 8)
+#  if 1 && defined(ACC_UA_COPY64)
+#    define UA_GET64        ACC_UA_GET64
+#    define UA_SET64        ACC_UA_SET64
+#    define UA_COPY64       ACC_UA_COPY64
+#  else
+#    define UA_GET64(p)     (* (__lzo_ua_volatile const lzo_uint64p) (__lzo_ua_volatile const lzo_voidp) (p))
+#    define UA_SET64(p,v)   ((* (__lzo_ua_volatile lzo_uint64p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint64) (v))
+#    define UA_COPY64(d,s)  UA_SET64(d, UA_GET64(s))
+#  endif
+#endif
+
+#define MEMCPY8_DS(dest,src,len) \
+    lzo_memcpy(dest,src,len); dest += len; src += len
+
+#define BZERO8_PTR(s,l,n) \
+    lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n))
+
+#define MEMCPY_DS(dest,src,len) \
+    do *dest++ = *src++; while (--len > 0)
+
+LZO_EXTERN(const lzo_bytep) lzo_copyright(void);
+
+#ifndef __LZO_PTR_H
+#define __LZO_PTR_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(lzo_uintptr_t)
+#  if (__LZO_MMODEL_HUGE)
+#    define lzo_uintptr_t   unsigned long
+#  else
+#    define lzo_uintptr_t   acc_uintptr_t
+#    ifdef __ACC_INTPTR_T_IS_POINTER
+#      define __LZO_UINTPTR_T_IS_POINTER 1
+#    endif
+#  endif
+#endif
+
+#if (LZO_ARCH_I086)
+#define PTR(a)              ((lzo_bytep) (a))
+#define PTR_ALIGNED_4(a)    ((ACC_PTR_FP_OFF(a) & 3) == 0)
+#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0)
+#elif (LZO_MM_PVP)
+#define PTR(a)              ((lzo_bytep) (a))
+#define PTR_ALIGNED_8(a)    ((((lzo_uintptr_t)(a)) >> 61) == 0)
+#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0)
+#else
+#define PTR(a)              ((lzo_uintptr_t) (a))
+#define PTR_LINEAR(a)       PTR(a)
+#define PTR_ALIGNED_4(a)    ((PTR_LINEAR(a) & 3) == 0)
+#define PTR_ALIGNED_8(a)    ((PTR_LINEAR(a) & 7) == 0)
+#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
+#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
+#endif
+
+#define PTR_LT(a,b)         (PTR(a) < PTR(b))
+#define PTR_GE(a,b)         (PTR(a) >= PTR(b))
+#define PTR_DIFF(a,b)       (PTR(a) - PTR(b))
+#define pd(a,b)             ((lzo_uint) ((a)-(b)))
+
+LZO_EXTERN(lzo_uintptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr);
+
+typedef union
+{
+    char            a_char;
+    unsigned char   a_uchar;
+    short           a_short;
+    unsigned short  a_ushort;
+    int             a_int;
+    unsigned int    a_uint;
+    long            a_long;
+    unsigned long   a_ulong;
+    lzo_int         a_lzo_int;
+    lzo_uint        a_lzo_uint;
+    lzo_int32       a_lzo_int32;
+    lzo_uint32      a_lzo_uint32;
+#if defined(LZO_UINT64_MAX)
+    lzo_int64       a_lzo_int64;
+    lzo_uint64      a_lzo_uint64;
+#endif
+    ptrdiff_t       a_ptrdiff_t;
+    lzo_uintptr_t   a_lzo_uintptr_t;
+    lzo_voidp       a_lzo_voidp;
+    void *          a_void_p;
+    lzo_bytep       a_lzo_bytep;
+    lzo_bytepp      a_lzo_bytepp;
+    lzo_uintp       a_lzo_uintp;
+    lzo_uint *      a_lzo_uint_p;
+    lzo_uint32p     a_lzo_uint32p;
+    lzo_uint32 *    a_lzo_uint32_p;
+    unsigned char * a_uchar_p;
+    char *          a_char_p;
+}
+lzo_full_align_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#ifndef LZO_DETERMINISTIC
+#define LZO_DETERMINISTIC 1
+#endif
+
+#ifndef LZO_DICT_USE_PTR
+#define LZO_DICT_USE_PTR 1
+#if 0 && (LZO_ARCH_I086)
+#  undef LZO_DICT_USE_PTR
+#  define LZO_DICT_USE_PTR 0
+#endif
+#endif
+
+#if (LZO_DICT_USE_PTR)
+#  define lzo_dict_t    const lzo_bytep
+#  define lzo_dict_p    lzo_dict_t __LZO_MMODEL *
+#else
+#  define lzo_dict_t    lzo_uint
+#  define lzo_dict_p    lzo_dict_t __LZO_MMODEL *
+#endif
+
+#endif
+
+#if !defined(MINILZO_CFG_SKIP_LZO_PTR)
+
+LZO_PUBLIC(lzo_uintptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr)
+{
+    lzo_uintptr_t p;
+
+#if (LZO_ARCH_I086)
+    p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr));
+#elif (LZO_MM_PVP)
+    p = (lzo_uintptr_t) (ptr);
+    p = (p << 3) | (p >> 61);
+#else
+    p = (lzo_uintptr_t) PTR_LINEAR(ptr);
+#endif
+
+    return p;
+}
+
+LZO_PUBLIC(unsigned)
+__lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
+{
+#if defined(__LZO_UINTPTR_T_IS_POINTER)
+    size_t n = (size_t) ptr;
+    n = (((n + size - 1) / size) * size) - n;
+#else
+    lzo_uintptr_t p, n;
+    p = __lzo_ptr_linear(ptr);
+    n = (((p + size - 1) / size) * size) - p;
+#endif
+
+    assert(size > 0);
+    assert((long)n >= 0);
+    assert(n <= size);
+    return (unsigned)n;
+}
+
+#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_UTIL)
+
+/* If you use the LZO library in a product, I would appreciate that you
+ * keep this copyright string in the executable of your product.
+ */
+
+static const char __lzo_copyright[] =
+#if !defined(__LZO_IN_MINLZO)
+    LZO_VERSION_STRING;
+#else
+    "\r\n\n"
+    "LZO data compression library.\n"
+    "$Copyright: LZO Copyright (C) 1996-2011 Markus Franz Xaver Johannes Oberhumer\n"
+    "<markus@oberhumer.com>\n"
+    "http://www.oberhumer.com $\n\n"
+    "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n"
+    "$Info: " LZO_INFO_STRING " $\n";
+#endif
+
+LZO_PUBLIC(const lzo_bytep)
+lzo_copyright(void)
+{
+#if (LZO_OS_DOS16 && LZO_CC_TURBOC)
+    return (lzo_voidp) __lzo_copyright;
+#else
+    return (const lzo_bytep) __lzo_copyright;
+#endif
+}
+
+LZO_PUBLIC(unsigned)
+lzo_version(void)
+{
+    return LZO_VERSION;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_string(void)
+{
+    return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_date(void)
+{
+    return LZO_VERSION_DATE;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_string(void)
+{
+    return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_date(void)
+{
+    return LZO_VERSION_DATE;
+}
+
+#define LZO_BASE 65521u
+#define LZO_NMAX 5552
+
+#define LZO_DO1(buf,i)  s1 += buf[i]; s2 += s1
+#define LZO_DO2(buf,i)  LZO_DO1(buf,i); LZO_DO1(buf,i+1);
+#define LZO_DO4(buf,i)  LZO_DO2(buf,i); LZO_DO2(buf,i+2);
+#define LZO_DO8(buf,i)  LZO_DO4(buf,i); LZO_DO4(buf,i+4);
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
+
+LZO_PUBLIC(lzo_uint32)
+lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len)
+{
+    lzo_uint32 s1 = adler & 0xffff;
+    lzo_uint32 s2 = (adler >> 16) & 0xffff;
+    unsigned k;
+
+    if (buf == NULL)
+        return 1;
+
+    while (len > 0)
+    {
+        k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
+        len -= k;
+        if (k >= 16) do
+        {
+            LZO_DO16(buf,0);
+            buf += 16;
+            k -= 16;
+        } while (k >= 16);
+        if (k != 0) do
+        {
+            s1 += *buf++;
+            s2 += s1;
+        } while (--k > 0);
+        s1 %= LZO_BASE;
+        s2 %= LZO_BASE;
+    }
+    return (s2 << 16) | s1;
+}
+
+#undef LZO_DO1
+#undef LZO_DO2
+#undef LZO_DO4
+#undef LZO_DO8
+#undef LZO_DO16
+
+#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_STRING)
+#undef lzo_memcmp
+#undef lzo_memcpy
+#undef lzo_memmove
+#undef lzo_memset
+#if !defined(__LZO_MMODEL_HUGE)
+#  undef LZO_HAVE_MM_HUGE_PTR
+#endif
+#define lzo_hsize_t             lzo_uint
+#define lzo_hvoid_p             lzo_voidp
+#define lzo_hbyte_p             lzo_bytep
+#define LZOLIB_PUBLIC(r,f)      LZO_PUBLIC(r) f
+#define lzo_hmemcmp             lzo_memcmp
+#define lzo_hmemcpy             lzo_memcpy
+#define lzo_hmemmove            lzo_memmove
+#define lzo_hmemset             lzo_memset
+#define __LZOLIB_HMEMCPY_CH_INCLUDED 1
+#if !defined(LZOLIB_PUBLIC)
+#  define LZOLIB_PUBLIC(r,f)    r __LZOLIB_FUNCNAME(f)
+#endif
+LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP)
+    const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1;
+    const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2;
+    if __lzo_likely(len > 0) do
+    {
+        int d = *p1 - *p2;
+        if (d != 0)
+            return d;
+        p1++; p2++;
+    } while __lzo_likely(--len > 0);
+    return 0;
+#else
+    return memcmp(s1, s2, len);
+#endif
+}
+LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY)
+    lzo_hbyte_p p1 = (lzo_hbyte_p) dest;
+    const lzo_hbyte_p p2 = (const lzo_hbyte_p) src;
+    if (!(len > 0) || p1 == p2)
+        return dest;
+    do
+        *p1++ = *p2++;
+    while __lzo_likely(--len > 0);
+    return dest;
+#else
+    return memcpy(dest, src, len);
+#endif
+}
+LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE)
+    lzo_hbyte_p p1 = (lzo_hbyte_p) dest;
+    const lzo_hbyte_p p2 = (const lzo_hbyte_p) src;
+    if (!(len > 0) || p1 == p2)
+        return dest;
+    if (p1 < p2)
+    {
+        do
+            *p1++ = *p2++;
+        while __lzo_likely(--len > 0);
+    }
+    else
+    {
+        p1 += len;
+        p2 += len;
+        do
+            *--p1 = *--p2;
+        while __lzo_likely(--len > 0);
+    }
+    return dest;
+#else
+    return memmove(dest, src, len);
+#endif
+}
+LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET)
+    lzo_hbyte_p p = (lzo_hbyte_p) s;
+    if __lzo_likely(len > 0) do
+        *p++ = (unsigned char) c;
+    while __lzo_likely(--len > 0);
+    return s;
+#else
+    return memset(s, c, len);
+#endif
+}
+#undef LZOLIB_PUBLIC
+#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_INIT)
+
+#if !defined(__LZO_IN_MINILZO)
+
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+
+    ACCCHK_ASSERT_IS_SIGNED_T(lzo_int)
+    ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint)
+
+    ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32)
+    ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32)
+    ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0)
+    ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4)
+#if defined(LZO_UINT64_MAX)
+    ACCCHK_ASSERT(sizeof(lzo_uint64) == 8)
+    ACCCHK_ASSERT_IS_SIGNED_T(lzo_int64)
+    ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint64)
+#endif
+
+#if !defined(__LZO_UINTPTR_T_IS_POINTER)
+    ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t)
+#endif
+    ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
+
+    ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint)
+    ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32))
+    ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint))
+    ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint))
+
+#endif
+#undef ACCCHK_ASSERT
+
+#define WANT_lzo_bitops_clz32 1
+#define WANT_lzo_bitops_clz64 1
+#define WANT_lzo_bitops_ctz32 1
+#define WANT_lzo_bitops_ctz64 1
+
+#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400)))
+#include <intrin.h>
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0
+#pragma intrinsic(_BitScanReverse)
+static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v)
+{
+    unsigned long r;
+    (void) _BitScanReverse(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_clz32 lzo_bitops_clz32
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0
+#pragma intrinsic(_BitScanReverse64)
+static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v)
+{
+    unsigned long r;
+    (void) _BitScanReverse64(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_clz64 lzo_bitops_clz64
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#pragma intrinsic(_BitScanForward)
+static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v)
+{
+    unsigned long r;
+    (void) _BitScanForward(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_ctz32 lzo_bitops_ctz32
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#pragma intrinsic(_BitScanForward64)
+static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v)
+{
+    unsigned long r;
+    (void) _BitScanForward64(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_ctz64 lzo_bitops_ctz64
+#endif
+
+#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul))))
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32)
+#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v))
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v))
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v))
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32)
+#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v))
+#endif
+#endif
+
+#if 0
+#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off)))
+#else
+static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off)
+{
+    return (lzo_voidp) ((lzo_bytep) ptr + off);
+}
+#endif
+
+LZO_PUBLIC(int)
+_lzo_config_check(void)
+{
+    lzo_bool r = 1;
+    union {
+        lzo_xint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_xint))];
+#if defined(LZO_UNALIGNED_OK_8)
+        lzo_uint64 c[2];
+#endif
+        unsigned short x[2]; lzo_uint32 y[2]; lzo_uint z[2];
+    } u;
+    lzo_voidp p;
+
+    u.a[0] = u.a[1] = 0;
+    p = u2p(&u, 0);
+    r &= ((* (lzo_bytep) p) == 0);
+#if !defined(LZO_CFG_NO_CONFIG_CHECK)
+#if defined(LZO_ABI_BIG_ENDIAN)
+    u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128;
+    p = u2p(&u, 0);
+    r &= ((* (lzo_uintp) p) == 128);
+#endif
+#if defined(LZO_ABI_LITTLE_ENDIAN)
+    u.a[0] = u.a[1] = 0; u.b[0] = 128;
+    p = u2p(&u, 0);
+    r &= ((* (lzo_uintp) p) == 128);
+#endif
+#if defined(LZO_UNALIGNED_OK_2)
+    u.a[0] = u.a[1] = 0;
+    u.b[0] = 1; u.b[sizeof(unsigned short) + 1] = 2;
+    p = u2p(&u, 1);
+    r &= ((* (lzo_ushortp) p) == 0);
+#endif
+#if defined(LZO_UNALIGNED_OK_4)
+    u.a[0] = u.a[1] = 0;
+    u.b[0] = 3; u.b[sizeof(lzo_uint32) + 1] = 4;
+    p = u2p(&u, 1);
+    r &= ((* (lzo_uint32p) p) == 0);
+#endif
+#if defined(LZO_UNALIGNED_OK_8)
+    u.c[0] = u.c[1] = 0;
+    u.b[0] = 5; u.b[sizeof(lzo_uint64) + 1] = 6;
+    p = u2p(&u, 1);
+    r &= ((* (lzo_uint64p) p) == 0);
+#endif
+#if defined(lzo_bitops_clz32)
+    { unsigned i; lzo_uint32 v = 1;
+    for (i = 0; i < 32; i++, v <<= 1)
+        r &= lzo_bitops_clz32(v) == 31 - i;
+    }
+#endif
+#if defined(lzo_bitops_clz64)
+    { unsigned i; lzo_uint64 v = 1;
+    for (i = 0; i < 64; i++, v <<= 1)
+        r &= lzo_bitops_clz64(v) == 63 - i;
+    }
+#endif
+#if defined(lzo_bitops_ctz32)
+    { unsigned i; lzo_uint32 v = 1;
+    for (i = 0; i < 32; i++, v <<= 1)
+        r &= lzo_bitops_ctz32(v) == i;
+    }
+#endif
+#if defined(lzo_bitops_ctz64)
+    { unsigned i; lzo_uint64 v = 1;
+    for (i = 0; i < 64; i++, v <<= 1)
+        r &= lzo_bitops_ctz64(v) == i;
+    }
+#endif
+#endif
+
+    return r == 1 ? LZO_E_OK : LZO_E_ERROR;
+}
+
+LZO_PUBLIC(int)
+__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5,
+                          int s6, int s7, int s8, int s9)
+{
+    int r;
+
+#if defined(__LZO_IN_MINILZO)
+#elif (LZO_CC_MSC && ((_MSC_VER) < 700))
+#else
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+#define ACCCHK_ASSERT(expr)  LZO_COMPILE_TIME_ASSERT(expr)
+#endif
+#undef ACCCHK_ASSERT
+
+    if (v == 0)
+        return LZO_E_ERROR;
+
+    r = (s1 == -1 || s1 == (int) sizeof(short)) &&
+        (s2 == -1 || s2 == (int) sizeof(int)) &&
+        (s3 == -1 || s3 == (int) sizeof(long)) &&
+        (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) &&
+        (s5 == -1 || s5 == (int) sizeof(lzo_uint)) &&
+        (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) &&
+        (s7 == -1 || s7 == (int) sizeof(char *)) &&
+        (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) &&
+        (s9 == -1 || s9 == (int) sizeof(lzo_callback_t));
+    if (!r)
+        return LZO_E_ERROR;
+
+    r = _lzo_config_check();
+    if (r != LZO_E_OK)
+        return r;
+
+    return r;
+}
+
+#if !defined(__LZO_IN_MINILZO)
+
+#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD)
+
+#if 0
+BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment,
+                          WORD wHeapSize, LPSTR lpszCmdLine )
+#else
+int __far __pascal LibMain ( int a, short b, short c, long d )
+#endif
+{
+    LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d);
+    return 1;
+}
+
+#endif
+
+#endif
+
+#endif
+
+#define LZO1X           1
+#define LZO_EOF_CODE    1
+#define M2_MAX_OFFSET   0x0800
+
+#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS)
+
+#if 1 && defined(UA_GET32)
+#undef  LZO_DICT_USE_PTR
+#define LZO_DICT_USE_PTR 0
+#undef  lzo_dict_t
+#define lzo_dict_t unsigned short
+#endif
+
+#define LZO_NEED_DICT_H 1
+#ifndef D_BITS
+#define D_BITS          14
+#endif
+#define D_INDEX1(d,p)       d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
+#define D_INDEX2(d,p)       d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
+#if 1
+#define DINDEX(dv,p)        DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS)))
+#else
+#define DINDEX(dv,p)        DM((dv) + ((dv) >> (32-D_BITS)))
+#endif
+
+#ifndef __LZO_CONFIG1X_H
+#define __LZO_CONFIG1X_H 1
+
+#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
+#  define LZO1X 1
+#endif
+
+#if !defined(__LZO_IN_MINILZO)
+#include "lzo/lzo1x.h"
+#endif
+
+#ifndef LZO_EOF_CODE
+#define LZO_EOF_CODE 1
+#endif
+#undef LZO_DETERMINISTIC
+
+#define M1_MAX_OFFSET   0x0400
+#ifndef M2_MAX_OFFSET
+#define M2_MAX_OFFSET   0x0800
+#endif
+#define M3_MAX_OFFSET   0x4000
+#define M4_MAX_OFFSET   0xbfff
+
+#define MX_MAX_OFFSET   (M1_MAX_OFFSET + M2_MAX_OFFSET)
+
+#define M1_MIN_LEN      2
+#define M1_MAX_LEN      2
+#define M2_MIN_LEN      3
+#ifndef M2_MAX_LEN
+#define M2_MAX_LEN      8
+#endif
+#define M3_MIN_LEN      3
+#define M3_MAX_LEN      33
+#define M4_MIN_LEN      3
+#define M4_MAX_LEN      9
+
+#define M1_MARKER       0
+#define M2_MARKER       64
+#define M3_MARKER       32
+#define M4_MARKER       16
+
+#ifndef MIN_LOOKAHEAD
+#define MIN_LOOKAHEAD       (M2_MAX_LEN + 1)
+#endif
+
+#if defined(LZO_NEED_DICT_H)
+
+#ifndef LZO_HASH
+#define LZO_HASH            LZO_HASH_LZO_INCREMENTAL_B
+#endif
+#define DL_MIN_LEN          M2_MIN_LEN
+
+#ifndef __LZO_DICT_H
+#define __LZO_DICT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(D_BITS) && defined(DBITS)
+#  define D_BITS        DBITS
+#endif
+#if !defined(D_BITS)
+#  error "D_BITS is not defined"
+#endif
+#if (D_BITS < 16)
+#  define D_SIZE        LZO_SIZE(D_BITS)
+#  define D_MASK        LZO_MASK(D_BITS)
+#else
+#  define D_SIZE        LZO_USIZE(D_BITS)
+#  define D_MASK        LZO_UMASK(D_BITS)
+#endif
+#define D_HIGH          ((D_MASK >> 1) + 1)
+
+#if !defined(DD_BITS)
+#  define DD_BITS       0
+#endif
+#define DD_SIZE         LZO_SIZE(DD_BITS)
+#define DD_MASK         LZO_MASK(DD_BITS)
+
+#if !defined(DL_BITS)
+#  define DL_BITS       (D_BITS - DD_BITS)
+#endif
+#if (DL_BITS < 16)
+#  define DL_SIZE       LZO_SIZE(DL_BITS)
+#  define DL_MASK       LZO_MASK(DL_BITS)
+#else
+#  define DL_SIZE       LZO_USIZE(DL_BITS)
+#  define DL_MASK       LZO_UMASK(DL_BITS)
+#endif
+
+#if (D_BITS != DL_BITS + DD_BITS)
+#  error "D_BITS does not match"
+#endif
+#if (D_BITS < 6 || D_BITS > 18)
+#  error "invalid D_BITS"
+#endif
+#if (DL_BITS < 6 || DL_BITS > 20)
+#  error "invalid DL_BITS"
+#endif
+#if (DD_BITS < 0 || DD_BITS > 6)
+#  error "invalid DD_BITS"
+#endif
+
+#if !defined(DL_MIN_LEN)
+#  define DL_MIN_LEN    3
+#endif
+#if !defined(DL_SHIFT)
+#  define DL_SHIFT      ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN)
+#endif
+
+#define LZO_HASH_GZIP                   1
+#define LZO_HASH_GZIP_INCREMENTAL       2
+#define LZO_HASH_LZO_INCREMENTAL_A      3
+#define LZO_HASH_LZO_INCREMENTAL_B      4
+
+#if !defined(LZO_HASH)
+#  error "choose a hashing strategy"
+#endif
+
+#undef DM
+#undef DX
+
+#if (DL_MIN_LEN == 3)
+#  define _DV2_A(p,shift1,shift2) \
+        (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2])
+#  define _DV2_B(p,shift1,shift2) \
+        (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0])
+#  define _DV3_B(p,shift1,shift2,shift3) \
+        ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0])
+#elif (DL_MIN_LEN == 2)
+#  define _DV2_A(p,shift1,shift2) \
+        (( (lzo_xint)(p[0]) << shift1) ^ p[1])
+#  define _DV2_B(p,shift1,shift2) \
+        (( (lzo_xint)(p[1]) << shift1) ^ p[2])
+#else
+#  error "invalid DL_MIN_LEN"
+#endif
+#define _DV_A(p,shift)      _DV2_A(p,shift,shift)
+#define _DV_B(p,shift)      _DV2_B(p,shift,shift)
+#define DA2(p,s1,s2) \
+        (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0])
+#define DS2(p,s1,s2) \
+        (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0])
+#define DX2(p,s1,s2) \
+        (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0])
+#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0])
+#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0])
+#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0])
+#define DMS(v,s)        ((lzo_uint) (((v) & (D_MASK >> (s))) << (s)))
+#define DM(v)           DMS(v,0)
+
+#if (LZO_HASH == LZO_HASH_GZIP)
+#  define _DINDEX(dv,p)     (_DV_A((p),DL_SHIFT))
+
+#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL)
+#  define __LZO_HASH_INCREMENTAL 1
+#  define DVAL_FIRST(dv,p)  dv = _DV_A((p),DL_SHIFT)
+#  define DVAL_NEXT(dv,p)   dv = (((dv) << DL_SHIFT) ^ p[2])
+#  define _DINDEX(dv,p)     (dv)
+#  define DVAL_LOOKAHEAD    DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A)
+#  define __LZO_HASH_INCREMENTAL 1
+#  define DVAL_FIRST(dv,p)  dv = _DV_A((p),5)
+#  define DVAL_NEXT(dv,p) \
+                dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2])
+#  define _DINDEX(dv,p)     ((DMUL(0x9f5f,dv)) >> 5)
+#  define DVAL_LOOKAHEAD    DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B)
+#  define __LZO_HASH_INCREMENTAL 1
+#  define DVAL_FIRST(dv,p)  dv = _DV_B((p),5)
+#  define DVAL_NEXT(dv,p) \
+                dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5)))
+#  define _DINDEX(dv,p)     ((DMUL(0x9f5f,dv)) >> 5)
+#  define DVAL_LOOKAHEAD    DL_MIN_LEN
+
+#else
+#  error "choose a hashing strategy"
+#endif
+
+#ifndef DINDEX
+#define DINDEX(dv,p)        ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS)
+#endif
+#if !defined(DINDEX1) && defined(D_INDEX1)
+#define DINDEX1             D_INDEX1
+#endif
+#if !defined(DINDEX2) && defined(D_INDEX2)
+#define DINDEX2             D_INDEX2
+#endif
+
+#if !defined(__LZO_HASH_INCREMENTAL)
+#  define DVAL_FIRST(dv,p)  ((void) 0)
+#  define DVAL_NEXT(dv,p)   ((void) 0)
+#  define DVAL_LOOKAHEAD    0
+#endif
+
+#if !defined(DVAL_ASSERT)
+#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG)
+#if (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_LLVM)
+static void __attribute__((__unused__))
+#else
+static void
+#endif
+DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
+{
+    lzo_xint df;
+    DVAL_FIRST(df,(p));
+    assert(DINDEX(dv,p) == DINDEX(df,p));
+}
+#else
+#  define DVAL_ASSERT(dv,p) ((void) 0)
+#endif
+#endif
+
+#if (LZO_DICT_USE_PTR)
+#  define DENTRY(p,in)                          (p)
+#  define GINDEX(m_pos,m_off,dict,dindex,in)    m_pos = dict[dindex]
+#else
+#  define DENTRY(p,in)                          ((lzo_dict_t) pd(p, in))
+#  define GINDEX(m_pos,m_off,dict,dindex,in)    m_off = dict[dindex]
+#endif
+
+#if (DD_BITS == 0)
+
+#  define UPDATE_D(dict,drun,dv,p,in)       dict[ DINDEX(dv,p) ] = DENTRY(p,in)
+#  define UPDATE_I(dict,drun,index,p,in)    dict[index] = DENTRY(p,in)
+#  define UPDATE_P(ptr,drun,p,in)           (ptr)[0] = DENTRY(p,in)
+
+#else
+
+#  define UPDATE_D(dict,drun,dv,p,in)   \
+        dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+#  define UPDATE_I(dict,drun,index,p,in)    \
+        dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+#  define UPDATE_P(ptr,drun,p,in)   \
+        (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK
+
+#endif
+
+#if (LZO_DICT_USE_PTR)
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+        (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset)
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+    (BOUNDS_CHECKING_OFF_IN_EXPR(( \
+        m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \
+        PTR_LT(m_pos,in) || \
+        (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \
+         m_off > max_offset )))
+
+#else
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+        (m_off == 0 || \
+         ((m_off = pd(ip, in) - m_off) > max_offset) || \
+         (m_pos = (ip) - (m_off), 0) )
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+        (pd(ip, in) <= m_off || \
+         ((m_off = pd(ip, in) - m_off) > max_offset) || \
+         (m_pos = (ip) - (m_off), 0) )
+
+#endif
+
+#if (LZO_DETERMINISTIC)
+#  define LZO_CHECK_MPOS    LZO_CHECK_MPOS_DET
+#else
+#  define LZO_CHECK_MPOS    LZO_CHECK_MPOS_NON_DET
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
+
+#endif
+
+#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR)
+
+#ifndef DO_COMPRESS
+#define DO_COMPRESS     lzo1x_1_compress
+#endif
+
+#if 1 && defined(DO_COMPRESS) && !defined(do_compress)
+#  define do_compress       LZO_CPP_ECONCAT2(DO_COMPRESS,_core)
+#endif
+
+#if defined(UA_GET64) && (LZO_ABI_BIG_ENDIAN)
+#  define WANT_lzo_bitops_clz64 1
+#elif defined(UA_GET64) && (LZO_ABI_LITTLE_ENDIAN)
+#  define WANT_lzo_bitops_ctz64 1
+#elif defined(UA_GET32) && (LZO_ABI_BIG_ENDIAN)
+#  define WANT_lzo_bitops_clz32 1
+#elif defined(UA_GET32) && (LZO_ABI_LITTLE_ENDIAN)
+#  define WANT_lzo_bitops_ctz32 1
+#endif
+
+#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400)))
+#include <intrin.h>
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0
+#pragma intrinsic(_BitScanReverse)
+static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v)
+{
+    unsigned long r;
+    (void) _BitScanReverse(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_clz32 lzo_bitops_clz32
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0
+#pragma intrinsic(_BitScanReverse64)
+static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v)
+{
+    unsigned long r;
+    (void) _BitScanReverse64(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_clz64 lzo_bitops_clz64
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#pragma intrinsic(_BitScanForward)
+static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v)
+{
+    unsigned long r;
+    (void) _BitScanForward(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_ctz32 lzo_bitops_ctz32
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#pragma intrinsic(_BitScanForward64)
+static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v)
+{
+    unsigned long r;
+    (void) _BitScanForward64(&r, v);
+    return (unsigned) r;
+}
+#define lzo_bitops_ctz64 lzo_bitops_ctz64
+#endif
+
+#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul))))
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32)
+#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v))
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v))
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v))
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32)
+#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v))
+#endif
+#endif
+
+static __lzo_noinline lzo_uint
+do_compress ( const lzo_bytep in , lzo_uint  in_len,
+                    lzo_bytep out, lzo_uintp out_len,
+                    lzo_uint  ti,  lzo_voidp wrkmem)
+{
+    register const lzo_bytep ip;
+    lzo_bytep op;
+    const lzo_bytep const in_end = in + in_len;
+    const lzo_bytep const ip_end = in + in_len - 20;
+    const lzo_bytep ii;
+    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
+
+    op = out;
+    ip = in;
+    ii = ip;
+
+    ip += ti < 4 ? 4 - ti : 0;
+    for (;;)
+    {
+        const lzo_bytep m_pos;
+#if !(LZO_DETERMINISTIC)
+        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
+        lzo_uint m_len;
+        lzo_uint dindex;
+next:
+        if __lzo_unlikely(ip >= ip_end)
+            break;
+        DINDEX1(dindex,ip);
+        GINDEX(m_pos,m_off,dict,dindex,in);
+        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+            goto literal;
+#if 1
+        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+            goto try_match;
+        DINDEX2(dindex,ip);
+#endif
+        GINDEX(m_pos,m_off,dict,dindex,in);
+        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+            goto literal;
+        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+            goto try_match;
+        goto literal;
+
+try_match:
+#if defined(UA_GET32)
+        if (UA_GET32(m_pos) != UA_GET32(ip))
+#else
+        if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3])
+#endif
+        {
+literal:
+            UPDATE_I(dict,0,dindex,ip,in);
+            ip += 1 + ((ip - ii) >> 5);
+            continue;
+        }
+        UPDATE_I(dict,0,dindex,ip,in);
+#else
+        lzo_uint m_off;
+        lzo_uint m_len;
+        {
+        lzo_uint32 dv;
+        lzo_uint dindex;
+literal:
+        ip += 1 + ((ip - ii) >> 5);
+next:
+        if __lzo_unlikely(ip >= ip_end)
+            break;
+        dv = UA_GET32(ip);
+        dindex = DINDEX(dv,ip);
+        GINDEX(m_off,m_pos,in+dict,dindex,in);
+        UPDATE_I(dict,0,dindex,ip,in);
+        if __lzo_unlikely(dv != UA_GET32(m_pos))
+            goto literal;
+        }
+#endif
+
+        ii -= ti; ti = 0;
+        {
+        register lzo_uint t = pd(ip,ii);
+        if (t != 0)
+        {
+            if (t <= 3)
+            {
+                op[-2] |= LZO_BYTE(t);
+#if defined(UA_COPY32)
+                UA_COPY32(op, ii);
+                op += t;
+#else
+                { do *op++ = *ii++; while (--t > 0); }
+#endif
+            }
+#if defined(UA_COPY32) || defined(UA_COPY64)
+            else if (t <= 16)
+            {
+                *op++ = LZO_BYTE(t - 3);
+#if defined(UA_COPY64)
+                UA_COPY64(op, ii);
+                UA_COPY64(op+8, ii+8);
+#else
+                UA_COPY32(op, ii);
+                UA_COPY32(op+4, ii+4);
+                UA_COPY32(op+8, ii+8);
+                UA_COPY32(op+12, ii+12);
+#endif
+                op += t;
+            }
+#endif
+            else
+            {
+                if (t <= 18)
+                    *op++ = LZO_BYTE(t - 3);
+                else
+                {
+                    register lzo_uint tt = t - 18;
+                    *op++ = 0;
+                    while __lzo_unlikely(tt > 255)
+                    {
+                        tt -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+                        * (volatile unsigned char *) op++ = 0;
+#else
+                        *op++ = 0;
+#endif
+                    }
+                    assert(tt > 0);
+                    *op++ = LZO_BYTE(tt);
+                }
+#if defined(UA_COPY32) || defined(UA_COPY64)
+                do {
+#if defined(UA_COPY64)
+                    UA_COPY64(op, ii);
+                    UA_COPY64(op+8, ii+8);
+#else
+                    UA_COPY32(op, ii);
+                    UA_COPY32(op+4, ii+4);
+                    UA_COPY32(op+8, ii+8);
+                    UA_COPY32(op+12, ii+12);
+#endif
+                    op += 16; ii += 16; t -= 16;
+                } while (t >= 16); if (t > 0)
+#endif
+                { do *op++ = *ii++; while (--t > 0); }
+            }
+        }
+        }
+        m_len = 4;
+        {
+#if defined(UA_GET64)
+        lzo_uint64 v;
+        v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
+        if __lzo_unlikely(v == 0) {
+            do {
+                m_len += 8;
+                v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
+                if __lzo_unlikely(ip + m_len >= ip_end)
+                    goto m_len_done;
+            } while (v == 0);
+        }
+#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz64)
+        m_len += lzo_bitops_clz64(v) / CHAR_BIT;
+#elif (LZO_ABI_BIG_ENDIAN)
+        if ((v >> (64 - CHAR_BIT)) == 0) do {
+            v <<= CHAR_BIT;
+            m_len += 1;
+        } while ((v >> (64 - CHAR_BIT)) == 0);
+#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz64)
+        m_len += lzo_bitops_ctz64(v) / CHAR_BIT;
+#elif (LZO_ABI_LITTLE_ENDIAN)
+        if ((v & UCHAR_MAX) == 0) do {
+            v >>= CHAR_BIT;
+            m_len += 1;
+        } while ((v & UCHAR_MAX) == 0);
+#else
+        if (ip[m_len] == m_pos[m_len]) do {
+            m_len += 1;
+        } while (ip[m_len] == m_pos[m_len]);
+#endif
+#elif defined(UA_GET32)
+        lzo_uint32 v;
+        v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
+        if __lzo_unlikely(v == 0) {
+            do {
+                m_len += 4;
+                v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
+                if __lzo_unlikely(ip + m_len >= ip_end)
+                    goto m_len_done;
+            } while (v == 0);
+        }
+#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz32)
+        m_len += lzo_bitops_clz32(v) / CHAR_BIT;
+#elif (LZO_ABI_BIG_ENDIAN)
+        if ((v >> (32 - CHAR_BIT)) == 0) do {
+            v <<= CHAR_BIT;
+            m_len += 1;
+        } while ((v >> (32 - CHAR_BIT)) == 0);
+#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz32)
+        m_len += lzo_bitops_ctz32(v) / CHAR_BIT;
+#elif (LZO_ABI_LITTLE_ENDIAN)
+        if ((v & UCHAR_MAX) == 0) do {
+            v >>= CHAR_BIT;
+            m_len += 1;
+        } while ((v & UCHAR_MAX) == 0);
+#else
+        if (ip[m_len] == m_pos[m_len]) do {
+            m_len += 1;
+        } while (ip[m_len] == m_pos[m_len]);
+#endif
+#else
+        if __lzo_unlikely(ip[m_len] == m_pos[m_len]) {
+            do {
+                m_len += 1;
+                if __lzo_unlikely(ip + m_len >= ip_end)
+                    goto m_len_done;
+            } while (ip[m_len] == m_pos[m_len]);
+        }
+#endif
+        }
+m_len_done:
+        m_off = pd(ip,m_pos);
+        ip += m_len;
+        ii = ip;
+        if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
+        {
+            m_off -= 1;
+#if defined(LZO1X)
+            *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
+            *op++ = LZO_BYTE(m_off >> 3);
+#elif defined(LZO1Y)
+            *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
+            *op++ = LZO_BYTE(m_off >> 2);
+#endif
+        }
+        else if (m_off <= M3_MAX_OFFSET)
+        {
+            m_off -= 1;
+            if (m_len <= M3_MAX_LEN)
+                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+            else
+            {
+                m_len -= M3_MAX_LEN;
+                *op++ = M3_MARKER | 0;
+                while __lzo_unlikely(m_len > 255)
+                {
+                    m_len -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+                    * (volatile unsigned char *) op++ = 0;
+#else
+                    *op++ = 0;
+#endif
+                }
+                *op++ = LZO_BYTE(m_len);
+            }
+            *op++ = LZO_BYTE(m_off << 2);
+            *op++ = LZO_BYTE(m_off >> 6);
+        }
+        else
+        {
+            m_off -= 0x4000;
+            if (m_len <= M4_MAX_LEN)
+                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2));
+            else
+            {
+                m_len -= M4_MAX_LEN;
+                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8));
+                while __lzo_unlikely(m_len > 255)
+                {
+                    m_len -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+                    * (volatile unsigned char *) op++ = 0;
+#else
+                    *op++ = 0;
+#endif
+                }
+                *op++ = LZO_BYTE(m_len);
+            }
+            *op++ = LZO_BYTE(m_off << 2);
+            *op++ = LZO_BYTE(m_off >> 6);
+        }
+        goto next;
+    }
+
+    *out_len = pd(op, out);
+    return pd(in_end,ii-ti);
+}
+
+LZO_PUBLIC(int)
+DO_COMPRESS      ( const lzo_bytep in , lzo_uint  in_len,
+                         lzo_bytep out, lzo_uintp out_len,
+                         lzo_voidp wrkmem )
+{
+    const lzo_bytep ip = in;
+    lzo_bytep op = out;
+    lzo_uint l = in_len;
+    lzo_uint t = 0;
+
+    while (l > 20)
+    {
+        lzo_uint ll = l;
+        lzo_uintptr_t ll_end;
+#if 0 || (LZO_DETERMINISTIC)
+        ll = LZO_MIN(ll, 49152);
+#endif
+        ll_end = (lzo_uintptr_t)ip + ll;
+        if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll)
+            break;
+#if (LZO_DETERMINISTIC)
+        lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t));
+#endif
+        t = do_compress(ip,ll,op,out_len,t,wrkmem);
+        ip += ll;
+        op += *out_len;
+        l  -= ll;
+    }
+    t += l;
+
+    if (t > 0)
+    {
+        const lzo_bytep ii = in + in_len - t;
+
+        if (op == out && t <= 238)
+            *op++ = LZO_BYTE(17 + t);
+        else if (t <= 3)
+            op[-2] |= LZO_BYTE(t);
+        else if (t <= 18)
+            *op++ = LZO_BYTE(t - 3);
+        else
+        {
+            lzo_uint tt = t - 18;
+
+            *op++ = 0;
+            while (tt > 255)
+            {
+                tt -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+
+                * (volatile unsigned char *) op++ = 0;
+#else
+                *op++ = 0;
+#endif
+            }
+            assert(tt > 0);
+            *op++ = LZO_BYTE(tt);
+        }
+        do *op++ = *ii++; while (--t > 0);
+    }
+
+    *op++ = M4_MARKER | 1;
+    *op++ = 0;
+    *op++ = 0;
+
+    *out_len = pd(op, out);
+    return LZO_E_OK;
+}
+
+#endif
+
+#undef do_compress
+#undef DO_COMPRESS
+#undef LZO_HASH
+
+#undef LZO_TEST_OVERRUN
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS       lzo1x_decompress
+
+#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS)
+
+#if defined(LZO_TEST_OVERRUN)
+#  if !defined(LZO_TEST_OVERRUN_INPUT)
+#    define LZO_TEST_OVERRUN_INPUT       2
+#  endif
+#  if !defined(LZO_TEST_OVERRUN_OUTPUT)
+#    define LZO_TEST_OVERRUN_OUTPUT      2
+#  endif
+#  if !defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+#    define LZO_TEST_OVERRUN_LOOKBEHIND  1
+#  endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LB
+#undef TEST_LBO
+#undef NEED_IP
+#undef NEED_OP
+#undef HAVE_TEST_IP
+#undef HAVE_TEST_OP
+#undef HAVE_NEED_IP
+#undef HAVE_NEED_OP
+#undef HAVE_ANY_IP
+#undef HAVE_ANY_OP
+
+#if defined(LZO_TEST_OVERRUN_INPUT)
+#  if (LZO_TEST_OVERRUN_INPUT >= 1)
+#    define TEST_IP             (ip < ip_end)
+#  endif
+#  if (LZO_TEST_OVERRUN_INPUT >= 2)
+#    define NEED_IP(x) \
+            if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x))  goto input_overrun
+#  endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_OUTPUT)
+#  if (LZO_TEST_OVERRUN_OUTPUT >= 1)
+#    define TEST_OP             (op <= op_end)
+#  endif
+#  if (LZO_TEST_OVERRUN_OUTPUT >= 2)
+#    undef TEST_OP
+#    define NEED_OP(x) \
+            if ((lzo_uint)(op_end - op) < (lzo_uint)(x))  goto output_overrun
+#  endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+#  define TEST_LB(m_pos)        if (m_pos < out || m_pos >= op) goto lookbehind_overrun
+#  define TEST_LBO(m_pos,o)     if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
+#else
+#  define TEST_LB(m_pos)        ((void) 0)
+#  define TEST_LBO(m_pos,o)     ((void) 0)
+#endif
+
+#if !defined(LZO_EOF_CODE) && !defined(TEST_IP)
+#  define TEST_IP               (ip < ip_end)
+#endif
+
+#if defined(TEST_IP)
+#  define HAVE_TEST_IP 1
+#else
+#  define TEST_IP               1
+#endif
+#if defined(TEST_OP)
+#  define HAVE_TEST_OP 1
+#else
+#  define TEST_OP               1
+#endif
+
+#if defined(NEED_IP)
+#  define HAVE_NEED_IP 1
+#else
+#  define NEED_IP(x)            ((void) 0)
+#endif
+#if defined(NEED_OP)
+#  define HAVE_NEED_OP 1
+#else
+#  define NEED_OP(x)            ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+#  define HAVE_ANY_IP 1
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+#  define HAVE_ANY_OP 1
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS  ( const lzo_bytep in , lzo_uint  in_len,
+                       lzo_bytep out, lzo_uintp out_len,
+                       lzo_voidp wrkmem )
+#endif
+{
+    register lzo_bytep op;
+    register const lzo_bytep ip;
+    register lzo_uint t;
+#if defined(COPY_DICT)
+    lzo_uint m_off;
+    const lzo_bytep dict_end;
+#else
+    register const lzo_bytep m_pos;
+#endif
+
+    const lzo_bytep const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+    lzo_bytep const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+    lzo_uint last_m_off = 0;
+#endif
+
+    LZO_UNUSED(wrkmem);
+
+#if defined(COPY_DICT)
+    if (dict)
+    {
+        if (dict_len > M4_MAX_OFFSET)
+        {
+            dict += dict_len - M4_MAX_OFFSET;
+            dict_len = M4_MAX_OFFSET;
+        }
+        dict_end = dict + dict_len;
+    }
+    else
+    {
+        dict_len = 0;
+        dict_end = NULL;
+    }
+#endif
+
+    *out_len = 0;
+
+    op = out;
+    ip = in;
+
+    if (*ip > 17)
+    {
+        t = *ip++ - 17;
+        if (t < 4)
+            goto match_next;
+        assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+        do *op++ = *ip++; while (--t > 0);
+        goto first_literal_run;
+    }
+
+    while (TEST_IP && TEST_OP)
+    {
+        t = *ip++;
+        if (t >= 16)
+            goto match;
+        if (t == 0)
+        {
+            NEED_IP(1);
+            while (*ip == 0)
+            {
+                t += 255;
+                ip++;
+                NEED_IP(1);
+            }
+            t += 15 + *ip++;
+        }
+        assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+        t += 3;
+        if (t >= 8) do
+        {
+            UA_COPY64(op,ip);
+            op += 8; ip += 8; t -= 8;
+        } while (t >= 8);
+        if (t >= 4)
+        {
+            UA_COPY32(op,ip);
+            op += 4; ip += 4; t -= 4;
+        }
+        if (t > 0)
+        {
+            *op++ = *ip++;
+            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+        }
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+        if (PTR_ALIGNED2_4(op,ip))
+        {
+#endif
+        UA_COPY32(op,ip);
+        op += 4; ip += 4;
+        if (--t > 0)
+        {
+            if (t >= 4)
+            {
+                do {
+                    UA_COPY32(op,ip);
+                    op += 4; ip += 4; t -= 4;
+                } while (t >= 4);
+                if (t > 0) do *op++ = *ip++; while (--t > 0);
+            }
+            else
+                do *op++ = *ip++; while (--t > 0);
+        }
+#if !defined(LZO_UNALIGNED_OK_4)
+        }
+        else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
+        {
+            *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+            do *op++ = *ip++; while (--t > 0);
+        }
+#endif
+
+first_literal_run:
+
+        t = *ip++;
+        if (t >= 16)
+            goto match;
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+        m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+        last_m_off = m_off;
+#else
+        m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
+#endif
+        NEED_OP(3);
+        t = 3; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+        m_pos = op - t;
+        last_m_off = t;
+#else
+        m_pos = op - (1 + M2_MAX_OFFSET);
+        m_pos -= t >> 2;
+        m_pos -= *ip++ << 2;
+#endif
+        TEST_LB(m_pos); NEED_OP(3);
+        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+        goto match_done;
+
+        do {
+match:
+            if (t >= 64)
+            {
+#if defined(COPY_DICT)
+#if defined(LZO1X)
+                m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
+                t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+                m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
+                t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+                m_off = t & 0x1f;
+                if (m_off >= 0x1c)
+                    m_off = last_m_off;
+                else
+                {
+                    m_off = 1 + (m_off << 6) + (*ip++ >> 2);
+                    last_m_off = m_off;
+                }
+                t = (t >> 5) - 1;
+#endif
+#else
+#if defined(LZO1X)
+                m_pos = op - 1;
+                m_pos -= (t >> 2) & 7;
+                m_pos -= *ip++ << 3;
+                t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+                m_pos = op - 1;
+                m_pos -= (t >> 2) & 3;
+                m_pos -= *ip++ << 2;
+                t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+                {
+                    lzo_uint off = t & 0x1f;
+                    m_pos = op;
+                    if (off >= 0x1c)
+                    {
+                        assert(last_m_off > 0);
+                        m_pos -= last_m_off;
+                    }
+                    else
+                    {
+                        off = 1 + (off << 6) + (*ip++ >> 2);
+                        m_pos -= off;
+                        last_m_off = off;
+                    }
+                }
+                t = (t >> 5) - 1;
+#endif
+                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+                goto copy_match;
+#endif
+            }
+            else if (t >= 32)
+            {
+                t &= 31;
+                if (t == 0)
+                {
+                    NEED_IP(1);
+                    while (*ip == 0)
+                    {
+                        t += 255;
+                        ip++;
+                        NEED_IP(1);
+                    }
+                    t += 31 + *ip++;
+                }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+                m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+                last_m_off = m_off;
+#else
+                m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#else
+#if defined(LZO1Z)
+                {
+                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+                    m_pos = op - off;
+                    last_m_off = off;
+                }
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+                m_pos = op - 1;
+                m_pos -= UA_GET16(ip) >> 2;
+#else
+                m_pos = op - 1;
+                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#endif
+                ip += 2;
+            }
+            else if (t >= 16)
+            {
+#if defined(COPY_DICT)
+                m_off = (t & 8) << 11;
+#else
+                m_pos = op;
+                m_pos -= (t & 8) << 11;
+#endif
+                t &= 7;
+                if (t == 0)
+                {
+                    NEED_IP(1);
+                    while (*ip == 0)
+                    {
+                        t += 255;
+                        ip++;
+                        NEED_IP(1);
+                    }
+                    t += 7 + *ip++;
+                }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+                m_off += (ip[0] << 6) + (ip[1] >> 2);
+#else
+                m_off += (ip[0] >> 2) + (ip[1] << 6);
+#endif
+                ip += 2;
+                if (m_off == 0)
+                    goto eof_found;
+                m_off += 0x4000;
+#if defined(LZO1Z)
+                last_m_off = m_off;
+#endif
+#else
+#if defined(LZO1Z)
+                m_pos -= (ip[0] << 6) + (ip[1] >> 2);
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+                m_pos -= UA_GET16(ip) >> 2;
+#else
+                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+                ip += 2;
+                if (m_pos == op)
+                    goto eof_found;
+                m_pos -= 0x4000;
+#if defined(LZO1Z)
+                last_m_off = pd((const lzo_bytep)op, m_pos);
+#endif
+#endif
+            }
+            else
+            {
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+                m_off = 1 + (t << 6) + (*ip++ >> 2);
+                last_m_off = m_off;
+#else
+                m_off = 1 + (t >> 2) + (*ip++ << 2);
+#endif
+                NEED_OP(2);
+                t = 2; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+                t = 1 + (t << 6) + (*ip++ >> 2);
+                m_pos = op - t;
+                last_m_off = t;
+#else
+                m_pos = op - 1;
+                m_pos -= t >> 2;
+                m_pos -= *ip++ << 2;
+#endif
+                TEST_LB(m_pos); NEED_OP(2);
+                *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+                goto match_done;
+            }
+
+#if defined(COPY_DICT)
+
+            NEED_OP(t+3-1);
+            t += 3-1; COPY_DICT(t,m_off)
+
+#else
+
+            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+            if (op - m_pos >= 8)
+            {
+                t += (3 - 1);
+                if (t >= 8) do
+                {
+                    UA_COPY64(op,m_pos);
+                    op += 8; m_pos += 8; t -= 8;
+                } while (t >= 8);
+                if (t >= 4)
+                {
+                    UA_COPY32(op,m_pos);
+                    op += 4; m_pos += 4; t -= 4;
+                }
+                if (t > 0)
+                {
+                    *op++ = m_pos[0];
+                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
+                }
+            }
+            else
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+            if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
+            {
+                assert((op - m_pos) >= 4);
+#else
+            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
+            {
+#endif
+                UA_COPY32(op,m_pos);
+                op += 4; m_pos += 4; t -= 4 - (3 - 1);
+                do {
+                    UA_COPY32(op,m_pos);
+                    op += 4; m_pos += 4; t -= 4;
+                } while (t >= 4);
+                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
+            }
+            else
+#endif
+            {
+copy_match:
+                *op++ = *m_pos++; *op++ = *m_pos++;
+                do *op++ = *m_pos++; while (--t > 0);
+            }
+
+#endif
+
+match_done:
+#if defined(LZO1Z)
+            t = ip[-1] & 3;
+#else
+            t = ip[-2] & 3;
+#endif
+            if (t == 0)
+                break;
+
+match_next:
+            assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
+#if 0
+            do *op++ = *ip++; while (--t > 0);
+#else
+            *op++ = *ip++;
+            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+#endif
+            t = *ip++;
+        } while (TEST_IP && TEST_OP);
+    }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+    *out_len = pd(op, out);
+    return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+    assert(t == 1);
+    *out_len = pd(op, out);
+    return (ip == ip_end ? LZO_E_OK :
+           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+
+#if defined(HAVE_NEED_IP)
+input_overrun:
+    *out_len = pd(op, out);
+    return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+    *out_len = pd(op, out);
+    return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+    *out_len = pd(op, out);
+    return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+#endif
+
+#define LZO_TEST_OVERRUN 1
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS       lzo1x_decompress_safe
+
+#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE)
+
+#if defined(LZO_TEST_OVERRUN)
+#  if !defined(LZO_TEST_OVERRUN_INPUT)
+#    define LZO_TEST_OVERRUN_INPUT       2
+#  endif
+#  if !defined(LZO_TEST_OVERRUN_OUTPUT)
+#    define LZO_TEST_OVERRUN_OUTPUT      2
+#  endif
+#  if !defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+#    define LZO_TEST_OVERRUN_LOOKBEHIND  1
+#  endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LB
+#undef TEST_LBO
+#undef NEED_IP
+#undef NEED_OP
+#undef HAVE_TEST_IP
+#undef HAVE_TEST_OP
+#undef HAVE_NEED_IP
+#undef HAVE_NEED_OP
+#undef HAVE_ANY_IP
+#undef HAVE_ANY_OP
+
+#if defined(LZO_TEST_OVERRUN_INPUT)
+#  if (LZO_TEST_OVERRUN_INPUT >= 1)
+#    define TEST_IP             (ip < ip_end)
+#  endif
+#  if (LZO_TEST_OVERRUN_INPUT >= 2)
+#    define NEED_IP(x) \
+            if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x))  goto input_overrun
+#  endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_OUTPUT)
+#  if (LZO_TEST_OVERRUN_OUTPUT >= 1)
+#    define TEST_OP             (op <= op_end)
+#  endif
+#  if (LZO_TEST_OVERRUN_OUTPUT >= 2)
+#    undef TEST_OP
+#    define NEED_OP(x) \
+            if ((lzo_uint)(op_end - op) < (lzo_uint)(x))  goto output_overrun
+#  endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+#  define TEST_LB(m_pos)        if (m_pos < out || m_pos >= op) goto lookbehind_overrun
+#  define TEST_LBO(m_pos,o)     if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
+#else
+#  define TEST_LB(m_pos)        ((void) 0)
+#  define TEST_LBO(m_pos,o)     ((void) 0)
+#endif
+
+#if !defined(LZO_EOF_CODE) && !defined(TEST_IP)
+#  define TEST_IP               (ip < ip_end)
+#endif
+
+#if defined(TEST_IP)
+#  define HAVE_TEST_IP 1
+#else
+#  define TEST_IP               1
+#endif
+#if defined(TEST_OP)
+#  define HAVE_TEST_OP 1
+#else
+#  define TEST_OP               1
+#endif
+
+#if defined(NEED_IP)
+#  define HAVE_NEED_IP 1
+#else
+#  define NEED_IP(x)            ((void) 0)
+#endif
+#if defined(NEED_OP)
+#  define HAVE_NEED_OP 1
+#else
+#  define NEED_OP(x)            ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+#  define HAVE_ANY_IP 1
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+#  define HAVE_ANY_OP 1
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS  ( const lzo_bytep in , lzo_uint  in_len,
+                       lzo_bytep out, lzo_uintp out_len,
+                       lzo_voidp wrkmem )
+#endif
+{
+    register lzo_bytep op;
+    register const lzo_bytep ip;
+    register lzo_uint t;
+#if defined(COPY_DICT)
+    lzo_uint m_off;
+    const lzo_bytep dict_end;
+#else
+    register const lzo_bytep m_pos;
+#endif
+
+    const lzo_bytep const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+    lzo_bytep const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+    lzo_uint last_m_off = 0;
+#endif
+
+    LZO_UNUSED(wrkmem);
+
+#if defined(COPY_DICT)
+    if (dict)
+    {
+        if (dict_len > M4_MAX_OFFSET)
+        {
+            dict += dict_len - M4_MAX_OFFSET;
+            dict_len = M4_MAX_OFFSET;
+        }
+        dict_end = dict + dict_len;
+    }
+    else
+    {
+        dict_len = 0;
+        dict_end = NULL;
+    }
+#endif
+
+    *out_len = 0;
+
+    op = out;
+    ip = in;
+
+    if (*ip > 17)
+    {
+        t = *ip++ - 17;
+        if (t < 4)
+            goto match_next;
+        assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+        do *op++ = *ip++; while (--t > 0);
+        goto first_literal_run;
+    }
+
+    while (TEST_IP && TEST_OP)
+    {
+        t = *ip++;
+        if (t >= 16)
+            goto match;
+        if (t == 0)
+        {
+            NEED_IP(1);
+            while (*ip == 0)
+            {
+                t += 255;
+                ip++;
+                NEED_IP(1);
+            }
+            t += 15 + *ip++;
+        }
+        assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+        t += 3;
+        if (t >= 8) do
+        {
+            UA_COPY64(op,ip);
+            op += 8; ip += 8; t -= 8;
+        } while (t >= 8);
+        if (t >= 4)
+        {
+            UA_COPY32(op,ip);
+            op += 4; ip += 4; t -= 4;
+        }
+        if (t > 0)
+        {
+            *op++ = *ip++;
+            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+        }
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+        if (PTR_ALIGNED2_4(op,ip))
+        {
+#endif
+        UA_COPY32(op,ip);
+        op += 4; ip += 4;
+        if (--t > 0)
+        {
+            if (t >= 4)
+            {
+                do {
+                    UA_COPY32(op,ip);
+                    op += 4; ip += 4; t -= 4;
+                } while (t >= 4);
+                if (t > 0) do *op++ = *ip++; while (--t > 0);
+            }
+            else
+                do *op++ = *ip++; while (--t > 0);
+        }
+#if !defined(LZO_UNALIGNED_OK_4)
+        }
+        else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
+        {
+            *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+            do *op++ = *ip++; while (--t > 0);
+        }
+#endif
+
+first_literal_run:
+
+        t = *ip++;
+        if (t >= 16)
+            goto match;
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+        m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+        last_m_off = m_off;
+#else
+        m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
+#endif
+        NEED_OP(3);
+        t = 3; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+        t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+        m_pos = op - t;
+        last_m_off = t;
+#else
+        m_pos = op - (1 + M2_MAX_OFFSET);
+        m_pos -= t >> 2;
+        m_pos -= *ip++ << 2;
+#endif
+        TEST_LB(m_pos); NEED_OP(3);
+        *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+        goto match_done;
+
+        do {
+match:
+            if (t >= 64)
+            {
+#if defined(COPY_DICT)
+#if defined(LZO1X)
+                m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
+                t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+                m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
+                t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+                m_off = t & 0x1f;
+                if (m_off >= 0x1c)
+                    m_off = last_m_off;
+                else
+                {
+                    m_off = 1 + (m_off << 6) + (*ip++ >> 2);
+                    last_m_off = m_off;
+                }
+                t = (t >> 5) - 1;
+#endif
+#else
+#if defined(LZO1X)
+                m_pos = op - 1;
+                m_pos -= (t >> 2) & 7;
+                m_pos -= *ip++ << 3;
+                t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+                m_pos = op - 1;
+                m_pos -= (t >> 2) & 3;
+                m_pos -= *ip++ << 2;
+                t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+                {
+                    lzo_uint off = t & 0x1f;
+                    m_pos = op;
+                    if (off >= 0x1c)
+                    {
+                        assert(last_m_off > 0);
+                        m_pos -= last_m_off;
+                    }
+                    else
+                    {
+                        off = 1 + (off << 6) + (*ip++ >> 2);
+                        m_pos -= off;
+                        last_m_off = off;
+                    }
+                }
+                t = (t >> 5) - 1;
+#endif
+                TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+                goto copy_match;
+#endif
+            }
+            else if (t >= 32)
+            {
+                t &= 31;
+                if (t == 0)
+                {
+                    NEED_IP(1);
+                    while (*ip == 0)
+                    {
+                        t += 255;
+                        ip++;
+                        NEED_IP(1);
+                    }
+                    t += 31 + *ip++;
+                }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+                m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+                last_m_off = m_off;
+#else
+                m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#else
+#if defined(LZO1Z)
+                {
+                    lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+                    m_pos = op - off;
+                    last_m_off = off;
+                }
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+                m_pos = op - 1;
+                m_pos -= UA_GET16(ip) >> 2;
+#else
+                m_pos = op - 1;
+                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#endif
+                ip += 2;
+            }
+            else if (t >= 16)
+            {
+#if defined(COPY_DICT)
+                m_off = (t & 8) << 11;
+#else
+                m_pos = op;
+                m_pos -= (t & 8) << 11;
+#endif
+                t &= 7;
+                if (t == 0)
+                {
+                    NEED_IP(1);
+                    while (*ip == 0)
+                    {
+                        t += 255;
+                        ip++;
+                        NEED_IP(1);
+                    }
+                    t += 7 + *ip++;
+                }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+                m_off += (ip[0] << 6) + (ip[1] >> 2);
+#else
+                m_off += (ip[0] >> 2) + (ip[1] << 6);
+#endif
+                ip += 2;
+                if (m_off == 0)
+                    goto eof_found;
+                m_off += 0x4000;
+#if defined(LZO1Z)
+                last_m_off = m_off;
+#endif
+#else
+#if defined(LZO1Z)
+                m_pos -= (ip[0] << 6) + (ip[1] >> 2);
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+                m_pos -= UA_GET16(ip) >> 2;
+#else
+                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+                ip += 2;
+                if (m_pos == op)
+                    goto eof_found;
+                m_pos -= 0x4000;
+#if defined(LZO1Z)
+                last_m_off = pd((const lzo_bytep)op, m_pos);
+#endif
+#endif
+            }
+            else
+            {
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+                m_off = 1 + (t << 6) + (*ip++ >> 2);
+                last_m_off = m_off;
+#else
+                m_off = 1 + (t >> 2) + (*ip++ << 2);
+#endif
+                NEED_OP(2);
+                t = 2; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+                t = 1 + (t << 6) + (*ip++ >> 2);
+                m_pos = op - t;
+                last_m_off = t;
+#else
+                m_pos = op - 1;
+                m_pos -= t >> 2;
+                m_pos -= *ip++ << 2;
+#endif
+                TEST_LB(m_pos); NEED_OP(2);
+                *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+                goto match_done;
+            }
+
+#if defined(COPY_DICT)
+
+            NEED_OP(t+3-1);
+            t += 3-1; COPY_DICT(t,m_off)
+
+#else
+
+            TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+            if (op - m_pos >= 8)
+            {
+                t += (3 - 1);
+                if (t >= 8) do
+                {
+                    UA_COPY64(op,m_pos);
+                    op += 8; m_pos += 8; t -= 8;
+                } while (t >= 8);
+                if (t >= 4)
+                {
+                    UA_COPY32(op,m_pos);
+                    op += 4; m_pos += 4; t -= 4;
+                }
+                if (t > 0)
+                {
+                    *op++ = m_pos[0];
+                    if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
+                }
+            }
+            else
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+            if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
+            {
+                assert((op - m_pos) >= 4);
+#else
+            if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
+            {
+#endif
+                UA_COPY32(op,m_pos);
+                op += 4; m_pos += 4; t -= 4 - (3 - 1);
+                do {
+                    UA_COPY32(op,m_pos);
+                    op += 4; m_pos += 4; t -= 4;
+                } while (t >= 4);
+                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
+            }
+            else
+#endif
+            {
+copy_match:
+                *op++ = *m_pos++; *op++ = *m_pos++;
+                do *op++ = *m_pos++; while (--t > 0);
+            }
+
+#endif
+
+match_done:
+#if defined(LZO1Z)
+            t = ip[-1] & 3;
+#else
+            t = ip[-2] & 3;
+#endif
+            if (t == 0)
+                break;
+
+match_next:
+            assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
+#if 0
+            do *op++ = *ip++; while (--t > 0);
+#else
+            *op++ = *ip++;
+            if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+#endif
+            t = *ip++;
+        } while (TEST_IP && TEST_OP);
+    }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+    *out_len = pd(op, out);
+    return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+    assert(t == 1);
+    *out_len = pd(op, out);
+    return (ip == ip_end ? LZO_E_OK :
+           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+
+#if defined(HAVE_NEED_IP)
+input_overrun:
+    *out_len = pd(op, out);
+    return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+    *out_len = pd(op, out);
+    return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+    *out_len = pd(op, out);
+    return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+#endif
+
+/***** End of minilzo.c *****/
+
diff --git a/coregrind/m_debuginfo/minilzo.h b/coregrind/m_debuginfo/minilzo.h
new file mode 100644
index 0000000..4c7b237
--- /dev/null
+++ b/coregrind/m_debuginfo/minilzo.h
@@ -0,0 +1,109 @@
+/* minilzo.h -- mini subset of the LZO real-time data compression library
+
+   This file is part of the LZO real-time data compression library.
+
+   Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+   All Rights Reserved.
+
+   The LZO library 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; either version 2 of
+   the License, or (at your option) any later version.
+
+   The LZO library 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 the LZO library; see the file COPYING.
+   If not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+   Markus F.X.J. Oberhumer
+   <markus@oberhumer.com>
+   http://www.oberhumer.com/opensource/lzo/
+ */
+
+/*
+ * NOTE:
+ *   the full LZO package can be found at
+ *   http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __MINILZO_H
+#define __MINILZO_H 1
+
+#define MINILZO_VERSION         0x2060
+
+#ifdef __LZOCONF_H
+#  error "you cannot use both LZO and miniLZO"
+#endif
+
+#undef LZO_HAVE_CONFIG_H
+#include "lzoconf.h"
+
+#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
+#  error "version mismatch in header files"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1X_MEM_COMPRESS      LZO1X_1_MEM_COMPRESS
+#define LZO1X_1_MEM_COMPRESS    ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1X_MEM_DECOMPRESS    (0)
+
+
+/* compression */
+LZO_EXTERN(int)
+lzo1x_1_compress        ( const lzo_bytep src, lzo_uint  src_len,
+                                lzo_bytep dst, lzo_uintp dst_len,
+                                lzo_voidp wrkmem );
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1x_decompress        ( const lzo_bytep src, lzo_uint  src_len,
+                                lzo_bytep dst, lzo_uintp dst_len,
+                                lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1x_decompress_safe   ( const lzo_bytep src, lzo_uint  src_len,
+                                lzo_bytep dst, lzo_uintp dst_len,
+                                lzo_voidp wrkmem /* NOT USED */ );
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
diff --git a/coregrind/m_debuginfo/priv_image.h b/coregrind/m_debuginfo/priv_image.h
new file mode 100644
index 0000000..083f079
--- /dev/null
+++ b/coregrind/m_debuginfo/priv_image.h
@@ -0,0 +1,346 @@
+
+/*--------------------------------------------------------------------*/
+/*--- An abstraction that provides a file-reading mechanism.       ---*/
+/*---                                                 priv_image.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2013-2013 Mozilla Foundation
+
+   This program 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; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Julian Seward <jseward@acm.org> */
+
+
+/*------------------------------------------------------------*/
+/*--- DiImage -- abstract images                           ---*/
+/*------------------------------------------------------------*/
+
+/* The basic type, containing an abstractified memory area that can be
+   read from.  This is an abstract type since there can be more than
+   one implementation of it. */
+
+/* abstract */
+typedef  struct _DiImage  DiImage;
+
+/* an offset in the image */
+typedef  ULong  DiOffT;
+
+/* This denotes an invalid DiOffT value.  Except where otherwise
+   noted, you must never pass this to any of the ML_(image_*)
+   functions -- they will assert.  That does mean though that they can
+   be used for signalling other conditions, for example that some
+   expected part of the image is missing. */
+#define DiOffT_INVALID ((DiOffT)(0xFFFFFFFFFFFFFFFFULL))
+
+/* Create an image from a file in the local filesysem.  Returns NULL
+   if it fails, for whatever reason. */
+DiImage* ML_(img_from_local_file)(const HChar* fullpath);
+
+/* Create an image by connecting to a Valgrind debuginfo server
+   (auxprogs/valgrind-di-server.c).  |filename| contains the object
+   name to ask for; it must be a plain filename, not absolute, not a
+   path.  |serverAddr| must be of the form either "d.d.d.d" or
+   "d.d.d.d:d" where d is one or more digits.  These specify the IPv4
+   address and (in the second case) port number for the server.  In
+   the first case, port 1500 is assumed. */
+DiImage* ML_(img_from_di_server)(const HChar* filename,
+                                 const HChar* serverAddr);
+
+/* Destroy an existing image. */
+void ML_(img_done)(DiImage*);
+
+/* How big is the image? */
+DiOffT ML_(img_size)(DiImage* img);
+
+/* Does the section [offset, +size) exist in the image? */
+Bool ML_(img_valid)(DiImage* img, DiOffT offset, SizeT size);
+
+/* Get info out of an image.  If any part of the section denoted by
+   [offset, +size) is invalid, does not return. */
+void ML_(img_get)(/*OUT*/void* dst,
+                  DiImage* img, DiOffT offset, SizeT size);
+
+/* A version of ML_(img_get) that is significantly cheaper when
+   fetching a lot of data, at the cost of being more difficult to use.
+   Fetches between 1 and |size| bytes from |img| at |offset| and
+   places them in |dst|.  |size| must be at least 1.  The number of
+   bytes read is returned, and the caller must be able to deal with
+   any number between 1 and |size|.  |offset| must be a valid offset
+   in the image; if not the function will not return.  This function
+   will not read off the end of the image. */
+SizeT ML_(img_get_some)(/*OUT*/void* dst,
+                        DiImage* img, DiOffT offset, SizeT size);
+
+/* Copy a C string out of the image, into ML_(dinfo_zalloc)'d space.
+   The caller owns the string and must free it with ML_(dinfo_free).
+   |offset| may be DiOffT_INVALID, in which case this returns NULL. */
+HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset);
+
+/* Do strcmp on two C strings in the image.  Chars are cast to HChar
+   before comparison. */
+Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2);
+
+/* Do strcmp of a C string in the image vs a normal one.  Chars are
+   cast to HChar before comparison. */
+Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
+
+/* Do strlen of a C string in the image. */
+SizeT ML_(img_strlen)(DiImage* img, DiOffT off);
+
+/* Fetch various sized primitive types from the image.  These operate
+   at the endianness and word size of the host. */
+UChar  ML_(img_get_UChar) (DiImage* img, DiOffT offset);
+UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset);
+UInt   ML_(img_get_UInt)  (DiImage* img, DiOffT offset);
+ULong  ML_(img_get_ULong) (DiImage* img, DiOffT offset);
+
+/* Calculate the "GNU Debuglink CRC" for the image.  This
+   unfortunately has to be done as part of the DiImage implementation
+   because it involves reading the entire image, and is therefore
+   something that needs to be handed off to the remote server -- since
+   to do it otherwise would imply pulling the entire image across the
+   connection, making the client/server split pointless. */
+UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img);
+
+
+/*------------------------------------------------------------*/
+/*--- DiCursor -- cursors for reading images               ---*/
+/*------------------------------------------------------------*/
+
+/* A type built on DiImage.  It contains a DiImage and a 'current
+   offset' in the image, and is useful for building low level readers
+   of images.  In the functions section below, "read" means "read data
+   at the cursor without moving it along", and "step" means "read data
+   at the cursor and move it along by the size of the item read". */
+typedef
+   struct { DiImage* img; DiOffT ioff; }
+   DiCursor;
+
+/* An invalid cursor.  You can't use it for anything. */
+#define DiCursor_INVALID ((DiCursor){NULL,DiOffT_INVALID})
+
+static inline DiCursor mk_DiCursor ( DiImage* img, DiOffT ioff ) {
+   return (DiCursor){img, ioff};
+}
+
+static inline Bool ML_(cur_is_valid)(DiCursor c) {
+   return c.img != NULL;
+}
+
+
+/*------------------------------------------------------------*/
+/*--- DiSlice -- subranges within DiImages                 ---*/
+/*------------------------------------------------------------*/
+
+/* Another type built on top of DiImage.  It denotes a subrange of an
+   image and is useful for representing (eg) exactly the part of an
+   image that is a specific ELF section. */
+typedef
+   struct { DiImage* img; DiOffT ioff; DiOffT szB; }
+   DiSlice;
+
+/* A DiSlice can also be INVALID, meaning it does not refer to any
+   part of any image. */
+#define DiSlice_INVALID ((DiSlice){NULL,DiOffT_INVALID,0})
+
+static inline DiSlice mk_DiSlice ( DiImage* img, DiOffT ioff, DiOffT szB ) {
+   return (DiSlice){img, ioff, szB};
+}
+
+static inline Bool ML_(sli_is_valid)( DiSlice sli ) {
+   return sli.img != NULL;
+}
+
+/* Create a slice from a combination of a cursor and a length.  The
+   maximum implied offset must not exceed the size of the underlying
+   image; this is asserted for. */
+static inline DiSlice ML_(sli_from_cur)( DiCursor cur, DiOffT size ) {
+   if (ML_(cur_is_valid)(cur)) {
+      vg_assert(size != DiOffT_INVALID);
+      vg_assert(cur.ioff + size <= ML_(img_size)(cur.img));
+      return mk_DiSlice(cur.img, cur.ioff, size);
+   } else {
+      return DiSlice_INVALID;
+   }
+}
+
+/* Create a slice which exactly covers the given image. */
+static inline DiSlice ML_(sli_from_img)( DiImage* img ) {
+   if (img) {
+      return mk_DiSlice(img, 0, ML_(img_size)(img));
+   } else {
+      return DiSlice_INVALID;
+   }
+}
+
+
+/*------------------------------------------------------------*/
+/*--- Functions that operate on DiCursors                  ---*/
+/*------------------------------------------------------------*/
+
+/* Create a cursor from a slice, referring to the first byte of the
+   slice. */
+static inline DiCursor ML_(cur_from_sli)( DiSlice sl ) {
+   if (ML_(sli_is_valid)(sl)) {
+      DiCursor c;
+      c.img  = sl.img;
+      c.ioff = sl.ioff;
+      return c;
+   } else {
+      return DiCursor_INVALID;
+   }
+}
+
+static inline Bool ML_(cur_cmpLT)( DiCursor c1, DiCursor c2 ) {
+   vg_assert(c1.img == c2.img);
+   return c1.ioff < c2.ioff;
+}
+static inline Bool ML_(cur_cmpEQ)( DiCursor c1, DiCursor c2 ) {
+   vg_assert(c1.img == c2.img);
+   return c1.ioff == c2.ioff;
+}
+static inline Bool ML_(cur_cmpGT)( DiCursor c1, DiCursor c2 ) {
+   vg_assert(c1.img == c2.img);
+   return c1.ioff > c2.ioff;
+}
+
+static inline DiCursor ML_(cur_plus)( DiCursor c, Long n ) {
+   c.ioff += (DiOffT)n;
+   return c;
+}
+
+/* Asserts that c1 and c2 refer to the same image.  Returns the difference
+   in offsets (c1.ioff - c2.ioff). */
+static inline Long ML_(cur_minus)( DiCursor c1, DiCursor c2 ) {
+   vg_assert(c1.img == c2.img);
+   return (Long)(c1.ioff) - (Long)(c2.ioff);
+}
+
+static inline SizeT ML_(cur_strlen)( DiCursor c ) {
+   return ML_(img_strlen)( c.img, c.ioff );
+}
+
+// strdup from the given cursor.  Caller must ML_(dinfo_free) the
+// resulting string.
+static inline HChar* ML_(cur_read_strdup)( DiCursor c, const HChar* cc ) {
+   vg_assert(c.ioff != DiOffT_INVALID);
+   HChar* res = ML_(img_strdup)(c.img, cc, c.ioff);
+   return res;
+}
+// strdup from the given cursor and advance it.  Caller must
+// ML_(dinfo_free) the resulting string.
+static inline HChar* ML_(cur_step_strdup)( DiCursor* c, const HChar* cc ) {
+   vg_assert(c->ioff != DiOffT_INVALID);
+   HChar* res = ML_(img_strdup)(c->img, cc, c->ioff);
+   c->ioff += VG_(strlen)(res) + 1;
+   return res;
+}
+
+// Fetch an arbitrary number of bytes from the cursor.
+static inline void ML_(cur_read_get) ( /*OUT*/void* dst,
+                                       DiCursor c, SizeT size) {
+   ML_(img_get)(dst, c.img, c.ioff, size);
+}
+
+// Fetch an arbitrary number of bytes from the cursor, and advance it.
+static inline void ML_(cur_step_get) ( /*OUT*/void* dst,
+                                       DiCursor* c, SizeT size) {
+   ML_(img_get)(dst, c->img, c->ioff, size);
+   c->ioff += size;
+}
+
+// memdup from the given cursor.  Caller must ML_(dinfo_free) the
+// resulting block.
+static inline UChar* ML_(cur_read_memdup)( DiCursor c, SizeT size,
+                                           const HChar* cc )
+{
+   UChar* dst = ML_(dinfo_zalloc)(cc, size);
+   if (size > 0)
+      ML_(cur_read_get)(dst, c, size);
+   return dst;
+}
+
+static inline UChar ML_(cur_read_UChar) ( DiCursor c ) {
+   UChar r = ML_(img_get_UChar)( c.img, c.ioff );
+   return r;
+}
+static inline UChar ML_(cur_step_UChar)( DiCursor* c ) {
+   UChar r = ML_(img_get_UChar)( c->img, c->ioff );
+   c->ioff += sizeof(UChar);
+   return r;
+}
+
+static inline UShort ML_(cur_read_UShort) ( DiCursor c ) {
+   UShort r = ML_(img_get_UShort)( c.img, c.ioff );
+   return r;
+}
+static inline UShort ML_(cur_step_UShort) ( DiCursor* c ) {
+   UShort r = ML_(img_get_UShort)( c->img, c->ioff );
+   c->ioff += sizeof(UShort);
+   return r;
+}
+static inline Short ML_(cur_step_Short) ( DiCursor* c ) {
+   return (Short)ML_(cur_step_UShort)( c );
+}
+
+static inline UInt ML_(cur_read_UInt) ( DiCursor c ) {
+   UInt r = ML_(img_get_UInt)( c.img, c.ioff );
+   return r;
+}
+static inline UInt ML_(cur_step_UInt) ( DiCursor* c ) {
+   UInt r = ML_(img_get_UInt)( c->img, c->ioff );
+   c->ioff += sizeof(UInt);
+   return r;
+}
+static inline Int ML_(cur_step_Int) ( DiCursor* c ) {
+   return (Int)ML_(cur_step_UInt)( c );
+}
+
+static inline ULong ML_(cur_read_ULong) ( DiCursor c ) {
+   ULong r = ML_(img_get_ULong)( c.img, c.ioff );
+   return r;
+}
+static inline ULong ML_(cur_step_ULong) ( DiCursor* c ) {
+   ULong r = ML_(img_get_ULong)( c->img, c->ioff );
+   c->ioff += sizeof(ULong);
+   return r;
+}
+static inline Long ML_(cur_step_Long) ( DiCursor* c ) {
+   return (Long)ML_(cur_step_ULong)( c );
+}
+
+static inline Addr ML_(cur_step_Addr) ( DiCursor* c ) {
+   if (sizeof(Addr) == sizeof(UInt)) {
+      return ML_(cur_step_UInt)(c);
+   } else if  (sizeof(Addr) == sizeof(ULong)) {
+      return ML_(cur_step_ULong)(c);
+   } else {
+      vg_assert(0);
+   }
+}
+
+
+
+/*--------------------------------------------------------------------*/
+/*--- end                                             priv_image.h ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_debuginfo/priv_readdwarf.h b/coregrind/m_debuginfo/priv_readdwarf.h
index efc56be..a8c6fdb 100644
--- a/coregrind/m_debuginfo/priv_readdwarf.h
+++ b/coregrind/m_debuginfo/priv_readdwarf.h
@@ -44,12 +44,12 @@
 extern
 void ML_(read_debuginfo_dwarf3)
         ( struct _DebugInfo* di,
-          UChar* debug_info_img, Word debug_info_sz,  /* .debug_info */
-          UChar* debug_types_img, Word debug_types_sz,  /* .debug_types */
-          UChar* debug_abbv_img, Word debug_abbv_sz,  /* .debug_abbrev */
-          UChar* debug_line_img, Word debug_line_sz,  /* .debug_line */
-          HChar* debug_str_img,  Word debug_str_sz,   /* .debug_str */
-          HChar* debug_str_alt_img, Word debug_str_alt_sz ); /* .debug_str */
+          DiSlice escn_debug_info,      /* .debug_info */
+          DiSlice escn_debug_types,     /* .debug_types */
+          DiSlice escn_debug_abbv,      /* .debug_abbrev */
+          DiSlice escn_debug_line,      /* .debug_line */
+          DiSlice escn_debug_str,       /* .debug_str */
+          DiSlice escn_debug_str_alt ); /* .debug_str */
 
 /* --------------------
    DWARF1 reader
@@ -65,8 +65,7 @@
 extern
 void ML_(read_callframe_info_dwarf3)
         ( /*OUT*/struct _DebugInfo* di,
-          UChar* frame_image, SizeT frame_size, Addr frame_avma,
-          Bool is_ehframe );
+          DiSlice escn_frame, Addr frame_avma, Bool is_ehframe );
 
 
 #endif /* ndef __PRIV_READDWARF_H */
diff --git a/coregrind/m_debuginfo/priv_readdwarf3.h b/coregrind/m_debuginfo/priv_readdwarf3.h
index cfc2895..7cba4e2 100644
--- a/coregrind/m_debuginfo/priv_readdwarf3.h
+++ b/coregrind/m_debuginfo/priv_readdwarf3.h
@@ -42,17 +42,12 @@
 void 
 ML_(new_dwarf3_reader) (
    struct _DebugInfo* di,
-   UChar* debug_info_img,   SizeT debug_info_sz,
-   UChar* debug_types_img,  SizeT debug_types_sz,
-   UChar* debug_abbv_img,   SizeT debug_abbv_sz,
-   UChar* debug_line_img,   SizeT debug_line_sz,
-   HChar* debug_str_img,    SizeT debug_str_sz,
-   UChar* debug_ranges_img, SizeT debug_ranges_sz,
-   UChar* debug_loc_img,    SizeT debug_loc_sz,
-   UChar* debug_info_alt_img, SizeT debug_info_alt_sz,
-   UChar* debug_abbv_alt_img, SizeT debug_abbv_alt_sz,
-   UChar* debug_line_alt_img, SizeT debug_line_alt_sz,
-   HChar* debug_str_alt_img,  SizeT debug_str_alt_sz
+   DiSlice escn_debug_info,      DiSlice escn_debug_types,
+   DiSlice escn_debug_abbv,      DiSlice escn_debug_line,
+   DiSlice escn_debug_str,       DiSlice escn_debug_ranges,
+   DiSlice escn_debug_loc,       DiSlice escn_debug_info_alt,
+   DiSlice escn_debug_abbv_alt,  DiSlice escn_debug_line_alt,
+   DiSlice escn_debug_str_alt
 );
 
 #endif /* ndef __PRIV_READDWARF3_H */
diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
index ecf7fae..6628373 100644
--- a/coregrind/m_debuginfo/priv_storage.h
+++ b/coregrind/m_debuginfo/priv_storage.h
@@ -845,6 +845,11 @@
    ML_(addStr) will itself measure the length of the string. */
 extern HChar* ML_(addStr) ( struct _DebugInfo* di, const HChar* str, Int len );
 
+/* Add a string to the string table of a DebugInfo, by copying the
+   string from the given DiCursor.  Measures the length of the string
+   itself. */
+extern HChar* ML_(addStrFromCursor)( struct _DebugInfo* di, DiCursor c );
+
 extern void ML_(addVar)( struct _DebugInfo* di,
                          Int    level,
                          Addr   aMin,
@@ -908,8 +913,9 @@
 extern void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si );
 
 
+#define TRACE_SYMTAB_ENABLED (di->trace_symtab)
 #define TRACE_SYMTAB(format, args...) \
-   if (di->trace_symtab) { VG_(printf)(format, ## args); }
+   if (TRACE_SYMTAB_ENABLED) { VG_(printf)(format, ## args); }
 
 
 #endif /* ndef __PRIV_STORAGE_H */
diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
index a7d5803..0e369c5 100644
--- a/coregrind/m_debuginfo/readdwarf.c
+++ b/coregrind/m_debuginfo/readdwarf.c
@@ -1,3 +1,4 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
 
 /*--------------------------------------------------------------------*/
 /*--- Read DWARF1/2/3/4 debug info.                    readdwarf.c ---*/
@@ -39,6 +40,7 @@
 #include "pub_core_xarray.h"
 #include "pub_core_tooliface.h"    /* VG_(needs) */
 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
+#include "priv_image.h"
 #include "priv_d3basics.h"
 #include "priv_tytypes.h"
 #include "priv_storage.h"
@@ -152,10 +154,10 @@
 typedef struct
 {
   /* Feel free to add more members here if you need ! */
-  HChar* compdir;  /* Compilation directory - points to .debug_info */
-  HChar* name;     /* Main file name - points to .debug_info */
-  ULong stmt_list; /* Offset in .debug_line */
-  Bool  dw64;      /* 64-bit Dwarf? */
+  DiCursor compdir;  /* Compilation directory - points to .debug_info */
+  DiCursor name;     /* Main file name - points to .debug_info */
+  ULong    stmt_list; /* Offset in .debug_line */
+  Bool     dw64;      /* 64-bit Dwarf? */
 } 
 UnitInfo;
 
@@ -206,57 +208,36 @@
 
 
 /* FIXME: duplicated in readdwarf3.c */
-static 
-ULong read_leb128 ( UChar* data, Int* length_return, Int sign )
+/* Read a 'leb128' and advance *data accordingly. */
+static ULong step_leb128 ( DiCursor* data, Int sign )
 {
-  ULong  result = 0;
-  UInt   num_read = 0;
-  Int    shift = 0;
-  UChar  byte;
+   ULong  result = 0;
+   Int    shift = 0;
+   UChar  byte;
 
-  vg_assert(sign == 0 || sign == 1);
+   vg_assert(sign == 0 || sign == 1);
 
-  do
-    {
-      byte = * data ++;
-      num_read ++;
-
+   do {
+      byte = ML_(cur_step_UChar)(data);
       result |= ((ULong)(byte & 0x7f)) << shift;
-
       shift += 7;
+   }
+   while (byte & 0x80);
 
-    }
-  while (byte & 0x80);
+   if (sign && (shift < 64) && (byte & 0x40))
+      result |= -(1ULL << shift);
 
-  if (length_return != NULL)
-    * length_return = num_read;
-
-  if (sign && (shift < 64) && (byte & 0x40))
-    result |= -(1ULL << shift);
-
-  return result;
+   return result;
 }
 
-/* Small helper functions easier to use
- * value is returned and the given pointer is
- * moved past end of leb128 data */
 /* FIXME: duplicated in readdwarf3.c */
-static ULong read_leb128U( UChar **data )
-{
-  Int len;
-  ULong val = read_leb128( *data, &len, 0 );
-  *data += len;
-  return val;
+static ULong step_leb128U( DiCursor* data ) {
+   return step_leb128( data, 0 );
 }
 
-/* Same for signed data */
 /* FIXME: duplicated in readdwarf3.c */
-static Long read_leb128S( UChar **data )
-{
-   Int len;
-   ULong val = read_leb128( *data, &len, 1 );
-   *data += len;
-   return (Long)val;
+static Long step_leb128S( DiCursor* data ) {
+   return step_leb128( data, 1 );
 }
 
 /* Read what the DWARF3 spec calls an "initial length field".  This
@@ -265,7 +246,7 @@
 
    Read 32-bit value from p.  If it is 0xFFFFFFFF, instead read a
    64-bit bit value from p+4.  This is used in 64-bit dwarf to encode
-   some table lengths. 
+   some table lengths.  Advance the cursor (p) accordingly.
 
    XXX this is a hack: the endianness of the initial length field is
    specified by the DWARF we're reading.  This happens to work only
@@ -275,18 +256,27 @@
    of other places -- to be precise, exactly the places where
    binutils/dwarf.c calls byte_get().
 */
-static ULong read_initial_length_field ( UChar* p_img, /*OUT*/Bool* is64 )
+static
+ULong step_initial_length_field ( DiCursor* p_img, /*OUT*/Bool* is64 )
 {
-   UInt w32 = ML_(read_UInt)(p_img);
+   UInt w32 = ML_(cur_step_UInt)(p_img);
    if (w32 == 0xFFFFFFFF) {
       *is64 = True;
-      return ML_(read_ULong)(p_img+4);
+      return ML_(cur_step_ULong)(p_img);
    } else {
       *is64 = False;
       return (ULong)w32;
    }
 }
 
+static
+ULong read_initial_length_field ( DiCursor p_img, /*OUT*/Bool* is64 )
+{
+   /* Something of a roundabout approach .. the modification to p_img
+      is abandoned. */
+   return step_initial_length_field( &p_img, is64 );
+}
+
 
 static LineSMR state_machine_regs;
 
@@ -329,34 +319,24 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
-/* Handled an extended line op starting at 'data'.  Returns the number
-   of bytes that 'data' should be advanced by. */
+/* Handled an extended line op starting at *data, and advance *data
+   accordingly. */
 static 
-Word process_extended_line_op( struct _DebugInfo* di,
+void process_extended_line_op( struct _DebugInfo* di,
                                WordArray* filenames, 
                                WordArray* dirnames, 
                                WordArray* fnidx2dir, 
-                               UChar* data, Int is_stmt)
+                               DiCursor* data, Int is_stmt)
 {
-   UChar  op_code;
-   Int    bytes_read;
-   UInt   len;
-   HChar* name;
-   Addr   adr;
-
-   len = read_leb128 (data, & bytes_read, 0);
-   data += bytes_read;
-
+   UInt len = step_leb128U(data);
    if (len == 0) {
       VG_(message)(Vg_UserMsg,
                    "Warning: DWARF2 reader: "
                    "Badly formed extended line op encountered\n");
-      return (Word)bytes_read;
+      return;
    }
 
-   len += bytes_read;
-   op_code = * data ++;
-
+   UChar op_code = ML_(cur_step_UChar)(data);
    if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
 
    switch (op_code) {
@@ -392,30 +372,29 @@
                         (Int)op_code);
          break;
 
-      case DW_LNE_set_address:
-         adr = ML_(read_Addr)(data);
+      case DW_LNE_set_address: {
+         Addr adr = ML_(cur_step_Addr)(data);
          state_machine_regs.address = adr;
          if (di->ddump_line)
             VG_(printf)("  Extended opcode %d: set Address to 0x%lx\n",
                         (Int)op_code, (Addr)adr);
          break;
+      }
 
-      case DW_LNE_define_file:
-         name = (HChar *)data;
+      case DW_LNE_define_file: {
+         HChar* name = ML_(cur_step_strdup)(data, "di.pelo.1");
          addto_WordArray( filenames, (Word)ML_(addStr)(di,name,-1) );
-         data += VG_(strlen) ((char *) data) + 1;
-         read_leb128 (data, & bytes_read, 0);
-         data += bytes_read;
-         read_leb128 (data, & bytes_read, 0);
-         data += bytes_read;
-         read_leb128 (data, & bytes_read, 0);
+         ML_(dinfo_free)(name);
+         (void)step_leb128U(data); // ignored: dir index
+         (void)step_leb128U(data); // ignored: mod time
+         (void)step_leb128U(data); // ignored: file size
          if (di->ddump_line)
             VG_(printf)("  DWARF2-line: set_address\n");
          break;
+      }
 
       case DW_LNE_set_discriminator:
-         read_leb128 (data, & bytes_read, 0);
-         data += bytes_read;
+         (void)step_leb128U(data); // ignored: new 'discriminator' value
          break;
 
       default:
@@ -423,8 +402,6 @@
             VG_(printf)("process_extended_line_op:default\n");
          break;
    }
-
-   return (Word)len;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -442,20 +419,18 @@
 static 
 void read_dwarf2_lineblock ( struct _DebugInfo* di,
                              UnitInfo* ui, 
-                             UChar*    theBlock, /* IMAGE */
+                             DiCursor  theBlock, /* IMAGE */
                              Int       noLargerThan )
 {
    Int            i;
    DebugLineInfo  info;
-   UChar*         standard_opcodes;
-   UChar*         end_of_sequence;
    Bool           is64;
    WordArray      filenames;
    WordArray      dirnames;
    WordArray      fnidx2dir;
 
-   UChar*         external = theBlock;
-   UChar*         data = theBlock;
+   DiCursor       external = theBlock;
+   DiCursor       data = theBlock;
 
    /* filenames is an array of file names harvested from the DWARF2
       info.  Entry [0] is NULL and is never referred to by the state
@@ -492,15 +467,15 @@
    */
    addto_WordArray( &filenames, (Word)NULL );
 
-   if (ui->compdir)
-      addto_WordArray( &dirnames, (Word)ML_(addStr)(di, ui->compdir, -1) );
+   if (ML_(cur_is_valid)(ui->compdir))
+      addto_WordArray( &dirnames,
+                       (Word)ML_(addStrFromCursor)(di, ui->compdir) );
    else
       addto_WordArray( &dirnames, (Word)ML_(addStr)(di, ".", -1) );
 
    addto_WordArray( &fnidx2dir, (Word)0 );  /* compilation dir */
 
-   info.li_length = read_initial_length_field( external, &is64 );
-   external += is64 ? 12 : 4;
+   info.li_length = step_initial_length_field( &external, &is64 );
    if (di->ddump_line)
       VG_(printf)("  Length:                      %llu\n", 
                   info.li_length);
@@ -514,8 +489,7 @@
    }
 
    /* Check its version number.  */
-   info.li_version = ML_(read_UShort)(external);
-   external += 2;
+   info.li_version = ML_(cur_step_UShort)(&external);
    if (di->ddump_line)
       VG_(printf)("  DWARF Version:               %d\n", 
                   (Int)info.li_version);
@@ -527,15 +501,13 @@
       goto out;
    }
 
-   info.li_header_length = is64 ? ML_(read_ULong)(external) 
-                                : (ULong)(ML_(read_UInt)(external));
-   external += is64 ? 8 : 4;
+   info.li_header_length = is64 ? ML_(cur_step_ULong)(&external) 
+                                : (ULong)(ML_(cur_step_UInt)(&external));
    if (di->ddump_line)
       VG_(printf)("  Prologue Length:             %llu\n", 
                   info.li_header_length);
 
-   info.li_min_insn_length = * ((UChar *)external);
-   external += 1;
+   info.li_min_insn_length = ML_(cur_step_UChar)(&external);
    if (di->ddump_line)
       VG_(printf)("  Minimum Instruction Length:  %d\n", 
                   (Int)info.li_min_insn_length);
@@ -546,13 +518,12 @@
       patch attached to BZ#233595.
    */
    if (info.li_version >= 4) {
-      info.li_max_ops_per_insn = * ((UChar *)external);
+      info.li_max_ops_per_insn = ML_(cur_step_UChar)(&external);
       if (info.li_max_ops_per_insn != 1) {
          ML_(symerr)(di, True,
                      "Invalid Maximum Ops Per Insn in line info.");
          goto out;
       }
-      external += 1;
       if (di->ddump_line)
          VG_(printf)("  Maximum Ops Per Insn:        %d\n", 
                   (Int)info.li_max_ops_per_insn);
@@ -560,8 +531,7 @@
       info.li_max_ops_per_insn = 1;
    }
 
-   info.li_default_is_stmt = * ((UChar *)external);
-   external += 1;
+   info.li_default_is_stmt = ML_(cur_step_UChar)(&external);
    if (di->ddump_line)
       VG_(printf)("  Initial value of 'is_stmt':  %d\n", 
                   (Int)info.li_default_is_stmt);
@@ -586,21 +556,18 @@
    info.li_default_is_stmt = True; 
 
    /* JRS: changed (UInt*) to (UChar*) */
-   info.li_line_base = * ((UChar *)external);
-   info.li_line_base = (Int)(signed char)info.li_line_base;
-   external += 1;
+   info.li_line_base = ML_(cur_step_UChar)(&external);
+   info.li_line_base = (Int)(Char)info.li_line_base;
    if (di->ddump_line)
       VG_(printf)("  Line Base:                   %d\n", 
                   info.li_line_base);
 
-   info.li_line_range = * ((UChar *)external);
-   external += 1;
+   info.li_line_range = ML_(cur_step_UChar)(&external);
    if (di->ddump_line)
       VG_(printf)("  Line Range:                  %d\n", 
                   (Int)info.li_line_range);
 
-   info.li_opcode_base = * ((UChar *)external);
-   external += 1;
+   info.li_opcode_base = ML_(cur_step_UChar)(&external);
    if (di->ddump_line)
       VG_(printf)("  Opcode Base:                 %d\n\n", 
                   info.li_opcode_base);
@@ -610,62 +577,69 @@
                       (Int)info.li_line_range,
                       (Int)info.li_opcode_base);
 
-   end_of_sequence = data + info.li_length 
-                          + (is64 ? 12 : 4);
+   DiCursor end_of_sequence
+     = ML_(cur_plus)(data, info.li_length + (is64 ? 12 : 4));
 
    reset_state_machine (info.li_default_is_stmt);
 
    /* Read the contents of the Opcodes table.  */
-   standard_opcodes = external;
+   DiCursor standard_opcodes = external;
    if (di->ddump_line) {
       VG_(printf)(" Opcodes:\n");
       for (i = 1; i < (Int)info.li_opcode_base; i++) {
          VG_(printf)("  Opcode %d has %d args\n", 
-                     i, (Int)standard_opcodes[i-1]);
+                     i, (Int)ML_(cur_read_UChar)(
+                                ML_(cur_plus)(standard_opcodes,
+                                              (i-1) * sizeof(UChar)) ));
       }
       VG_(printf)("\n");
    }
 
    /* Read the contents of the Directory table.  */
-   data = standard_opcodes + info.li_opcode_base - 1;
+   data = ML_(cur_plus)(standard_opcodes, info.li_opcode_base - 1);
 
    if (di->ddump_line)
       VG_(printf)(" The Directory Table%s\n", 
-                  *data == 0 ? " is empty." : ":" );
+                  ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" );
 
-   while (* data != 0) {
+   while (ML_(cur_read_UChar)(data) != 0) {
 
 #     define NBUF 4096
       static HChar buf[NBUF];
 
+      HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1");
       if (di->ddump_line)
-         VG_(printf)("  %s\n", data);
+         VG_(printf)("  %s\n", data_str);
 
       /* If data[0] is '/', then 'data' is an absolute path and we
          don't mess with it.  Otherwise, if we can, construct the
-         'path ui->compdir' ++ "/" ++ 'data'. */
+         path 'ui->compdir' ++ "/" ++ 'data'. */
 
-      if (*data != '/' 
+      if (data_str[0] != '/' 
           /* not an absolute path */
-          && ui->compdir != NULL
+          && ML_(cur_is_valid)(ui->compdir)
           /* actually got something sensible for compdir */
-          && VG_(strlen)(ui->compdir) + VG_(strlen)((HChar *)data) + 5/*paranoia*/ < NBUF
+          && ML_(cur_strlen)(ui->compdir)
+             + VG_(strlen)(data_str) + 5/*paranoia*/ < NBUF
           /* it's short enough to concatenate */) 
       {
          buf[0] = 0;
-         VG_(strcat)(buf, ui->compdir);
+         HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, "di.rd2l.1b");
+         VG_(strcat)(buf, compdir_str);
          VG_(strcat)(buf, "/");
-         VG_(strcat)(buf, (HChar *)data);
+         VG_(strcat)(buf, data_str);
          vg_assert(VG_(strlen)(buf) < NBUF);
          addto_WordArray( &dirnames, (Word)ML_(addStr)(di,buf,-1) );
          if (0) VG_(printf)("rel path  %s\n", buf);
+         ML_(dinfo_free)(compdir_str);
       } else {
          /* just use 'data'. */
-        addto_WordArray( &dirnames, (Word)ML_(addStr)(di,(HChar *)data,-1) );
-         if (0) VG_(printf)("abs path  %s\n", data);
+         addto_WordArray( &dirnames, (Word)ML_(addStr)(di,data_str,-1) );
+         if (0) VG_(printf)("abs path  %s\n", data_str);
       }
 
-      data += VG_(strlen)((HChar *)data) + 1;
+      data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1);
+      ML_(dinfo_free)(data_str);
 
 #     undef NBUF
    }
@@ -673,12 +647,12 @@
    if (di->ddump_line)
       VG_(printf)("\n");
 
-   if (*data != 0) {
+   if (ML_(cur_read_UChar)(data) != 0) {
       ML_(symerr)(di, True,
                   "can't find NUL at end of DWARF2 directory table");
       goto out;
    }
-   data ++;
+   data = ML_(cur_plus)(data, 1);
 
    /* Read the contents of the File Name table.  This produces a bunch
       of file names, and for each, an index to the corresponding
@@ -689,20 +663,11 @@
    }
 
    i = 1;
-   while (* data != 0) {
-      HChar* name;
-      Int    bytes_read, diridx;
-      Int    uu_time, uu_size; /* unused, and a guess */
-      name = (HChar *)data;
-      data += VG_(strlen) (name) + 1;
-
-      diridx = read_leb128 (data, & bytes_read, 0);
-      data += bytes_read;
-      uu_time = read_leb128 (data, & bytes_read, 0);
-      data += bytes_read;
-      uu_size = read_leb128 (data, & bytes_read, 0);
-      data += bytes_read;
-
+   while (ML_(cur_read_UChar)(data) != 0) {
+      HChar* name    = ML_(cur_step_strdup)(&data, "di.rd2l.2");
+      Int    diridx  = step_leb128U(&data);
+      Int    uu_time = step_leb128U(&data); /* unused */
+      Int    uu_size = step_leb128U(&data); /* unused */
       addto_WordArray( &filenames, (Word)ML_(addStr)(di,name,-1) );
       addto_WordArray( &fnidx2dir, (Word)diridx );
       if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
@@ -710,43 +675,37 @@
          VG_(printf)("  %d\t%d\t%d\t%d\t%s\n", 
                      i, diridx, uu_time, uu_size, name);
       i++;
+      ML_(dinfo_free)(name);
    }
 
    if (di->ddump_line)
       VG_(printf)("\n");
 
-   if (*data != 0) {
+   if (ML_(cur_read_UChar)(data) != 0) {
       ML_(symerr)(di, True,
                   "can't find NUL at end of DWARF2 file name table");
       goto out;
    }
-   data ++;
+   data = ML_(cur_plus)(data, 1);
 
    if (di->ddump_line)
       VG_(printf)(" Line Number Statements:\n");
 
    /* Now display the statements.  */
 
-   while (data < end_of_sequence) {
-
-      UChar op_code;
-      Int           adv;
-      Int           bytes_read;
-
-      op_code = * data ++;
+   while (ML_(cur_cmpLT)(data, end_of_sequence)) {
+      UChar op_code = ML_(cur_step_UChar)(&data);
 
       if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
 
       if (op_code >= info.li_opcode_base) {
-
-         Int advAddr;
          op_code -= info.li_opcode_base;
-         adv      = (op_code / info.li_line_range)
+         Word adv = (op_code / info.li_line_range)
                        * info.li_min_insn_length;
-         advAddr = adv;
+         Int advAddr = adv;
          state_machine_regs.address += adv;
 
-         if (0) VG_(printf)("smr.a += %#x\n", adv );
+         if (0) VG_(printf)("smr.a += %#lx\n", adv );
          adv = (op_code % info.li_line_range) + info.li_line_base;
          if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
                             di->text_debug_bias, state_machine_regs.address );
@@ -782,16 +741,15 @@
             state_machine_regs.last_file = state_machine_regs.file;
             state_machine_regs.last_line = state_machine_regs.line;
          }
-
       }
 
       else { /* ! (op_code >= info.li_opcode_base) */
 
       switch (op_code) {
          case DW_LNS_extended_op:
-            data += process_extended_line_op (
+            process_extended_line_op (
                        di, &filenames, &dirnames, &fnidx2dir,
-                       data, info.li_default_is_stmt);
+                       &data, info.li_default_is_stmt);
             break;
 
          case DW_LNS_copy:
@@ -826,77 +784,71 @@
                VG_(printf)("  Copy\n");
             break;
 
-         case DW_LNS_advance_pc:
-            adv = info.li_min_insn_length
-                     * read_leb128 (data, & bytes_read, 0);
-            data += bytes_read;
+         case DW_LNS_advance_pc: {
+            Word adv = info.li_min_insn_length * step_leb128U(&data);
             state_machine_regs.address += adv;
-            if (0) VG_(printf)("smr.a += %#x\n", adv );
+            if (0) VG_(printf)("smr.a += %#lx\n", adv );
             if (di->ddump_line)
-               VG_(printf)("  Advance PC by %d to 0x%lx\n", 
-                           (Int)adv, state_machine_regs.address);
+               VG_(printf)("  Advance PC by %ld to 0x%lx\n", 
+                           adv, state_machine_regs.address);
             break;
-
-         case DW_LNS_advance_line:
-            adv = read_leb128 (data, & bytes_read, 1);
-            data += bytes_read;
+         }
+         case DW_LNS_advance_line: {
+            Word adv = step_leb128S(&data);
             state_machine_regs.line += adv;
             if (di->ddump_line)
-               VG_(printf)("  Advance Line by %d to %d\n", 
-                           (Int)adv, (Int)state_machine_regs.line);
+               VG_(printf)("  Advance Line by %ld to %d\n", 
+                           adv, (Int)state_machine_regs.line);
             break;
-
-         case DW_LNS_set_file:
-            adv = read_leb128 (data, & bytes_read, 0);
-            data += bytes_read;
+         }
+         case DW_LNS_set_file: {
+            Word adv = step_leb128U(&data);
             state_machine_regs.file = adv;
             if (di->ddump_line)
-               VG_(printf)("  Set File Name to entry %d in the File Name Table\n",
-                           (Int)adv);
+               VG_(printf)("  Set File Name to entry %ld in the "
+                           "File Name Table\n", adv);
             break;
-
-         case DW_LNS_set_column:
-            adv = read_leb128 (data, & bytes_read, 0);
-            data += bytes_read;
+         }
+         case DW_LNS_set_column: {
+            Word adv = step_leb128U(&data);
             state_machine_regs.column = adv;
             if (di->ddump_line)
-               VG_(printf)("  Set column to %d\n", (Int)adv);
+               VG_(printf)("  Set column to %ld\n", adv);
             break;
-
-         case DW_LNS_negate_stmt:
-            adv = state_machine_regs.is_stmt;
+         }
+         case DW_LNS_negate_stmt: {
+            Int adv = state_machine_regs.is_stmt;
             adv = ! adv;
             state_machine_regs.is_stmt = adv;
             if (di->ddump_line)
                VG_(printf)("  DWARF2-line: negate_stmt\n");
             break;
-
-         case DW_LNS_set_basic_block:
+         }
+         case DW_LNS_set_basic_block: {
             state_machine_regs.basic_block = 1;
             if (di->ddump_line)
                VG_(printf)("  DWARF2-line: set_basic_block\n");
             break;
-
-         case DW_LNS_const_add_pc:
-            adv = (((255 - info.li_opcode_base) / info.li_line_range)
-                   * info.li_min_insn_length);
+         }
+         case DW_LNS_const_add_pc: {
+            Word adv = (((255 - info.li_opcode_base) / info.li_line_range)
+                          * info.li_min_insn_length);
             state_machine_regs.address += adv;
-            if (0) VG_(printf)("smr.a += %#x\n", adv );
+            if (0) VG_(printf)("smr.a += %#lx\n", adv );
             if (di->ddump_line)
-               VG_(printf)("  Advance PC by constant %d to 0x%lx\n", 
-                           (Int)adv, (Addr)state_machine_regs.address);
+               VG_(printf)("  Advance PC by constant %ld to 0x%lx\n", 
+                           adv, (Addr)state_machine_regs.address);
             break;
-
-         case DW_LNS_fixed_advance_pc:
+         }
+         case DW_LNS_fixed_advance_pc: {
             /* XXX: Need something to get 2 bytes */
-            adv = ML_(read_UShort)(data);
-            data += 2;
+            Word adv = ML_(cur_step_UShort)(&data);
             state_machine_regs.address += adv;
-            if (0) VG_(printf)("smr.a += %#x\n", adv );
+            if (0) VG_(printf)("smr.a += %#lx\n", adv );
             if (di->ddump_line)
                VG_(printf)("  DWARF2-line: fixed_advance_pc\n");
             break;
-
+         }
          case DW_LNS_set_prologue_end:
             if (di->ddump_line)
                VG_(printf)("  DWARF2-line: set_prologue_end\n");
@@ -908,17 +860,18 @@
             break;
 
          case DW_LNS_set_isa:
-            /*adv =*/ read_leb128 (data, & bytes_read, 0);
-            data += bytes_read;
+            (void)step_leb128U(&data);
             if (di->ddump_line)
                VG_(printf)("  DWARF2-line: set_isa\n");
             break;
 
          default: {
             Int j;
-            for (j = standard_opcodes[op_code - 1]; j > 0 ; --j) {
-               read_leb128 (data, &bytes_read, 0);
-               data += bytes_read;
+            for (j = (Int)ML_(cur_read_UChar)(
+                             ML_(cur_plus)(standard_opcodes,
+                                           (op_code-1) * sizeof(UChar)));
+                 j > 0 ; --j) {
+               step_leb128U(&data);
             }
             if (di->ddump_line)
                VG_(printf)("  Unknown opcode %d\n", (Int)op_code);
@@ -943,25 +896,23 @@
 ////////////////////////////////////////////////////////////////////
 
 /* Return abbrev for given code 
- * Returned pointer points to the tag
+ * Returned cursor points to the tag
  * */
-static UChar* lookup_abbrev( UChar* p, UInt acode )
+static DiCursor lookup_abbrev( DiCursor p, ULong acode )
 {
-   UInt code;
-   UInt name;
-   for( ; ; ) {
-      code = read_leb128U( &p );
-      if ( code == acode )
+   while (1) {
+      ULong code = step_leb128U(&p);
+      if (code == acode)
          return p;
-      read_leb128U( &p ); /* skip tag */
-      p++;                /* skip has_children flag */
+      (void)step_leb128U(&p);  /* skip tag */
+      p = ML_(cur_plus)(p,1);  /* skip has_children flag */
+      ULong name;
       do {
-         name = read_leb128U( &p ); /* name */
-         read_leb128U( &p );   /* form */
+         name = step_leb128U(&p); /* name */
+         (void)step_leb128U(&p);  /* form */
       }
-      while( name != 0 ); /* until name == form == 0 */
+      while (name != 0); /* until name == form == 0 */
    }
-   return NULL;
 }
 
 /* Read general information for a particular compile unit block in
@@ -985,19 +936,19 @@
  */
 static 
 void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
-                                  UChar*    unitblock_img,
-                                  UChar*    debugabbrev_img,
-                                  HChar*    debugstr_img,
-                                  HChar*    debugstr_alt_img )
+                                  DiCursor  unitblock_img,
+                                  DiCursor  debugabbrev_img,
+                                  DiCursor  debugstr_img,
+                                  DiCursor  debugstr_alt_img )
 {
    UInt   acode, abcode;
    ULong  atoffs, blklen;
    UShort ver;
 
-   UChar addr_size;
-   UChar* p = unitblock_img;
-   UChar* end_img;
-   UChar* abbrev_img;
+   UChar    addr_size;
+   DiCursor p = unitblock_img;
+   DiCursor end_img;
+   DiCursor abbrev_img;
 
    VG_(memset)( ui, 0, sizeof( UnitInfo ) );
    ui->stmt_list = -1LL;
@@ -1005,65 +956,64 @@
    /* Read the compilation unit header in .debug_info section - See p 70 */
 
    /* This block length */
-   blklen = read_initial_length_field( p, &ui->dw64 );
-   p += ui->dw64 ? 12 : 4;
+   blklen = step_initial_length_field( &p, &ui->dw64 );
 
    /* version should be 2, 3 or 4 */
-   ver = ML_(read_UShort)(p);
-   p += 2;
+   ver = ML_(cur_step_UShort)(&p);
 
    /* get offset in abbrev */
-   atoffs = ui->dw64 ? ML_(read_ULong)(p) : (ULong)(ML_(read_UInt)(p));
-   p += ui->dw64 ? 8 : 4;
+   atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p)
+                     : (ULong)(ML_(cur_step_UInt)(&p));
 
    /* Address size */
-   addr_size = *p;
-   p += 1;
+   addr_size = ML_(cur_step_UChar)(&p);
 
-   end_img     = unitblock_img 
-                 + blklen + (ui->dw64 ? 12 : 4); /* End of this block */
-   abbrev_img  = debugabbrev_img 
-                 + atoffs; /* Abbreviation data for this block */
+   /* End of this block */
+   end_img = ML_(cur_plus)(unitblock_img, blklen + (ui->dw64 ? 12 : 4)); 
+
+   /* Abbreviation data for this block */
+   abbrev_img = ML_(cur_plus)(debugabbrev_img, atoffs);
    
    /* Read the compilation unit entry - this is always the first DIE.
     * See DWARF4 para 7.5. */
-   if ( p < end_img ) {
+   if (ML_(cur_cmpLT)(p, end_img)) {
       UInt tag;
 
-      acode = read_leb128U( &p ); /* abbreviation code */
+      acode = step_leb128U( &p ); /* abbreviation code */
       
       /* Read abbreviation header */
-      abcode = read_leb128U( &abbrev_img ); /* abbreviation code */
+      abcode = step_leb128U( &abbrev_img ); /* abbreviation code */
       if ( acode != abcode ) {
          /* This isn't illegal, but somewhat unlikely. Normally the
           * first abbrev describes the first DIE, the compile_unit.
           * But maybe this abbrevation data is shared with another
           * or it is a NULL entry used for padding. See para 7.5.3. */
-         abbrev_img = lookup_abbrev( debugabbrev_img + atoffs, acode );
+         abbrev_img = lookup_abbrev( ML_(cur_plus)(debugabbrev_img, atoffs),
+                                     acode );
       }
 
-      tag = read_leb128U( &abbrev_img );
+      tag = step_leb128U( &abbrev_img );
 
       if ( tag != 0x0011 /*TAG_compile_unit*/ )
          return; /* Not a compile unit (might be partial) or broken DWARF. */
 
-      abbrev_img++; /* DW_CHILDREN_yes or DW_CHILDREN_no */
+      /* DW_CHILDREN_yes or DW_CHILDREN_no */
+      abbrev_img = ML_(cur_plus)(abbrev_img, 1);
 
       /* And loop on entries */
       for ( ; ; ) {
          /* Read entry definition */
-         UInt  name, form;
-         ULong cval = -1LL;  /* Constant value read */
-         HChar *sval = NULL; /* String value read */
-         name = read_leb128U( &abbrev_img );
-         form = read_leb128U( &abbrev_img );
-         if ( name == 0 )
+         ULong    cval = -1LL;  /* Constant value read */
+         DiCursor sval = DiCursor_INVALID; /* String value read */
+         UInt     name = step_leb128U( &abbrev_img );
+         UInt     form = step_leb128U( &abbrev_img );
+         if (name == 0)
             break;
        
          /* Read data */
          /* Attributes encoding explained p 71 */
          if ( form == 0x16 /* FORM_indirect */ )
-            form = read_leb128U( &p );
+            form = step_leb128U( &p );
          /* Decode form. For most kinds, Just skip the amount of data since
             we don't use it for now */
          /* JRS 9 Feb 06: This now handles 64-bit DWARF too.  In
@@ -1079,62 +1029,108 @@
             handle FORM_addr too. */
          switch( form ) {
             /* Those cases extract the data properly */
-            case 0x05: /* FORM_data2 */     cval = ML_(read_UShort)(p); p +=2; break;
-            case 0x06: /* FORM_data4 */     cval = ML_(read_UInt)(p);   p +=4; break;
+            case 0x05: /* FORM_data2 */
+               cval = ML_(cur_step_UShort)(&p);
+               break;
+            case 0x06: /* FORM_data4 */
+               cval = ML_(cur_step_UInt)(&p);
+               break;
             case 0x0e: /* FORM_strp */      /* pointer in .debug_str */
-                       /* 2006-01-01: only generate a value if
-                          debugstr is non-NULL (which means that a
-                          debug_str section was found) */
-                                            if (debugstr_img && !ui->dw64)
-                                               sval = debugstr_img + ML_(read_UInt)(p); 
-                                            if (debugstr_img && ui->dw64)
-                                               sval = debugstr_img + ML_(read_ULong)(p); 
-                                            p += ui->dw64 ? 8 : 4; 
-                                            break;
-            case 0x08: /* FORM_string */    sval = (HChar*)p; 
-                                            p += VG_(strlen)(sval) + 1; break;
-            case 0x0b: /* FORM_data1 */     cval = *p; p++; break;
-            case 0x17: /* FORM_sec_offset */if (ui->dw64) {
-                                               cval = ML_(read_ULong)(p); p += 8;
-                                            } else {
-                                               cval = ML_(read_UInt)(p); p += 4;
-                                            }; break;
-
-            case 0x07: /* FORM_data8 */     if (ui->dw64) cval = ML_(read_ULong)(p);
-                                            p += 8; break;
-                                            /* perhaps should assign
-                                               unconditionally to cval? */
-
+               /* 2006-01-01: only generate a value if a debug_str
+                  section was found) */
+               if (ML_(cur_is_valid)(debugstr_img) && !ui->dw64)
+                  sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_UInt)(p));
+               if (ML_(cur_is_valid)(debugstr_img) && ui->dw64)
+                  sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_ULong)(p));
+               p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
+               break;
+            case 0x08: /* FORM_string */
+               sval = p;
+               p = ML_(cur_plus)(p, ML_(cur_strlen)(p) + 1);
+               break;
+            case 0x0b: /* FORM_data1 */
+               cval = ML_(cur_step_UChar)(&p);
+               break;
+            case 0x17: /* FORM_sec_offset */
+               if (ui->dw64) {
+                 cval = ML_(cur_step_ULong)(&p);
+               } else {
+                 cval = ML_(cur_step_UInt)(&p);
+               };
+               break;
+            case 0x07: /* FORM_data8 */
+               if (ui->dw64) cval = ML_(cur_read_ULong)(p);
+               p = ML_(cur_plus)(p, 8);
+               /* perhaps should assign unconditionally to cval? */
+               break;
             /* TODO : Following ones just skip data - implement if you need */
-            case 0x01: /* FORM_addr */      p += addr_size; break;
-            case 0x03: /* FORM_block2 */    p += ML_(read_UShort)(p) + 2; break;
-            case 0x04: /* FORM_block4 */    p += ML_(read_UInt)(p) + 4; break;
-            case 0x09: /* FORM_block */     /* fallthrough */
-            case 0x18: /* FORM_exprloc */   { ULong block_len = read_leb128U( &p );
-                                              p += block_len; break; }
-            case 0x0a: /* FORM_block1 */    p += *p + 1; break;
-            case 0x0c: /* FORM_flag */      p++; break;
-            case 0x0d: /* FORM_sdata */     read_leb128S( &p ); break;
-            case 0x0f: /* FORM_udata */     read_leb128U( &p ); break;
-            case 0x10: /* FORM_ref_addr */  p += (ver == 2) ? addr_size : (ui->dw64 ? 8 : 4); break;
-            case 0x11: /* FORM_ref1 */      p++; break;
-            case 0x12: /* FORM_ref2 */      p += 2; break;
-            case 0x13: /* FORM_ref4 */      p += 4; break;
-            case 0x14: /* FORM_ref8 */      p += 8; break;
-            case 0x15: /* FORM_ref_udata */ read_leb128U( &p ); break;
-            case 0x19: /* FORM_flag_present */break;
-            case 0x20: /* FORM_ref_sig8 */  p += 8; break;
-            case 0x1f20: /* FORM_GNU_ref_alt */ p += ui->dw64 ? 8 : 4; break;
+            case 0x01: /* FORM_addr */
+               p = ML_(cur_plus)(p, addr_size);
+               break;
+            case 0x03: /* FORM_block2 */
+               p = ML_(cur_plus)(p, ML_(cur_read_UShort)(p) + 2);
+               break;
+            case 0x04: /* FORM_block4 */
+               p = ML_(cur_plus)(p, ML_(cur_read_UInt)(p) + 4);
+               break;
+            case 0x09:   /* FORM_block */     /* fallthrough */
+            case 0x18: { /* FORM_exprloc */
+               ULong block_len = step_leb128U(&p);
+               p = ML_(cur_plus)(p, block_len);
+               break;
+            }
+            case 0x0a: /* FORM_block1 */
+               p = ML_(cur_plus)(p, ML_(cur_read_UChar)(p) + 1);
+               break;
+            case 0x0c: /* FORM_flag */
+               p = ML_(cur_plus)(p, 1);
+               break;
+            case 0x0d: /* FORM_sdata */
+               (void)step_leb128S(&p);
+               break;
+            case 0x0f: /* FORM_udata */
+               (void)step_leb128U(&p);
+               break;
+            case 0x10: /* FORM_ref_addr */
+               p = ML_(cur_plus)(p, (ver == 2) ? addr_size 
+                                               : (ui->dw64 ? 8 : 4));
+               break;
+            case 0x11: /* FORM_ref1 */
+               p = ML_(cur_plus)(p, 1);
+               break;
+            case 0x12: /* FORM_ref2 */
+               p = ML_(cur_plus)(p, 2);
+               break;
+            case 0x13: /* FORM_ref4 */
+               p = ML_(cur_plus)(p, 4);
+               break;
+            case 0x14: /* FORM_ref8 */
+               p = ML_(cur_plus)(p, 8);
+               break;
+            case 0x15: /* FORM_ref_udata */
+               (void)step_leb128U(&p);
+               break;
+            case 0x19: /* FORM_flag_present */
+               break;
+            case 0x20: /* FORM_ref_sig8 */
+               p = ML_(cur_plus)(p, 8);
+               break;
+            case 0x1f20: /* FORM_GNU_ref_alt */
+               p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
+               break;
             case 0x1f21: /* FORM_GNU_strp_alt */
-                                            if (debugstr_alt_img && !ui->dw64)
-                                               sval = debugstr_alt_img + ML_(read_UInt)(p);
-                                            if (debugstr_alt_img && ui->dw64)
-                                               sval = debugstr_alt_img + ML_(read_ULong)(p);
-                                            p += ui->dw64 ? 8 : 4; 
-                                            break;
+               if (ML_(cur_is_valid)(debugstr_alt_img) && !ui->dw64)
+                  sval = ML_(cur_plus)(debugstr_alt_img,
+                                       ML_(cur_read_UInt)(p));
+               if (ML_(cur_is_valid)(debugstr_alt_img) && ui->dw64)
+                  sval = ML_(cur_plus)(debugstr_alt_img,
+                                       ML_(cur_read_ULong)(p));
+               p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
+               break;
 
             default:
-               VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\n", form );
+               VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\n",
+                            form );
                break;
          }
          
@@ -1162,49 +1158,50 @@
  */
 void ML_(read_debuginfo_dwarf3)
         ( struct _DebugInfo* di,
-          UChar* debug_info_img, Word debug_info_sz, /* .debug_info */
-          UChar* debug_types_img, Word debug_types_sz, /* .debug_types */
-          UChar* debug_abbv_img, Word debug_abbv_sz, /* .debug_abbrev */
-          UChar* debug_line_img, Word debug_line_sz, /* .debug_line */
-          HChar* debug_str_img,  Word debug_str_sz, /* .debug_str */
-          HChar* debug_str_alt_img, Word debug_str_alt_sz ) /* .debug_str */
+          DiSlice escn_debug_info,      /* .debug_info */
+          DiSlice escn_debug_types,     /* .debug_types */
+          DiSlice escn_debug_abbv,      /* .debug_abbrev */
+          DiSlice escn_debug_line,      /* .debug_line */
+          DiSlice escn_debug_str,       /* .debug_str */
+          DiSlice escn_debug_str_alt )  /* .debug_str */
 {
    UnitInfo ui;
    UShort   ver;
-   UChar*   block_img;
-   UChar*   end1_img;
    ULong    blklen;
    Bool     blklen_is_64;
-   Int      blklen_len;
-
-   end1_img  = debug_info_img + debug_info_sz;
-   blklen_len = 0;
 
    /* Make sure we at least have a header for the first block */
-   if (debug_info_sz < 4) {
+   if (escn_debug_info.szB < 4) {
       ML_(symerr)( di, True, 
                    "Last block truncated in .debug_info; ignoring" );
       return;
    }
 
+   DiCursor block_img = DiCursor_INVALID;
+   DiCursor end1_img  = ML_(cur_plus)( ML_(cur_from_sli)(escn_debug_info), 
+                                       escn_debug_info.szB );
+   Int blklen_len = 0;
+
    /* Iterate on all the blocks we find in .debug_info */
-   for ( block_img = debug_info_img; 
-         block_img < end1_img - 4; 
-         block_img += blklen + blklen_len ) {
+   for ( block_img = ML_(cur_from_sli)(escn_debug_info);
+         ML_(cur_cmpLT)(block_img, ML_(cur_plus)(end1_img, -(DiOffT)4));
+         block_img = ML_(cur_plus)(block_img, blklen + blklen_len) ) {
 
       /* Read the compilation unit header in .debug_info section - See
          p 70 */
       /* This block length */
       blklen     = read_initial_length_field( block_img, &blklen_is_64 );
       blklen_len = blklen_is_64 ? 12 : 4;
-      if ( block_img + blklen + blklen_len > end1_img ) {
+
+      if (ML_(cur_cmpGT)( ML_(cur_plus)(block_img, blklen + blklen_len),
+                          end1_img )) {
          ML_(symerr)( di, True,
                       "Last block truncated in .debug_info; ignoring" );
          return;
       }
 
       /* version should be 2 */
-      ver = ML_(read_UShort)( block_img + blklen_len );
+      ver = ML_(cur_read_UShort)( ML_(cur_plus)(block_img, blklen_len) );
       if ( ver != 2 && ver != 3 && ver != 4 ) {
          ML_(symerr)( di, True,
                       "Ignoring non-Dwarf2/3/4 block in .debug_info" );
@@ -1213,26 +1210,40 @@
       
       /* Fill ui with offset in .debug_line and compdir */
       if (0)
-         VG_(printf)( "Reading UnitInfo at 0x%lx.....\n",
-                      block_img - debug_info_img + 0UL );
+         VG_(printf)(
+            "Reading UnitInfo at 0x%llx.....\n",
+            (ULong)ML_(cur_minus)( block_img,
+                                   ML_(cur_from_sli)(escn_debug_info)) );
       read_unitinfo_dwarf2( &ui, block_img, 
-                                 debug_abbv_img, debug_str_img,
-                                 debug_str_alt_img );
-      if (0)
+                                 ML_(cur_from_sli)(escn_debug_abbv),
+                                 ML_(cur_from_sli)(escn_debug_str),
+                                 ML_(cur_from_sli)(escn_debug_str_alt) );
+      if (0) {
+         HChar* str_name    = ML_(cur_read_strdup)(ui.name,    "di.rdd3.1");
+         HChar* str_compdir = ML_(cur_read_strdup)(ui.compdir, "di.rdd3.2");
          VG_(printf)( "   => LINES=0x%llx    NAME=%s     DIR=%s\n", 
-                      ui.stmt_list, ui.name, ui.compdir );
-      
+                      ui.stmt_list, str_name, str_compdir );
+         ML_(dinfo_free)(str_name);
+         ML_(dinfo_free)(str_compdir);
+      }
+
       /* Ignore blocks with no .debug_line associated block */
       if ( ui.stmt_list == -1LL )
          continue;
       
-      if (0) 
-         VG_(printf)("debug_line_sz %ld, ui.stmt_list %lld  %s\n",
-                     debug_line_sz, ui.stmt_list, ui.name );
+      if (0) {
+         HChar* str_name = ML_(cur_read_strdup)(ui.name, "di.rdd3.3");
+         VG_(printf)("debug_line_sz %lld, ui.stmt_list %lld  %s\n",
+                     escn_debug_line.szB, ui.stmt_list, str_name );
+         ML_(dinfo_free)(str_name);
+      }
+
       /* Read the .debug_line block for this compile unit */
-      read_dwarf2_lineblock( 
-         di, &ui, debug_line_img + ui.stmt_list, 
-                  debug_line_sz  - ui.stmt_list );
+      read_dwarf2_lineblock(
+         di, &ui,
+         ML_(cur_plus)(ML_(cur_from_sli)(escn_debug_line), ui.stmt_list),
+         escn_debug_line.szB  - ui.stmt_list
+      );
    }
 }
 
@@ -1391,7 +1402,7 @@
 };
 
 /* end of enums taken from gdb-6.0 sources */
-
+#if 0
 void ML_(read_debuginfo_dwarf1) ( 
         struct _DebugInfo* di, 
         UChar* dwarf1d, Int dwarf1d_sz, 
@@ -1534,7 +1545,7 @@
    } /* Looping over DIEs */
 
 }
-
+#endif
 
 /*------------------------------------------------------------*/
 /*--- Read call-frame info from an .eh_frame section       ---*/
@@ -2094,10 +2105,10 @@
 */
 typedef
    struct {
-      UChar  encoding;
-      UChar* ehframe_image;
-      Addr   ehframe_avma;
-      Addr   text_bias;
+      UChar    encoding;
+      DiCursor ehframe_image;
+      Addr     ehframe_avma;
+      Addr     text_bias;
    }
    AddressDecodingInfo;
 
@@ -2549,20 +2560,20 @@
 
 /* ------------ Pick apart DWARF2 byte streams ------------ */
 
-static ULong read_le_u_encoded_literal ( UChar* data, UInt size )
+static ULong step_le_u_encoded_literal ( DiCursor* data, UInt size )
 {
    switch (size) {
-      case 8:  return (ULong)ML_(read_ULong)( data );
-      case 4:  return (ULong)ML_(read_UInt)( data );
-      case 2:  return (ULong)ML_(read_UShort)( data );
-      case 1:  return (ULong)ML_(read_UChar)( data );
+      case 8:  return (ULong)ML_(cur_step_ULong)( data );
+      case 4:  return (ULong)ML_(cur_step_UInt)( data );
+      case 2:  return (ULong)ML_(cur_step_UShort)( data );
+      case 1:  return (ULong)ML_(cur_step_UChar)( data );
       default: vg_assert(0); /*NOTREACHED*/ return 0;
    }
 }
 
-static Long read_le_s_encoded_literal ( UChar* data, UInt size )
+static Long step_le_s_encoded_literal ( DiCursor* data, UInt size )
 {
-   Long s64 = read_le_u_encoded_literal( data, size );
+   Long s64 = step_le_u_encoded_literal( data, size );
    switch (size) {
       case 8:  break;
       case 4:  s64 <<= 32; s64 >>= 32; break;
@@ -2596,9 +2607,8 @@
    }
 }
 
-static Addr read_encoded_Addr ( /*OUT*/Int* nbytes,
-                                AddressDecodingInfo* adi,
-                                UChar* data )
+static Addr step_encoded_Addr ( AddressDecodingInfo* adi,
+                                /*MOD*/DiCursor* data )
 {
    /* Regarding the handling of DW_EH_PE_absptr.  DWARF3 says this
       denotes an absolute address, hence you would think 'base' is
@@ -2619,22 +2629,20 @@
          address at which the object was attached.  This offset is
          available in the run-time linker's data structures.
    */
-   Addr   base;
-   Word   offset;
-   UChar  encoding      = adi->encoding;
-   UChar* ehframe_image = adi->ehframe_image;
-   Addr   ehframe_avma  = adi->ehframe_avma;
+   Addr     base;
+   Word     offset;
+   UChar    encoding      = adi->encoding;
+   DiCursor ehframe_image = adi->ehframe_image;
+   Addr     ehframe_avma  = adi->ehframe_avma;
 
    vg_assert((encoding & DW_EH_PE_indirect) == 0);
 
-   *nbytes = 0;
-
    switch (encoding & 0x70) {
       case DW_EH_PE_absptr:
          base = adi->text_bias;
          break;
       case DW_EH_PE_pcrel:
-         base = ehframe_avma + ( data - ehframe_image );
+         base = ehframe_avma + ML_(cur_minus)(*data, ehframe_image);
          break;
       case DW_EH_PE_datarel:
          vg_assert(0);
@@ -2649,10 +2657,10 @@
          break;
       case DW_EH_PE_aligned:
          base = 0;
-         offset = data - ehframe_image;
+         offset = ML_(cur_minus)(*data, ehframe_image);
          if ((offset % sizeof(Addr)) != 0) {
-            *nbytes = sizeof(Addr) - (offset % sizeof(Addr));
-            data += *nbytes;
+            Word nbytes = sizeof(Addr) - (offset % sizeof(Addr));
+            *data = ML_(cur_plus)(*data, nbytes);
          }
          break;
       default:
@@ -2664,23 +2672,17 @@
 
    switch (encoding & 0x0f) {
       case DW_EH_PE_udata2:
-         *nbytes += sizeof(UShort);
-         return base + ML_(read_UShort)(data);
+         return base + ML_(cur_step_UShort)(data);
       case DW_EH_PE_udata4:
-         *nbytes += sizeof(UInt);
-         return base + ML_(read_UInt)(data);
+         return base + ML_(cur_step_UInt)(data);
       case DW_EH_PE_udata8:
-         *nbytes += sizeof(ULong);
-         return base + ML_(read_ULong)(data);
+         return base + ML_(cur_step_ULong)(data);
       case DW_EH_PE_sdata2:
-         *nbytes += sizeof(Short);
-         return base + ML_(read_Short)(data);
+         return base + ML_(cur_step_Short)(data);
       case DW_EH_PE_sdata4:
-         *nbytes += sizeof(Int);
-         return base + ML_(read_Int)(data);
+         return base + ML_(cur_step_Int)(data);
       case DW_EH_PE_sdata8:
-         *nbytes += sizeof(Long);
-         return base + ML_(read_Long)(data);
+         return base + ML_(cur_step_Long)(data);
       default:
          vg_assert2(0, "read encoded address %d\n", encoding & 0x0f);
    }
@@ -2695,7 +2697,7 @@
 /* IMPORTANT: when adding expression forms here, also remember to
    add suitable evaluation code in evalCfiExpr in debuginfo.c. */
 static Int dwarfexpr_to_dag ( UnwindContext* ctx, 
-                              UChar* expr, Int exprlen, 
+                              DiCursor expr, Int exprlen, 
                               Bool push_cfa_at_start,
                               Bool ddump_frames )
 {
@@ -2731,8 +2733,8 @@
    Int stack[N_EXPR_STACK];  /* indices into ctx->exprs */
    struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
 
-   XArray* dst   = ctx->exprs;
-   UChar*  limit = expr + exprlen;
+   XArray*  dst   = ctx->exprs;
+   DiCursor limit = ML_(cur_plus)(expr, exprlen);
 
    vg_assert(dst);
    vg_assert(exprlen >= 0);
@@ -2759,10 +2761,10 @@
 
       vg_assert(sp >= -1 && sp < N_EXPR_STACK);
 
-      if (expr > limit) 
+      if (ML_(cur_cmpGT)(expr, limit)) /* "expr > limit" */
          return -1;  /* overrun - something's wrong */
 
-      if (expr == limit) {
+      if (ML_(cur_cmpEQ)(expr, limit)) { /* "expr == limit" */
         /* end of expr - return expr on the top of stack. */
         if (sp == -1)
            return -1; /* stack empty.  Bad. */
@@ -2772,7 +2774,7 @@
 
       uop = 0; bop = 0; opname = NULL; /* excessively conservative */
 
-      opcode = *expr++;
+      opcode = ML_(cur_step_UChar)(&expr);
       switch (opcode) {
 
          case DW_OP_lit0 ... DW_OP_lit31:
@@ -2788,7 +2790,7 @@
             /* push: reg + sleb128 */
             reg = (Int)opcode - (Int)DW_OP_breg0;
             vg_assert(reg >= 0 && reg <= 31);
-            sw = read_leb128S( &expr );
+            sw = step_leb128S( &expr );
             ix = ML_(CfiExpr_Binop)( dst,
                     Cbinop_Add,
                     ML_(CfiExpr_DwReg)( dst, reg ),
@@ -2810,7 +2812,7 @@
             break;
 
          case DW_OP_plus_uconst:
-            uw = read_leb128U( &expr );
+            uw = step_leb128U( &expr );
             PUSH( ML_(CfiExpr_Const)( dst, uw ) );
             POP( ix );
             POP( ix2 );
@@ -2821,8 +2823,7 @@
 
          case DW_OP_const4s:
             /* push: 32-bit signed immediate */
-            sw = read_le_s_encoded_literal( expr, 4 );
-            expr += 4;
+            sw = step_le_s_encoded_literal( &expr, 4 );
             PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
             if (ddump_frames)
                VG_(printf)("DW_OP_const4s: %ld", sw);
@@ -2830,8 +2831,7 @@
 
          case DW_OP_const2s:
             /* push: 16-bit signed immediate */
-            sw = read_le_s_encoded_literal( expr, 2 );
-            expr += 2;
+            sw = step_le_s_encoded_literal( &expr, 2 );
             PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
             if (ddump_frames)
                VG_(printf)("DW_OP_const2s: %ld", sw);
@@ -2839,8 +2839,7 @@
 
          case DW_OP_const1s:
             /* push: 8-bit signed immediate */
-            sw = read_le_s_encoded_literal( expr, 1 );
-            expr += 1;
+            sw = step_le_s_encoded_literal( &expr, 1 );
             PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
             if (ddump_frames)
                VG_(printf)("DW_OP_const1s: %ld", sw);
@@ -2848,8 +2847,7 @@
 
          case DW_OP_const1u:
             /* push: 8-bit unsigned immediate */
-            uw = read_le_u_encoded_literal( expr, 1 );
-            expr += 1;
+            uw = step_le_u_encoded_literal( &expr, 1 );
             PUSH( ML_(CfiExpr_Const)( dst, uw ) );
             if (ddump_frames)
                VG_(printf)("DW_OP_const1: %lu", uw);
@@ -2857,8 +2855,7 @@
 
          case DW_OP_const2u:
             /* push: 16-bit unsigned immediate */
-            uw = read_le_u_encoded_literal( expr, 2 );
-            expr += 2;
+            uw = step_le_u_encoded_literal( &expr, 2 );
             PUSH( ML_(CfiExpr_Const)( dst, uw ) );
             if (ddump_frames)
                VG_(printf)("DW_OP_const2: %lu", uw);
@@ -2866,8 +2863,7 @@
 
          case DW_OP_const4u:
             /* push: 32-bit unsigned immediate */
-            uw = read_le_u_encoded_literal( expr, 4 );
-            expr += 4;
+            uw = step_le_u_encoded_literal( &expr, 4 );
             PUSH( ML_(CfiExpr_Const)( dst, uw ) );
             if (ddump_frames)
                VG_(printf)("DW_OP_const4: %lu", uw);
@@ -2933,7 +2929,7 @@
             return -1;
       }
 
-      if (expr < limit && ddump_frames)
+      if (ML_(cur_cmpLT)(expr, limit) && ddump_frames)
          VG_(printf)("; ");
 
    }
@@ -2958,21 +2954,20 @@
    Returns 0 if the instruction could not be executed. 
 */
 static Int run_CF_instruction ( /*MOD*/UnwindContext* ctx, 
-                                UChar* instr,
+                                DiCursor instrIN,
                                 UnwindContext* restore_ctx,
                                 AddressDecodingInfo* adi,
                                 struct _DebugInfo* di )
 {
-   Int    off, reg, reg2, nleb, len;
-   UInt   delta;
-   UChar* expr;
-   Int    j;
-   Int    i   = 0;
-   UChar  hi2 = (instr[i] >> 6) & 3;
-   UChar  lo6 = instr[i] & 0x3F;
-   Addr   printing_bias = ((Addr)ctx->initloc) - ((Addr)di->text_bias);
+   Int      off, reg, reg2, len, j;
+   UInt     delta;
+   Addr     printing_bias = ((Addr)ctx->initloc) - ((Addr)di->text_bias);
    struct UnwindContextState* ctxs;
-   i++;
+
+   DiCursor instr   = instrIN;
+   UChar    instr_0 = ML_(cur_step_UChar)(&instr);
+   UChar    hi2     = (instr_0 >> 6) & 3;
+   UChar    lo6     = instr_0 & 0x3F;
 
    if (ctx->state_sp < 0 || ctx->state_sp >= N_RR_STACK)
       return 0; /* bogus reg-rule stack pointer */
@@ -2985,13 +2980,12 @@
       if (di->ddump_frames)
          VG_(printf)("  DW_CFA_advance_loc: %d to %08lx\n", 
                      (Int)delta, (Addr)ctx->loc + printing_bias);
-      return i;
+      return ML_(cur_minus)(instr, instrIN);
    }
 
    if (hi2 == DW_CFA_offset) {
       /* Set rule for reg 'lo6' to CFAOff(off * data_af) */
-      off = read_leb128( &instr[i], &nleb, 0 );
-      i += nleb;
+      off = step_leb128( &instr, 0 );
       reg = (Int)lo6;
       if (reg < 0 || reg >= N_CFI_REGS) 
          return 0; /* fail */
@@ -3002,7 +2996,7 @@
                      (Int)reg,
                      ctxs->reg[reg].arg < 0 ? "" : "+", 
                      (Int)ctxs->reg[reg].arg );
-      return i;
+      return ML_(cur_minus)(instr, instrIN);
    }
 
    if (hi2 == DW_CFA_restore) {
@@ -3014,7 +3008,7 @@
       ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
       if (di->ddump_frames)
          VG_(printf)("  DW_CFA_restore: r%d\n", (Int)reg);
-      return i;
+      return ML_(cur_minus)(instr, instrIN);
    }
 
    vg_assert(hi2 == DW_CFA_use_secondary);
@@ -3031,13 +3025,12 @@
          /* 2007 Feb 23: No.  binutils/dwarf.c treats it as an encoded
             address and that appears to be in accordance with the
             DWARF3 spec. */
-         ctx->loc = read_encoded_Addr(&len, adi, &instr[i]);
-         i += len;
+         ctx->loc = step_encoded_Addr(adi, &instr);
          if (di->ddump_frames)
             VG_(printf)("  rci:DW_CFA_set_loc\n");
          break;
       case DW_CFA_advance_loc1:
-         delta = (UInt)ML_(read_UChar)(&instr[i]); i+= sizeof(UChar);
+         delta = (UInt)ML_(cur_step_UChar)(&instr);
          delta *= ctx->code_a_f;
          ctx->loc += delta;
          if (di->ddump_frames)
@@ -3045,7 +3038,7 @@
                         (Int)delta, (Addr)ctx->loc + printing_bias);
          break;
       case DW_CFA_advance_loc2:
-         delta = (UInt)ML_(read_UShort)(&instr[i]); i+= sizeof(UShort);
+         delta = (UInt)ML_(cur_step_UShort)(&instr);
          delta *= ctx->code_a_f;
          ctx->loc += delta;
          if (di->ddump_frames)
@@ -3053,7 +3046,7 @@
                         (Int)delta, (Addr)ctx->loc + printing_bias);
          break;
       case DW_CFA_advance_loc4:
-         delta = (UInt)ML_(read_UInt)(&instr[i]); i+= sizeof(UInt);
+         delta = (UInt)ML_(cur_step_UInt)(&instr);
          delta *= ctx->code_a_f;
          ctx->loc += delta;
          if (di->ddump_frames)
@@ -3062,10 +3055,8 @@
          break;
 
       case DW_CFA_def_cfa:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          if (reg < 0 || reg >= N_CFI_REGS) 
             return 0; /* fail */
          ctxs->cfa_is_regoff = True;
@@ -3077,10 +3068,8 @@
          break;
 
       case DW_CFA_def_cfa_sf:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 1 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 1 );
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
          ctxs->cfa_is_regoff = True;
@@ -3092,10 +3081,8 @@
          break;
 
       case DW_CFA_register:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
-         reg2 = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg  = step_leb128( &instr, 0 );
+         reg2 = step_leb128( &instr, 0 );
          if (reg < 0 || reg >= N_CFI_REGS) 
             return 0; /* fail */
          if (reg2 < 0 || reg2 >= N_CFI_REGS) 
@@ -3108,10 +3095,8 @@
          break;
 
       case DW_CFA_offset_extended:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
          ctxs->reg[reg].tag = RR_CFAOff;
@@ -3121,10 +3106,8 @@
          break;
 
       case DW_CFA_offset_extended_sf:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 1 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 1 );
          if (reg < 0 || reg >= N_CFI_REGS) 
             return 0; /* fail */
          ctxs->reg[reg].tag = RR_CFAOff;
@@ -3137,10 +3120,8 @@
          break;
 
       case DW_CFA_GNU_negative_offset_extended:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
          ctxs->reg[reg].tag = RR_CFAOff;
@@ -3150,8 +3131,7 @@
          break;
 
       case DW_CFA_restore_extended:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
 	 if (restore_ctx == NULL)
@@ -3162,10 +3142,8 @@
          break;
 
       case DW_CFA_val_offset:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
          ctxs->reg[reg].tag = RR_CFAValOff;
@@ -3175,10 +3153,8 @@
          break;
 
       case DW_CFA_val_offset_sf:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 1 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 1 );
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
          ctxs->reg[reg].tag = RR_CFAValOff;
@@ -3188,8 +3164,7 @@
          break;
 
       case DW_CFA_def_cfa_register:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg = step_leb128( &instr, 0);
          if (reg < 0 || reg >= N_CFI_REGS) 
             return 0; /* fail */
          ctxs->cfa_is_regoff = True;
@@ -3201,8 +3176,7 @@
          break;
 
       case DW_CFA_def_cfa_offset:
-         off = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         off = step_leb128( &instr, 0);
          ctxs->cfa_is_regoff = True;
          ctxs->cfa_expr_ix   = 0;
          /* ->reg is unchanged */
@@ -3212,8 +3186,7 @@
          break;
 
       case DW_CFA_def_cfa_offset_sf:
-         off = read_leb128( &instr[i], &nleb, 1);
-         i += nleb;
+         off = step_leb128( &instr, 1);
          ctxs->cfa_is_regoff = True;
          ctxs->cfa_expr_ix   = 0;
          /* ->reg is unchanged */
@@ -3223,8 +3196,7 @@
          break;
 
       case DW_CFA_undefined:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg = step_leb128( &instr, 0);
          if (reg < 0 || reg >= N_CFI_REGS) 
             return 0; /* fail */
          ctxs->reg[reg].tag = RR_Undef;
@@ -3234,8 +3206,7 @@
          break;
 
       case DW_CFA_same_value:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg = step_leb128( &instr, 0);
          if (reg < 0 || reg >= N_CFI_REGS) 
             return 0; /* fail */
          ctxs->reg[reg].tag = RR_Same;
@@ -3247,22 +3218,20 @@
       case DW_CFA_GNU_args_size:
          /* No idea what is supposed to happen.  gdb-6.3 simply
             ignores these. */
-         /*off = */ read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         /*off = */ (void)step_leb128( &instr, 0 );
          if (di->ddump_frames)
             VG_(printf)("  rci:DW_CFA_GNU_args_size (ignored)\n");
          break;
 
-      case DW_CFA_expression:
+      case DW_CFA_expression: {
          /* Identical to DW_CFA_val_expression except that the value
             computed is an address and so needs one final
             dereference. */
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         len = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         expr = &instr[i];
-         i += len;
+         DiCursor expr;
+         reg = step_leb128( &instr, 0 );
+         len = step_leb128( &instr, 0 );
+         expr = instr;
+         instr = ML_(cur_plus)(instr, len);
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
          if (di->ddump_frames)
@@ -3286,14 +3255,14 @@
          ctxs->reg[reg].tag = RR_ValExpr;
          ctxs->reg[reg].arg = j;
          break;
+      }
 
-      case DW_CFA_val_expression:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         len = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         expr = &instr[i];
-         i += len;
+      case DW_CFA_val_expression: {
+         DiCursor expr;
+         reg = step_leb128( &instr, 0 );
+         len = step_leb128( &instr, 0 );
+         expr = instr;
+         instr = ML_(cur_plus)(instr, len);
          if (reg < 0 || reg >= N_CFI_REGS)
             return 0; /* fail */
          if (di->ddump_frames)
@@ -3315,12 +3284,13 @@
          ctxs->reg[reg].tag = RR_ValExpr;
          ctxs->reg[reg].arg = j;
          break;
+      }
 
-      case DW_CFA_def_cfa_expression:
-         len = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         expr = &instr[i];
-         i += len;
+      case DW_CFA_def_cfa_expression: {
+         DiCursor expr;
+         len = step_leb128( &instr, 0 );
+         expr = instr;
+         instr = ML_(cur_plus)(instr, len);
          if (di->ddump_frames)
             VG_(printf)("  DW_CFA_def_cfa_expression (");
          /* Convert the expression into a dag rooted at ctx->exprs index j,
@@ -3334,6 +3304,7 @@
          ctxs->cfa_off       = 0;
          ctxs->cfa_expr_ix   = j;
          break;
+      }
 
       case DW_CFA_GNU_window_save:
          /* Ignored.  This appears to be sparc-specific; quite why it
@@ -3352,7 +3323,7 @@
             /* stack overflow.  We're hosed. */
             VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: N_RR_STACK is "
                                       "too low; increase and recompile.");
-            i = 0; /* indicate failure */
+            return 0; /* indicate failure */
          } else {
             VG_(memcpy)(/*dst*/&ctx->state[ctx->state_sp],
                         /*src*/&ctx->state[ctx->state_sp - 1],
@@ -3366,8 +3337,8 @@
          /* we just checked this at entry, so: */
          vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
          if (ctx->state_sp == 0) {
-            /* stack overflow.  Give up. */
-            i = 0; /* indicate failure */
+            /* stack undefflow.  Give up. */
+            return 0; /* indicate failure */
          } else {
             /* simply fall back to previous entry */
             ctx->state_sp--;
@@ -3379,11 +3350,11 @@
                                    "instruction 0:%d\n", (Int)lo6); 
          if (di->ddump_frames)
             VG_(printf)("  rci:run_CF_instruction:default\n");
-         i = 0;
-         break;
+         return 0; /* failure */
+         /*NOTREACHED*/
    }
 
-   return i;   
+   return ML_(cur_minus)(instr, instrIN);
 }
 
 
@@ -3391,40 +3362,48 @@
    close as possible (preferably identical) to how GNU binutils
    readelf --debug-dump=frames would. */
 
-static Int show_CF_instruction ( UChar* instr,
+static Int show_CF_instruction ( DiCursor instrIN,
                                  AddressDecodingInfo* adi,
                                  Int code_a_f, Int data_a_f )
 {
-   UInt  delta;
-   Int   off, coff, reg, reg2, nleb, len;
-   Addr  loc;
-   Int   i   = 0;
-   UChar hi2 = (instr[i] >> 6) & 3;
-   UChar lo6 = instr[i] & 0x3F;
-   i++;
+   Int      off, coff, reg, reg2, len;
+   UInt     delta;
+   Addr     loc;
+   DiCursor instr   = instrIN;
+   UChar    instr_0 = ML_(cur_step_UChar)(&instr);
+   UChar    hi2     = (instr_0 >> 6) & 3;
+   UChar    lo6     = instr_0 & 0x3F;
 
-   if (0) VG_(printf)("raw:%x/%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
-                      hi2, lo6,
-                      instr[i+0], instr[i+1], instr[i+2], instr[i+3],
-                      instr[i+4], instr[i+5], instr[i+6], instr[i+7] );
+   if (0) {
+      DiCursor tmpi = instrIN;
+      UInt i_0 = ML_(cur_step_UChar)(&tmpi);
+      UInt i_1 = ML_(cur_step_UChar)(&tmpi);
+      UInt i_2 = ML_(cur_step_UChar)(&tmpi);
+      UInt i_3 = ML_(cur_step_UChar)(&tmpi);
+      UInt i_4 = ML_(cur_step_UChar)(&tmpi);
+      UInt i_5 = ML_(cur_step_UChar)(&tmpi);
+      UInt i_6 = ML_(cur_step_UChar)(&tmpi);
+      UInt i_7 = ML_(cur_step_UChar)(&tmpi);
+      VG_(printf)("raw:%x/%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
+                  hi2, lo6, i_0, i_1, i_2, i_3, i_4, i_5, i_6, i_7);
+   }
    
    if (hi2 == DW_CFA_advance_loc) {
       VG_(printf)("  sci:DW_CFA_advance_loc(%d)\n", (Int)lo6);
-      return i;
+      return ML_(cur_minus)(instr, instrIN);
    }
 
    if (hi2 == DW_CFA_offset) {
-      off = read_leb128( &instr[i], &nleb, 0 );
-      i += nleb;
+      off = step_leb128( &instr, 0 );
       coff = off * data_a_f;
       VG_(printf)("  DW_CFA_offset: r%d at cfa%s%d\n",
                   (Int)lo6, coff < 0 ? "" : "+", (Int)coff );
-      return i;
+      return ML_(cur_minus)(instr, instrIN);
    }
 
    if (hi2 == DW_CFA_restore) {
       VG_(printf)("  sci:DW_CFA_restore(r%d)\n", (Int)lo6);
-      return i;
+      return ML_(cur_minus)(instr, instrIN);
    }
 
    vg_assert(hi2 == DW_CFA_use_secondary);
@@ -3438,84 +3417,71 @@
       case DW_CFA_set_loc:
          /* WAS: loc = read_Addr(&instr[i]); i+= sizeof(Addr); 
             (now known to be incorrect -- the address is encoded) */
-         loc = read_encoded_Addr(&len, adi, &instr[i]);
-         i += len;
+         loc = step_encoded_Addr(adi, &instr);
          VG_(printf)("  sci:DW_CFA_set_loc(%#lx)\n", loc);
          break;
 
       case DW_CFA_advance_loc1:
-         delta = (UInt)ML_(read_UChar)(&instr[i]); i+= sizeof(UChar);
+         delta = (UInt)ML_(cur_step_UChar)(&instr);
          VG_(printf)("  sci:DW_CFA_advance_loc1(%d)\n", delta); 
          break;
 
       case DW_CFA_advance_loc2:
-         delta = (UInt)ML_(read_UShort)(&instr[i]); i+= sizeof(UShort);
+         delta = (UInt)ML_(cur_step_UShort)(&instr);
          VG_(printf)("  sci:DW_CFA_advance_loc2(%d)\n", delta); 
          break;
 
       case DW_CFA_advance_loc4:
-         delta = (UInt)ML_(read_UInt)(&instr[i]); i+= sizeof(UInt);
+         delta = (UInt)ML_(cur_step_UInt)(&instr);
          VG_(printf)("  DW_CFA_advance_loc4(%d)\n", delta); 
          break;
 
       case DW_CFA_def_cfa:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          VG_(printf)("  DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off); 
          break;
 
       case DW_CFA_def_cfa_sf:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 1 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 1 );
          VG_(printf)("  DW_CFA_def_cfa_sf: r%d ofs %d\n", 
                      (Int)reg, (Int)(off * data_a_f));
          break;
 
       case DW_CFA_register:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
-         reg2 = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg  = step_leb128( &instr, 0);
+         reg2 = step_leb128( &instr, 0);
          VG_(printf)("  sci:DW_CFA_register(r%d, r%d)\n", reg, reg2); 
          break;
 
       case DW_CFA_def_cfa_register:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg = step_leb128( &instr, 0);
          VG_(printf)("  sci:DW_CFA_def_cfa_register(r%d)\n", reg); 
          break;
 
       case DW_CFA_def_cfa_offset: 
-         off = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         off = step_leb128( &instr, 0);
          VG_(printf)("  sci:DW_CFA_def_cfa_offset(%d)\n", off); 
          break;
 
       case DW_CFA_def_cfa_offset_sf:
-         off = read_leb128( &instr[i], &nleb, 1);
-         i += nleb;
+         off = step_leb128( &instr, 1);
          VG_(printf)("  sci:DW_CFA_def_cfa_offset_sf(%d)\n", off);
          break;
 
       case DW_CFA_restore_extended:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg = step_leb128( &instr, 0);
          VG_(printf)("  sci:DW_CFA_restore_extended(r%d)\n", reg);
          break;
 
       case DW_CFA_undefined:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg = step_leb128( &instr, 0);
          VG_(printf)("  sci:DW_CFA_undefined(r%d)\n", reg);
          break;
 
       case DW_CFA_same_value:
-         reg = read_leb128( &instr[i], &nleb, 0);
-         i += nleb;
+         reg = step_leb128( &instr, 0);
          VG_(printf)("  sci:DW_CFA_same_value(r%d)\n", reg);
          break;
 
@@ -3528,78 +3494,62 @@
          break;
 
       case DW_CFA_GNU_args_size:
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         off = step_leb128( &instr, 0 );
          VG_(printf)("  sci:DW_CFA_GNU_args_size(%d)\n", off ); 
          break;
 
       case DW_CFA_def_cfa_expression:
-         len = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         i += len;
+         len = step_leb128( &instr, 0 );
+         instr = ML_(cur_plus)(instr, len);
          VG_(printf)("  sci:DW_CFA_def_cfa_expression(length %d)\n", len);
          break;
 
       case DW_CFA_expression:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         len = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         i += len;
+         reg = step_leb128( &instr, 0 );
+         len = step_leb128( &instr, 0 );
+         instr = ML_(cur_plus)(instr, len);
          VG_(printf)("  sci:DW_CFA_expression(r%d, length %d)\n", reg, len);
          break;
 
       case DW_CFA_val_expression:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         len = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         i += len;
+         reg = step_leb128( &instr, 0 );
+         len = step_leb128( &instr, 0 );
+         instr = ML_(cur_plus)(instr, len);
          VG_(printf)("  sci:DW_CFA_val_expression(r%d, length %d)\n", reg, len);
          break;
 
       case DW_CFA_offset_extended:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          VG_(printf)("  sci:DW_CFA_offset_extended(r%d, "
                      "off %d x data_af)\n", reg, off);
          break;
 
       case DW_CFA_offset_extended_sf:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 1 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 1 );
 	 coff = (Int)(off * data_a_f);
          VG_(printf)("  DW_CFA_offset_extended_sf: r%d at cfa%s%d\n", 
                         reg, coff < 0 ? "" : "+", coff);
          break;
 
       case DW_CFA_GNU_negative_offset_extended:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          VG_(printf)("  sci:DW_CFA_GNU_negative_offset_extended"
                      "(r%d, off %d x data_af)\n", reg, -off);
          break;
 
       case DW_CFA_val_offset:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 0 );
          VG_(printf)("  sci:DW_CFA_val_offset(r%d, off %d x data_af)\n", 
                      reg, off);
          break;
 
        case DW_CFA_val_offset_sf:
-         reg = read_leb128( &instr[i], &nleb, 0 );
-         i += nleb;
-         off = read_leb128( &instr[i], &nleb, 1 );
-         i += nleb;
+         reg = step_leb128( &instr, 0 );
+         off = step_leb128( &instr, 1 );
          VG_(printf)("  sci:DW_CFA_val_offset_sf(r%d, off %d x data_af)\n", 
                      reg, off);
          break;
@@ -3613,19 +3563,20 @@
          break;
    }
 
-   return i;
+   return ML_(cur_minus)(instr, instrIN);
 }
 
 
 /* Show the instructions in instrs[0 .. ilen-1]. */
-static void show_CF_instructions ( UChar* instrs, Int ilen,
+static void show_CF_instructions ( DiCursor instrs, Int ilen,
                                    AddressDecodingInfo* adi,
                                    Int code_a_f, Int data_a_f )
 {
    Int i = 0;
    while (True) {
       if (i >= ilen) break;
-      i += show_CF_instruction( &instrs[i], adi, code_a_f, data_a_f );
+      i += show_CF_instruction( ML_(cur_plus)(instrs, i),
+                                adi, code_a_f, data_a_f );
    }
 }
 
@@ -3636,7 +3587,7 @@
 static 
 Bool run_CF_instructions ( struct _DebugInfo* di,
                            Bool record,
-                           UnwindContext* ctx, UChar* instrs, Int ilen,
+                           UnwindContext* ctx, DiCursor instrs, Int ilen,
                            UWord fde_arange,
                            UnwindContext* restore_ctx,
                            AddressDecodingInfo* adi )
@@ -3650,9 +3601,10 @@
    while (True) {
       loc_prev = ctx->loc;
       if (i >= ilen) break;
-      if (0) (void)show_CF_instruction( &instrs[i], adi, 
+      if (0) (void)show_CF_instruction( ML_(cur_plus)(instrs,i), adi, 
                                         ctx->code_a_f, ctx->data_a_f );
-      j = run_CF_instruction( ctx, &instrs[i], restore_ctx, adi, di );
+      j = run_CF_instruction( ctx, ML_(cur_plus)(instrs,i),
+                              restore_ctx, adi, di );
       if (j == 0)
          return False; /* execution failed */
       i += j;
@@ -3687,19 +3639,18 @@
 typedef
    struct {
       /* This gives the CIE an identity to which FDEs will refer. */
-      ULong  offset;
+      ULong    offset;
       /* Code, data factors. */
-      Int    code_a_f;
-      Int    data_a_f;
+      Int      code_a_f;
+      Int      data_a_f;
       /* Return-address pseudo-register. */
-      Int    ra_reg;
-      UChar  address_encoding;
-      /* Where are the instrs?  Note, this are simply pointers back to
-         the transiently-mapped-in section. */
-      UChar* instrs;
-      Int    ilen;
+      Int      ra_reg;
+      UChar    address_encoding;
+      /* Where are the instrs? */
+      DiCursor instrs;
+      Int      ilen;
       /* God knows .. don't ask */
-      Bool   saw_z_augmentation;
+      Bool     saw_z_augmentation;
    }
    CIE;
 
@@ -3710,7 +3661,7 @@
    cie->data_a_f           = 0;
    cie->ra_reg             = 0;
    cie->address_encoding   = 0;
-   cie->instrs             = NULL;
+   cie->instrs             = DiCursor_INVALID;
    cie->ilen               = 0;
    cie->saw_z_augmentation = False;
 }
@@ -3724,14 +3675,14 @@
    dealing with -- they are slightly different. */
 void ML_(read_callframe_info_dwarf3)
         ( /*OUT*/struct _DebugInfo* di,
-          UChar* frame_image, SizeT frame_size, Addr frame_avma,
-          Bool is_ehframe )
+          DiSlice escn_frame, Addr frame_avma, Bool is_ehframe )
 {
-   Int    nbytes;
    const HChar* how = NULL;
-   Int    n_CIEs = 0;
-   UChar* data = frame_image;
-   UWord  cfsi_used_orig;
+   Int      n_CIEs = 0;
+   DiCursor frame_image = ML_(cur_from_sli)(escn_frame); /* fixed */
+   DiOffT   frame_size  = escn_frame.szB;
+   DiCursor data        = frame_image;
+   UWord    cfsi_used_orig;
 
    /* If we're dealing with a .debug_frame, assume zero frame_avma. */
    if (!is_ehframe)
@@ -3757,10 +3708,9 @@
 
    if (di->trace_cfi) {
       VG_(printf)("\n-----------------------------------------------\n");
-      VG_(printf)("CFI info: szB %ld, _avma %#lx, _image %p\n",
-                  frame_size, frame_avma, frame_image );
-      VG_(printf)("CFI info: name %s\n",
-                  di->fsm.filename );
+      VG_(printf)("CFI info: szB %lld, _avma %#lx\n",
+                  escn_frame.szB, frame_avma );
+      VG_(printf)("CFI info: name %s\n", di->fsm.filename );
    }
 
    /* Loop over CIEs/FDEs */
@@ -3785,17 +3735,17 @@
       previously-seen CIE.
    */
    while (True) {
-      UChar* ciefde_start;
-      ULong  ciefde_len;
-      ULong  cie_pointer;
-      Bool   dw64;
+      DiCursor ciefde_start;
+      ULong    ciefde_len;
+      ULong    cie_pointer;
+      Bool     dw64;
 
       /* Are we done? */
-      if (data == frame_image + frame_size)
+      if (ML_(cur_cmpEQ)(data, ML_(cur_plus)(frame_image, frame_size)))
          return;
 
       /* Overshot the end?  Means something is wrong */
-      if (data > frame_image + frame_size) {
+      if (ML_(cur_cmpGT)(data, ML_(cur_plus)(frame_image, frame_size))) {
          how = "overran the end of .eh_frame";
          goto bad;
       }
@@ -3805,11 +3755,10 @@
 
       ciefde_start = data;
       if (di->trace_cfi) 
-         VG_(printf)("\ncie/fde.start   = %p (frame_image + 0x%lx)\n", 
-                     ciefde_start,
-                     ciefde_start - frame_image + 0UL);
+         VG_(printf)("\ncie/fde.start   = (frame_image + 0x%llx)\n", 
+                     ML_(cur_minus)(ciefde_start, frame_image));
 
-      ciefde_len = (ULong)ML_(read_UInt)(data); data += sizeof(UInt);
+      ciefde_len = (ULong)ML_(cur_step_UInt)(&data);
       if (di->trace_cfi) 
          VG_(printf)("cie/fde.length  = %lld\n", ciefde_len);
 
@@ -3819,8 +3768,8 @@
          places where .eh_frame and .debug_frame data differ. */
       if (ciefde_len == 0) {
          if (di->ddump_frames)
-            VG_(printf)("%08lx ZERO terminator\n\n",
-                        ((Addr)ciefde_start) - ((Addr)frame_image));
+            VG_(printf)("%08llx ZERO terminator\n\n",
+                        ML_(cur_minus)(ciefde_start, frame_image));
          return;
       }
 
@@ -3830,17 +3779,17 @@
       dw64 = False;
       if (ciefde_len == 0xFFFFFFFFUL) {
          dw64 = True;
-         ciefde_len = ML_(read_ULong)(data); data += sizeof(ULong);
+         ciefde_len = ML_(cur_step_ULong)(&data);
       }
 
       /* Now get the CIE ID, whose size depends on the DWARF 32 vs
 	 64-ness. */
       if (dw64) {
-         cie_pointer = ML_(read_ULong)(data); 
-         data += sizeof(ULong); /* XXX see XXX below */
+         /* see XXX below */
+         cie_pointer = ML_(cur_step_ULong)(&data); 
       } else {
-         cie_pointer = (ULong)ML_(read_UInt)(data); 
-         data += sizeof(UInt); /* XXX see XXX below */
+         /* see XXX below */
+         cie_pointer = (ULong)ML_(cur_step_UInt)(&data); 
       }
 
       if (di->trace_cfi) 
@@ -3851,9 +3800,9 @@
       if (cie_pointer == (is_ehframe ? 0ULL
                           : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
 
-         Int    this_CIE;
-         UChar  cie_version;
-         HChar* cie_augmentation;
+         Int      this_CIE;
+         UChar    cie_version;
+         DiCursor cie_augmentation;
 
          /* --------- CIE --------- */
 	 if (di->trace_cfi) 
@@ -3873,15 +3822,16 @@
 
 	 /* Record its offset.  This is how we will find it again
             later when looking at an FDE. */
-         the_CIEs[this_CIE].offset = (ULong)(ciefde_start - frame_image);
+         the_CIEs[this_CIE].offset
+            = (ULong)ML_(cur_minus)(ciefde_start, frame_image);
 
          if (di->ddump_frames)
             VG_(printf)("%08lx %08lx %08lx CIE\n",
-                        ((Addr)ciefde_start) - ((Addr)frame_image),
+                        (Addr)ML_(cur_minus)(ciefde_start, frame_image),
                         (Addr)ciefde_len,
                         (Addr)(UWord)cie_pointer );
 
-         cie_version = ML_(read_UChar)(data); data += sizeof(UChar);
+         cie_version = ML_(cur_step_UChar)(&data);
          if (di->trace_cfi)
             VG_(printf)("cie.version     = %d\n", (Int)cie_version);
          if (di->ddump_frames)
@@ -3891,33 +3841,37 @@
             goto bad;
          }
 
-         cie_augmentation = (HChar *)data;
-         data += 1 + VG_(strlen)(cie_augmentation);
-         if (di->trace_cfi) 
-            VG_(printf)("cie.augment     = \"%s\"\n", cie_augmentation);
-         if (di->ddump_frames)
-            VG_(printf)("  Augmentation:          \"%s\"\n", cie_augmentation);
+         cie_augmentation = data;
+         data = ML_(cur_plus)(data, 1 + ML_(cur_strlen)(cie_augmentation));
 
-         if (cie_augmentation[0] == 'e' && cie_augmentation[1] == 'h') {
-            data += sizeof(Addr);
-            cie_augmentation += 2;
+         if (di->trace_cfi || di->ddump_frames) {
+            HChar* str = ML_(cur_read_strdup)(cie_augmentation, "di.rcid3.1");
+            if (di->trace_cfi) 
+               VG_(printf)("cie.augment     = \"%s\"\n", str);
+            if (di->ddump_frames)
+               VG_(printf)("  Augmentation:          \"%s\"\n", str);
+            ML_(dinfo_free)(str);
+         }
+
+         if (ML_(cur_read_UChar)(cie_augmentation) == 'e'
+             && ML_(cur_read_UChar)
+                   (ML_(cur_plus)(cie_augmentation, 1)) == 'h') {
+            data = ML_(cur_plus)(data, sizeof(Addr));
+            cie_augmentation = ML_(cur_plus)(cie_augmentation, 2);
          }
 
          if (cie_version >= 4) {
-            if (ML_(read_UChar)(data) != sizeof(Addr)) {
+            if (ML_(cur_step_UChar)(&data) != sizeof(Addr)) {
                how = "unexpected address size";
                goto bad;
             }
-            data += sizeof(UChar);
-            if (ML_(read_UChar)(data) != 0) {
+            if (ML_(cur_step_UChar)(&data) != 0) {
                how = "unexpected non-zero segment size";
                goto bad;
             }
-            data += sizeof(UChar);
          }
 
-         the_CIEs[this_CIE].code_a_f = read_leb128( data, &nbytes, 0);
-         data += nbytes;
+         the_CIEs[this_CIE].code_a_f = step_leb128( &data, 0);
          if (di->trace_cfi) 
             VG_(printf)("cie.code_af     = %d\n", 
                         the_CIEs[this_CIE].code_a_f);
@@ -3925,8 +3879,7 @@
             VG_(printf)("  Code alignment factor: %d\n",
                         (Int)the_CIEs[this_CIE].code_a_f);
 
-         the_CIEs[this_CIE].data_a_f = read_leb128( data, &nbytes, 1);
-         data += nbytes;
+         the_CIEs[this_CIE].data_a_f = step_leb128( &data, 1);
          if (di->trace_cfi) 
             VG_(printf)("cie.data_af     = %d\n",
                         the_CIEs[this_CIE].data_a_f);
@@ -3935,11 +3888,9 @@
                         (Int)the_CIEs[this_CIE].data_a_f);
 
          if (cie_version == 1) {
-            the_CIEs[this_CIE].ra_reg = (Int)ML_(read_UChar)(data); 
-            data += sizeof(UChar);
+            the_CIEs[this_CIE].ra_reg = (Int)ML_(cur_step_UChar)(&data); 
          } else {
-            the_CIEs[this_CIE].ra_reg = read_leb128( data, &nbytes, 0);
-            data += nbytes;
+            the_CIEs[this_CIE].ra_reg = step_leb128( &data, 0);
          }
          if (di->trace_cfi) 
             VG_(printf)("cie.ra_reg      = %d\n", 
@@ -3955,46 +3906,47 @@
          }
 
          the_CIEs[this_CIE].saw_z_augmentation 
-            = *cie_augmentation == 'z';
+            = ML_(cur_read_UChar)(cie_augmentation) == 'z';
          if (the_CIEs[this_CIE].saw_z_augmentation) {
-            UInt length = read_leb128( data, &nbytes, 0);
-            data += nbytes;
-            the_CIEs[this_CIE].instrs = data + length;
-            cie_augmentation++;
+            UInt length = step_leb128( &data, 0);
+            the_CIEs[this_CIE].instrs = ML_(cur_plus)(data, length);
+            cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
             if (di->ddump_frames) {
                UInt i;
                VG_(printf)("  Augmentation data:    ");
                for (i = 0; i < length; i++)
-                  VG_(printf)(" %02x", (UInt)data[i]);
+                  VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
+                                                (ML_(cur_plus)(data, i)));
                VG_(printf)("\n");
             }
          } else {
-            the_CIEs[this_CIE].instrs = NULL;
+            the_CIEs[this_CIE].instrs = DiCursor_INVALID;
          }
 
          the_CIEs[this_CIE].address_encoding = default_Addr_encoding();
 
-         while (*cie_augmentation) {
-            switch (*cie_augmentation) {
+         while (ML_(cur_read_UChar)(cie_augmentation)) {
+            switch (ML_(cur_read_UChar)(cie_augmentation)) {
                case 'L':
-                  data++;
-                  cie_augmentation++;
+                  data = ML_(cur_plus)(data, 1);
+                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
                   break;
                case 'R':
                   the_CIEs[this_CIE].address_encoding 
-                     = ML_(read_UChar)(data); data += sizeof(UChar);
-                  cie_augmentation++;
+                     = ML_(cur_step_UChar)(&data);
+                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
                   break;
                case 'P':
-                  data += size_of_encoded_Addr( ML_(read_UChar)(data) );
-                  data++;
-                  cie_augmentation++;
+                  data = ML_(cur_plus)(data, size_of_encoded_Addr(
+                                                ML_(cur_read_UChar)(data) ));
+                  data = ML_(cur_plus)(data, 1);
+                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
                   break;
                case 'S':
-                  cie_augmentation++;
+                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
                   break;
                default:
-                  if (the_CIEs[this_CIE].instrs == NULL) {
+                  if (!ML_(cur_is_valid)(the_CIEs[this_CIE].instrs)) {
                      how = "unhandled cie.augmentation";
                      goto bad;
                   }
@@ -4010,10 +3962,10 @@
                         the_CIEs[this_CIE].address_encoding);
 
          the_CIEs[this_CIE].instrs = data;
-         the_CIEs[this_CIE].ilen
-            = ciefde_start + ciefde_len + sizeof(UInt) - data;
+         the_CIEs[this_CIE].ilen   = ML_(cur_minus)(ciefde_start, data) 
+                                     + (Long)ciefde_len + (Long)sizeof(UInt);
          if (di->trace_cfi) {
-            VG_(printf)("cie.instrs      = %p\n", the_CIEs[this_CIE].instrs);
+            //VG_(printf)("cie.instrs      = %p\n", the_CIEs[this_CIE].instrs);
             VG_(printf)("cie.ilen        = %d\n", the_CIEs[this_CIE].ilen);
 	 }
 
@@ -4023,7 +3975,7 @@
             goto bad;
          }
 
-         data += the_CIEs[this_CIE].ilen;
+         data = ML_(cur_plus)(data, the_CIEs[this_CIE].ilen);
 
          /* Show the CIE's instructions (the preamble for each FDE
             that uses this CIE). */ 
@@ -4049,13 +4001,13 @@
 
          AddressDecodingInfo adi;
          UnwindContext ctx, restore_ctx;
-         Int    cie;
-         ULong  look_for;
-         Bool   ok;
-         Addr   fde_initloc;
-         UWord  fde_arange;
-         UChar* fde_instrs;
-         Int    fde_ilen;
+         Int      cie;
+         ULong    look_for;
+         Bool     ok;
+         Addr     fde_initloc;
+         UWord    fde_arange;
+         DiCursor fde_instrs;
+         Int      fde_ilen;
 
          /* --------- FDE --------- */
 
@@ -4064,8 +4016,8 @@
 
          /* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
          if (is_ehframe)
-            look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt)) 
-                             - frame_image) 
+            look_for = ML_(cur_minus)(data, frame_image)
+                       - (dw64 ? sizeof(ULong) : sizeof(UInt))
                        - cie_pointer;
          else
             look_for = cie_pointer;
@@ -4086,8 +4038,7 @@
          adi.ehframe_image = frame_image;
          adi.ehframe_avma  = frame_avma;
          adi.text_bias     = di->text_debug_bias;
-         fde_initloc = read_encoded_Addr(&nbytes, &adi, data);
-         data += nbytes;
+         fde_initloc = step_encoded_Addr(&adi, &data);
          if (di->trace_cfi) 
             VG_(printf)("fde.initloc     = %#lx\n", fde_initloc);
 
@@ -4105,8 +4056,7 @@
            switch (ptr_size) {
               case 8: case 4: case 2: case 1: 
                  fde_arange 
-                    = (UWord)read_le_u_encoded_literal(data, ptr_size);
-                 data += ptr_size;
+                    = (UWord)step_le_u_encoded_literal(&data, ptr_size);
                  break;
               default: 
                  how = "unknown arange field encoding in FDE";
@@ -4119,7 +4069,7 @@
 
          if (di->ddump_frames)
             VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
-                        ((Addr)ciefde_start) - ((Addr)frame_image),
+                        (Addr)ML_(cur_minus)(ciefde_start, frame_image),
                         (Addr)ciefde_len,
                         (Addr)(UWord)cie_pointer,
                         (Addr)look_for, 
@@ -4127,22 +4077,23 @@
                         ((Addr)fde_initloc) - di->text_debug_bias + fde_arange);
 
          if (the_CIEs[cie].saw_z_augmentation) {
-            UInt length = read_leb128( data, &nbytes, 0);
-            data += nbytes;
+            UInt length = step_leb128( &data, 0);
             if (di->ddump_frames && (length > 0)) {
                UInt i;
                VG_(printf)("  Augmentation data:    ");
                for (i = 0; i < length; i++)
-                  VG_(printf)(" %02x", (UInt)data[i]);
+                  VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
+                                                (ML_(cur_plus)(data, i)));
                VG_(printf)("\n\n");
             }
-            data += length;
+            data = ML_(cur_plus)(data, length);
          }
 
          fde_instrs = data;
-         fde_ilen   = ciefde_start + ciefde_len + sizeof(UInt) - data;
+         fde_ilen   = ML_(cur_minus)(ciefde_start, data)
+                      + (Long)ciefde_len + (Long)sizeof(UInt);
          if (di->trace_cfi) {
-            VG_(printf)("fde.instrs      = %p\n", fde_instrs);
+            //VG_(printf)("fde.instrs      = %p\n", fde_instrs);
             VG_(printf)("fde.ilen        = %d\n", (Int)fde_ilen);
 	 }
 
@@ -4151,7 +4102,7 @@
             goto bad;
          }
 
-	 data += fde_ilen;
+	 data = ML_(cur_plus)(data, fde_ilen);
 
          /* If this object's DebugInfo* had some DiCFSIs from a
             previous .eh_frame or .debug_frame read, we must check
diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c
index 5e20ff0..fe35f55 100644
--- a/coregrind/m_debuginfo/readdwarf3.c
+++ b/coregrind/m_debuginfo/readdwarf3.c
@@ -1,3 +1,4 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
 
 /*--------------------------------------------------------------------*/
 /*--- Read DWARF3/4 ".debug_info" sections (DIE trees).            ---*/
@@ -146,6 +147,7 @@
 #include "pub_core_xarray.h"
 #include "pub_core_wordfm.h"
 #include "priv_misc.h"             /* dinfo_zalloc/free */
+#include "priv_image.h"
 #include "priv_tytypes.h"
 #include "priv_d3basics.h"
 #include "priv_storage.h"
@@ -166,9 +168,8 @@
 
 typedef
    struct {
-      UChar* region_start_img;
-      UWord  region_szB;
-      UWord  region_next;
+      DiSlice sli;      // to which this cursor applies
+      DiOffT  sli_next; // offset in underlying DiImage; must be >= sli.ioff
       void (*barf)( const HChar* ) __attribute__((noreturn));
       const HChar* barfstr;
    }
@@ -178,21 +179,25 @@
    if (!c)                return False;
    if (!c->barf)          return False;
    if (!c->barfstr)       return False;
+   if (!ML_(sli_is_valid)(c->sli))    return False;
+   if (c->sli.ioff == DiOffT_INVALID) return False;
+   if (c->sli_next < c->sli.ioff)     return False;
    return True;
 }
 
-static void init_Cursor ( Cursor* c,
-                          UChar*  region_start_img,
-                          UWord   region_szB,
-                          UWord   region_next,
-                          __attribute__((noreturn)) void (*barf)( const HChar* ),
+// Initialise a cursor from a DiSlice (ELF section, really) so as to
+// start reading at offset |sli_initial_offset| from the start of the
+// slice.
+static void init_Cursor ( /*OUT*/Cursor* c,
+                          DiSlice sli,
+                          ULong   sli_initial_offset,
+                          __attribute__((noreturn)) void (*barf)(const HChar*),
                           const HChar* barfstr )
 {
    vg_assert(c);
-   VG_(memset)(c, 0, sizeof(*c));
-   c->region_start_img = region_start_img;
-   c->region_szB       = region_szB;
-   c->region_next      = region_next;
+   VG_(bzero_inline)(c, sizeof(*c));
+   c->sli              = sli;
+   c->sli_next         = c->sli.ioff + sli_initial_offset;
    c->barf             = barf;
    c->barfstr          = barfstr;
    vg_assert(is_sane_Cursor(c));
@@ -200,79 +205,83 @@
 
 static Bool is_at_end_Cursor ( Cursor* c ) {
    vg_assert(is_sane_Cursor(c));
-   return c->region_next >= c->region_szB;
+   return c->sli_next >= c->sli.ioff + c->sli.szB;
 }
 
-static inline UWord get_position_of_Cursor ( Cursor* c ) {
+static inline ULong get_position_of_Cursor ( Cursor* c ) {
    vg_assert(is_sane_Cursor(c));
-   return c->region_next;
+   return c->sli_next - c->sli.ioff;
 }
-static inline void set_position_of_Cursor ( Cursor* c, UWord pos ) {
-   c->region_next = pos;
+static inline void set_position_of_Cursor ( Cursor* c, ULong pos ) {
+   c->sli_next = c->sli.ioff + pos;
    vg_assert(is_sane_Cursor(c));
 }
 
-static /*signed*/Word get_remaining_length_Cursor ( Cursor* c ) {
+static /*signed*/Long get_remaining_length_Cursor ( Cursor* c ) {
    vg_assert(is_sane_Cursor(c));
-   return c->region_szB - c->region_next;
+   return c->sli.ioff + c->sli.szB - c->sli_next;
 }
 
-static void* get_address_of_Cursor ( Cursor* c ) {
-   vg_assert(is_sane_Cursor(c));
-   return &c->region_start_img[ c->region_next ];
+//static void* get_address_of_Cursor ( Cursor* c ) {
+//   vg_assert(is_sane_Cursor(c));
+//   return &c->region_start_img[ c->region_next ];
+//}
+
+static DiCursor get_DiCursor_from_Cursor ( Cursor* c ) {
+   return mk_DiCursor(c->sli.img, c->sli_next);
 }
 
 /* FIXME: document assumptions on endianness for
    get_UShort/UInt/ULong. */
 static inline UChar get_UChar ( Cursor* c ) {
    UChar r;
-   /* vg_assert(is_sane_Cursor(c)); */
-   if (c->region_next + sizeof(UChar) > c->region_szB) {
+   vg_assert(is_sane_Cursor(c));
+   if (c->sli_next + sizeof(UChar) > c->sli.ioff + c->sli.szB) {
       c->barf(c->barfstr);
       /*NOTREACHED*/
       vg_assert(0);
    }
-   r = * (UChar*) &c->region_start_img[ c->region_next ];
-   c->region_next += sizeof(UChar);
+   r = ML_(img_get_UChar)(c->sli.img, c->sli_next);
+   c->sli_next += sizeof(UChar);
    return r;
 }
 static UShort get_UShort ( Cursor* c ) {
    UShort r;
    vg_assert(is_sane_Cursor(c));
-   if (c->region_next + sizeof(UShort) > c->region_szB) {
+   if (c->sli_next + sizeof(UShort) > c->sli.ioff + c->sli.szB) {
       c->barf(c->barfstr);
       /*NOTREACHED*/
       vg_assert(0);
    }
-   r = ML_(read_UShort)(&c->region_start_img[ c->region_next ]);
-   c->region_next += sizeof(UShort);
+   r = ML_(img_get_UShort)(c->sli.img, c->sli_next);
+   c->sli_next += sizeof(UShort);
    return r;
 }
 static UInt get_UInt ( Cursor* c ) {
    UInt r;
    vg_assert(is_sane_Cursor(c));
-   if (c->region_next + sizeof(UInt) > c->region_szB) {
+   if (c->sli_next + sizeof(UInt) > c->sli.ioff + c->sli.szB) {
       c->barf(c->barfstr);
       /*NOTREACHED*/
       vg_assert(0);
    }
-   r = ML_(read_UInt)(&c->region_start_img[ c->region_next ]);
-   c->region_next += sizeof(UInt);
+   r = ML_(img_get_UInt)(c->sli.img, c->sli_next);
+   c->sli_next += sizeof(UInt);
    return r;
 }
 static ULong get_ULong ( Cursor* c ) {
    ULong r;
    vg_assert(is_sane_Cursor(c));
-   if (c->region_next + sizeof(ULong) > c->region_szB) {
+   if (c->sli_next + sizeof(ULong) > c->sli.ioff + c->sli.szB) {
       c->barf(c->barfstr);
       /*NOTREACHED*/
       vg_assert(0);
    }
-   r = ML_(read_ULong)(&c->region_start_img[ c->region_next ]);
-   c->region_next += sizeof(ULong);
+   r = ML_(img_get_ULong)(c->sli.img, c->sli_next);
+   c->sli_next += sizeof(ULong);
    return r;
 }
-static inline ULong get_ULEB128 ( Cursor* c ) {
+static ULong get_ULEB128 ( Cursor* c ) {
    ULong result;
    Int   shift;
    UChar byte;
@@ -303,29 +312,28 @@
    return result;
 }
 
-/* Assume 'c' points to the start of a string.  Return the absolute
-   address of whatever it points at, and advance it past the
-   terminating zero.  This makes it safe for the caller to then copy
-   the string with ML_(addStr), since (w.r.t. image overruns) the
-   process of advancing past the terminating zero will already have
-   "vetted" the string. */
-static HChar* get_AsciiZ ( Cursor* c ) {
-   UChar  uc;
-   HChar* res = get_address_of_Cursor(c);
+/* Assume 'c' points to the start of a string.  Return a DiCursor of
+   whatever it points at, and advance it past the terminating zero.
+   This makes it safe for the caller to then copy the string with
+   ML_(addStr), since (w.r.t. image overruns) the process of advancing
+   past the terminating zero will already have "vetted" the string. */
+static DiCursor get_AsciiZ ( Cursor* c ) {
+   UChar uc;
+   DiCursor res = get_DiCursor_from_Cursor(c);
    do { uc = get_UChar(c); } while (uc != 0);
    return res;
 }
 
 static ULong peek_ULEB128 ( Cursor* c ) {
-   Word here = c->region_next;
-   ULong r = get_ULEB128( c );
-   c->region_next = here;
+   DiOffT here = c->sli_next;
+   ULong  r    = get_ULEB128( c );
+   c->sli_next = here;
    return r;
 }
 static UChar peek_UChar ( Cursor* c ) {
-   Word here = c->region_next;
-   UChar r = get_UChar( c );
-   c->region_next = here;
+   DiOffT here = c->sli_next;
+   UChar  r    = get_UChar( c );
+   c->sli_next = here;
    return r;
 }
 
@@ -397,34 +405,24 @@
          values. */
       Addr   cu_svma;
       Bool   cu_svma_known;
+
       /* The debug_abbreviations table to be used for this Unit */
-      UChar* debug_abbv;
+      //UChar* debug_abbv;
       /* Upper bound on size thereof (an overestimate, in general) */
-      UWord  debug_abbv_maxszB;
-      /* Where is .debug_str ? */
-      HChar* debug_str_img;
-      UWord  debug_str_sz;
-      /* Where is .debug_ranges ? */
-      UChar* debug_ranges_img;
-      UWord  debug_ranges_sz;
-      /* Where is .debug_loc ? */
-      UChar* debug_loc_img;
-      UWord  debug_loc_sz;
-      /* Where is .debug_line? */
-      UChar* debug_line_img;
-      UWord  debug_line_sz;
-      /* Where is .debug_info? */
-      UChar* debug_info_img;
-      UWord  debug_info_sz;
-      /* Where is .debug_types? */
-      UChar* debug_types_img;
-      UWord  debug_types_sz;
-      /* Where is alternate .debug_info? */
-      UChar* debug_info_alt_img;
-      UWord  debug_info_alt_sz;
-      /* Where is alternate .debug_str ? */
-      HChar* debug_str_alt_img;
-      UWord  debug_str_alt_sz;
+      //UWord  debug_abbv_maxszB;
+      /* A bounded area of the image, to be used as the
+         debug_abbreviations table tobe used for this Unit. */
+      DiSlice debug_abbv;
+
+      /* Image information for various sections. */
+      DiSlice escn_debug_str;
+      DiSlice escn_debug_ranges;
+      DiSlice escn_debug_loc;
+      DiSlice escn_debug_line;
+      DiSlice escn_debug_info;
+      DiSlice escn_debug_types;
+      DiSlice escn_debug_info_alt;
+      DiSlice escn_debug_str_alt;
       /* How much to add to .debug_types resp. alternate .debug_info offsets
          in cook_die*.  */
       UWord  types_cuOff_bias;
@@ -493,13 +491,18 @@
 {
    *alt_flag = False;
    *type_flag = False;
-   if (die >= cc->debug_info_sz) {
-      if (die >= cc->debug_info_sz + cc->debug_types_sz) {
+   /* The use of escn_debug_{info,types}.szB seems safe to me even if
+      escn_debug_{info,types} are DiSlice_INVALID (meaning the
+      sections were not found), because DiSlice_INVALID.szB is always
+      zero.  That said, it seems unlikely we'd ever get here if
+      .debug_info or .debug_types were missing. */
+   if (die >= cc->escn_debug_info.szB) {
+      if (die >= cc->escn_debug_info.szB + cc->escn_debug_types.szB) {
          *alt_flag = True;
-         die -= cc->debug_info_sz + cc->debug_types_sz;
+         die -= cc->escn_debug_info.szB + cc->escn_debug_types.szB;
       } else {
          *type_flag = True;
-         die -= cc->debug_info_sz;
+         die -= cc->escn_debug_info.szB;
       }
    }
    return die;
@@ -579,7 +582,7 @@
 }
 
 __attribute__((noinline))
-static GExpr* make_singleton_GX ( UChar* block, UWord nbytes )
+static GExpr* make_singleton_GX ( DiCursor block, ULong nbytes )
 {
    SizeT  bytesReqd;
    GExpr* gx;
@@ -590,7 +593,7 @@
    bytesReqd
       =   sizeof(UChar)  /*biasMe*/    + sizeof(UChar) /*!isEnd*/
         + sizeof(UWord)  /*aMin*/      + sizeof(UWord) /*aMax*/
-        + sizeof(UShort) /*nbytes*/    + nbytes
+        + sizeof(UShort) /*nbytes*/    + (SizeT)nbytes
         + sizeof(UChar); /*isEnd*/
 
    gx = ML_(dinfo_zalloc)( "di.readdwarf3.msGX.1", 
@@ -604,7 +607,7 @@
    p = ML_(write_Addr)(p, 0);         /*aMin*/
    p = ML_(write_Addr)(p, ~0);        /*aMax*/
    p = ML_(write_UShort)(p, nbytes);  /*nbytes*/
-   VG_(memcpy)(p, block, nbytes); p += nbytes;
+   ML_(cur_read_get)(p, block, nbytes); p += nbytes;
    p = ML_(write_UChar)(p, 1);        /*isEnd*/
 
    vg_assert( (SizeT)(p - pstart) == bytesReqd);
@@ -617,7 +620,7 @@
 __attribute__((noinline))
 static GExpr* make_general_GX ( CUConst* cc,
                                 Bool     td3,
-                                UWord    debug_loc_offset,
+                                ULong    debug_loc_offset,
                                 Addr     svma_of_referencing_CU )
 {
    Addr      base;
@@ -627,16 +630,15 @@
    Word      nbytes;
 
    vg_assert(sizeof(UWord) == sizeof(Addr));
-   if (cc->debug_loc_sz == 0)
+   if (!ML_(sli_is_valid)(cc->escn_debug_loc) || cc->escn_debug_loc.szB == 0)
       cc->barf("make_general_GX: .debug_loc is empty/missing");
 
-   init_Cursor( &loc, cc->debug_loc_img, 
-                cc->debug_loc_sz, 0, cc->barf,
+   init_Cursor( &loc, cc->escn_debug_loc, 0, cc->barf,
                 "Overrun whilst reading .debug_loc section(2)" );
    set_position_of_Cursor( &loc, debug_loc_offset );
 
-   TRACE_D3("make_general_GX (.debug_loc_offset = %lu, img = %p) {\n",
-            debug_loc_offset, get_address_of_Cursor( &loc ) );
+   TRACE_D3("make_general_GX (.debug_loc_offset = %llu, ioff = %llu) {\n",
+            debug_loc_offset, (ULong)get_DiCursor_from_Cursor(&loc).ioff );
 
    /* Who frees this xa?  It is freed before this fn exits. */
    xa = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.mgGX.1", 
@@ -672,7 +674,7 @@
          (sec 2.17.2) */
       if (w1 > w2) {
          TRACE_D3("negative range is for .debug_loc expr at "
-                  "file offset %lu\n", 
+                  "file offset %llu\n", 
                   debug_loc_offset);
          cc->barf( "negative range in .debug_loc section" );
       }
@@ -806,11 +808,11 @@
    XArray*   xa; /* XArray of AddrRange */
    AddrRange pair;
 
-   if (cc->debug_ranges_sz == 0)
+   if (!ML_(sli_is_valid)(cc->escn_debug_ranges)
+       || cc->escn_debug_ranges.szB == 0)
       cc->barf("get_range_list: .debug_ranges is empty/missing");
 
-   init_Cursor( &ranges, cc->debug_ranges_img, 
-                cc->debug_ranges_sz, 0, cc->barf,
+   init_Cursor( &ranges, cc->escn_debug_ranges, 0, cc->barf,
                 "Overrun whilst reading .debug_ranges section(2)" );
    set_position_of_Cursor( &ranges, debug_ranges_offset );
 
@@ -857,12 +859,12 @@
 void parse_CU_Header ( /*OUT*/CUConst* cc,
                        Bool td3,
                        Cursor* c, 
-                       UChar* debug_abbv_img, UWord debug_abbv_sz,
+                       DiSlice escn_debug_abbv,
 		       Bool type_unit,
                        Bool alt_info )
 {
    UChar  address_size;
-   UWord  debug_abbrev_offset;
+   ULong  debug_abbrev_offset;
    Int    i;
 
    VG_(memset)(cc, 0, sizeof(*cc));
@@ -884,9 +886,9 @@
 
    /* debug_abbrev_offset */
    debug_abbrev_offset = get_Dwarfish_UWord( c, cc->is_dw64 );
-   if (debug_abbrev_offset >= debug_abbv_sz)
+   if (debug_abbrev_offset >= escn_debug_abbv.szB)
       cc->barf( "parse_CU_Header: invalid debug_abbrev_offset" );
-   TRACE_D3("   Abbrev Offset: %ld\n", debug_abbrev_offset );
+   TRACE_D3("   Abbrev Offset: %lld\n", debug_abbrev_offset );
 
    /* address size.  If this isn't equal to the host word size, just
       give up.  This makes it safe to assume elsewhere that
@@ -905,13 +907,22 @@
       cc->type_offset = get_Dwarfish_UWord( c, cc->is_dw64 );
    }
 
-   /* Set up so that cc->debug_abbv points to the relevant table for
-      this CU.  Set the szB so that at least we can't read off the end
-      of the debug_abbrev section -- potentially (and quite likely)
-      too big, if this isn't the last table in the section, but at
-      least it's safe. */
-   cc->debug_abbv        = debug_abbv_img + debug_abbrev_offset;
-   cc->debug_abbv_maxszB = debug_abbv_sz  - debug_abbrev_offset;
+   /* Set up cc->debug_abbv to point to the relevant table for this
+      CU.  Set its .szB so that at least we can't read off the end of
+      the debug_abbrev section -- potentially (and quite likely) too
+      big, if this isn't the last table in the section, but at least
+      it's safe.
+
+      This amounts to taking debug_abbv_escn and moving the start
+      position along by debug_abbrev_offset bytes, hence forming a
+      smaller DiSlice which has the same end point.  Since we checked
+      just above that debug_abbrev_offset is less than the size of
+      debug_abbv_escn, this should leave us with a nonempty slice. */
+   vg_assert(debug_abbrev_offset < escn_debug_abbv.szB);
+   cc->debug_abbv      = escn_debug_abbv;
+   cc->debug_abbv.ioff += debug_abbrev_offset;
+   cc->debug_abbv.szB  -= debug_abbrev_offset;
+
    /* and empty out the set_abbv_Cursor cache */
    if (0) VG_(printf)("XXXXXX initialise set_abbv_Cursor cache\n");
    for (i = 0; i < N_ABBV_CACHE; i++) {
@@ -947,27 +958,25 @@
    for (i = 0; i < N_ABBV_CACHE; i++) {
       /* No need to test the cached abbv_codes for -1 (empty), since
          we just asserted that abbv_code is not -1. */
-     if (cc->saC_cache[i].abbv_code == abbv_code) {
-        /* Found it.  Cool.  Set up the parser using the cached
-           position, and move this cache entry 1 step closer to the
-           front. */
-        if (0) VG_(printf)("XXXXXX found in set_abbv_Cursor cache\n");
-        init_Cursor( c, cc->debug_abbv,
-                     cc->debug_abbv_maxszB, cc->saC_cache[i].posn, 
-                     cc->barf,
-                     "Overrun whilst parsing .debug_abbrev section(1)" );
-        if (i > 0) {
-           ULong t_abbv_code = cc->saC_cache[i].abbv_code;
-           UWord t_posn = cc->saC_cache[i].posn;
-           while (i > 0) {
-              cc->saC_cache[i] = cc->saC_cache[i-1];
-              cc->saC_cache[0].abbv_code = t_abbv_code;
-              cc->saC_cache[0].posn = t_posn;
-              i--;
-           }
-        }
-        return;
-     }
+      if (LIKELY(cc->saC_cache[i].abbv_code == abbv_code)) {
+         /* Found it.  Set up the parser using the cached position,
+            and move this cache entry to the front. */
+         if (0) VG_(printf)("XXXXXX found in set_abbv_Cursor cache\n");
+         init_Cursor( c, cc->debug_abbv, cc->saC_cache[i].posn, 
+                      cc->barf,
+                      "Overrun whilst parsing .debug_abbrev section(1)" );
+         if (i > 0) {
+            ULong t_abbv_code = cc->saC_cache[i].abbv_code;
+            UWord t_posn      = cc->saC_cache[i].posn;
+            while (i > 0) {
+               cc->saC_cache[i] = cc->saC_cache[i-1];
+               i--;
+            }
+            cc->saC_cache[0].abbv_code = t_abbv_code;
+            cc->saC_cache[0].posn      = t_posn;
+         }
+         return;
+      }
    }
 
    /* No.  It's not in the cache.  We have to search through
@@ -975,7 +984,7 @@
       when done. */
 
    cc->saC_cache_misses++;
-   init_Cursor( c, cc->debug_abbv, cc->debug_abbv_maxszB, 0, cc->barf,
+   init_Cursor( c, cc->debug_abbv, 0, cc->barf,
                "Overrun whilst parsing .debug_abbrev section(2)" );
 
    /* Now iterate though the table until we find the requested
@@ -1060,69 +1069,62 @@
    return dstype->die;
 }
 
-/* From 'c', get the Form data into the lowest 1/2/4/8 bytes of *cts.
 
-   If *cts itself contains the entire result, then *ctsSzB is set to
-   1,2,4 or 8 accordingly and *ctsMemSzB is set to zero.
+/* Represents Form data.  If szB is 1/2/4/8 then the result is in the
+   lowest 1/2/4/8 bytes of u.val.  If szB is zero or negative then the
+   result is an image section beginning at u.cur and with size -szB.
+   No other szB values are allowed. */
+typedef
+   struct {
+      Long szB; // 1, 2, 4, 8 or non-positive values only.
+      union { ULong val; DiCursor cur; } u;
+   }
+   FormContents;
 
-   Alternatively, the result can be a block of data (in the
-   transiently mapped-in object, so-called "image" space).  If so then
-   the lowest sizeof(void*)/8 bytes of *cts hold a pointer to said
-   image, *ctsSzB is zero, and *ctsMemSzB is the size of the block.
-
-   Unfortunately this means it is impossible to represent a zero-size
-   image block since that would have *ctsSzB == 0 and *ctsMemSzB == 0
-   and so is ambiguous (which case it is?)
-
-   Invariant on successful return: 
-      (*ctsSzB > 0 && *ctsMemSzB == 0)
-      || (*ctsSzB == 0 && *ctsMemSzB > 0)
-*/
+/* From 'c', get the Form data into 'cts'.  Either it gets a 1/2/4/8
+   byte scalar value, or (a reference to) zero or more bytes starting
+   at a DiCursor.*/
 static
-void get_Form_contents ( /*OUT*/ULong* cts,
-                         /*OUT*/Int*   ctsSzB,
-                         /*OUT*/UWord* ctsMemSzB,
+void get_Form_contents ( /*OUT*/FormContents* cts,
                          CUConst* cc, Cursor* c,
                          Bool td3, DW_FORM form )
 {
-   *cts       = 0;
-   *ctsSzB    = 0;
-   *ctsMemSzB = 0;
+   VG_(bzero_inline)(cts, sizeof(*cts));
    switch (form) {
       case DW_FORM_data1:
-         *cts = (ULong)(UChar)get_UChar(c);
-         *ctsSzB = 1;
-         TRACE_D3("%u", (UInt)*cts);
+         cts->u.val = (ULong)(UChar)get_UChar(c);
+         cts->szB   = 1;
+         TRACE_D3("%u", (UInt)cts->u.val);
          break;
       case DW_FORM_data2:
-         *cts = (ULong)(UShort)get_UShort(c);
-         *ctsSzB = 2;
-         TRACE_D3("%u", (UInt)*cts);
+         cts->u.val = (ULong)(UShort)get_UShort(c);
+         cts->szB   = 2;
+         TRACE_D3("%u", (UInt)cts->u.val);
          break;
       case DW_FORM_data4:
-         *cts = (ULong)(UInt)get_UInt(c);
-         *ctsSzB = 4;
-         TRACE_D3("%u", (UInt)*cts);
+         cts->u.val = (ULong)(UInt)get_UInt(c);
+         cts->szB   = 4;
+         TRACE_D3("%u", (UInt)cts->u.val);
          break;
       case DW_FORM_data8:
-         *cts = get_ULong(c);
-         *ctsSzB = 8;
-         TRACE_D3("%llu", *cts);
+         cts->u.val = get_ULong(c);
+         cts->szB   = 8;
+         TRACE_D3("%llu", cts->u.val);
          break;
       case DW_FORM_sec_offset:
-         *cts = (ULong)get_Dwarfish_UWord( c, cc->is_dw64 );
-         *ctsSzB = cc->is_dw64 ? 8 : 4;
-         TRACE_D3("%llu", *cts);
+         cts->u.val = (ULong)get_Dwarfish_UWord( c, cc->is_dw64 );
+         cts->szB   = cc->is_dw64 ? 8 : 4;
+         TRACE_D3("%llu", cts->u.val);
          break;
       case DW_FORM_sdata:
-         *cts = (ULong)(Long)get_SLEB128(c);
-         *ctsSzB = 8;
-         TRACE_D3("%lld", (Long)*cts);
+         cts->u.val = (ULong)(Long)get_SLEB128(c);
+         cts->szB   = 8;
+         TRACE_D3("%lld", (Long)cts->u.val);
          break;
       case DW_FORM_udata:
-         *cts = (ULong)(Long)get_ULEB128(c);
-         *ctsSzB = 8;
-         TRACE_D3("%llu", (Long)*cts);
+         cts->u.val = (ULong)(Long)get_ULEB128(c);
+         cts->szB   = 8;
+         TRACE_D3("%llu", (Long)cts->u.val);
          break;
       case DW_FORM_addr:
          /* note, this is a hack.  DW_FORM_addr is defined as getting
@@ -1131,9 +1133,9 @@
             parse_CU_Header() rejects all inputs except those for
             which address_size == sizeof(Word), hence we can just
             treat it as a (host) Word.  */
-         *cts = (ULong)(UWord)get_UWord(c);
-         *ctsSzB = sizeof(UWord);
-         TRACE_D3("0x%lx", (UWord)*cts);
+         cts->u.val = (ULong)(UWord)get_UWord(c);
+         cts->szB   = sizeof(UWord);
+         TRACE_D3("0x%lx", (UWord)cts->u.val);
          break;
 
       case DW_FORM_ref_addr:
@@ -1156,17 +1158,17 @@
             DWARF 3 and later, it is offset-sized.
          */
          if (cc->version == 2) {
-            *cts = (ULong)(UWord)get_UWord(c);
-            *ctsSzB = sizeof(UWord);
+            cts->u.val = (ULong)(UWord)get_UWord(c);
+            cts->szB   = sizeof(UWord);
          } else {
-            *cts = get_Dwarfish_UWord(c, cc->is_dw64);
-            *ctsSzB = cc->is_dw64 ? sizeof(ULong) : sizeof(UInt);
+            cts->u.val = get_Dwarfish_UWord(c, cc->is_dw64);
+            cts->szB   = cc->is_dw64 ? sizeof(ULong) : sizeof(UInt);
          }
-         TRACE_D3("0x%lx", (UWord)*cts);
-         if (0) VG_(printf)("DW_FORM_ref_addr 0x%lx\n", (UWord)*cts);
-         if (/* the following 2 are surely impossible, but ... */
-             cc->debug_info_img == NULL || cc->debug_info_sz == 0
-             || *cts >= (ULong)cc->debug_info_sz) {
+         TRACE_D3("0x%lx", (UWord)cts->u.val);
+         if (0) VG_(printf)("DW_FORM_ref_addr 0x%lx\n", (UWord)cts->u.val);
+         if (/* the following is surely impossible, but ... */
+             !ML_(sli_is_valid)(cc->escn_debug_info)
+             || cts->u.val >= (ULong)cc->escn_debug_info.szB) {
             /* Hmm.  Offset is nonsensical for this object's .debug_info
                section.  Be safe and reject it. */
             cc->barf("get_Form_contents: DW_FORM_ref_addr points "
@@ -1176,131 +1178,140 @@
 
       case DW_FORM_strp: {
          /* this is an offset into .debug_str */
-         HChar* str;
          UWord uw = (UWord)get_Dwarfish_UWord( c, cc->is_dw64 );
-         if (cc->debug_str_img == NULL || uw >= cc->debug_str_sz)
+         if (!ML_(sli_is_valid)(cc->escn_debug_str)
+             || uw >= cc->escn_debug_str.szB)
             cc->barf("get_Form_contents: DW_FORM_strp "
                      "points outside .debug_str");
          /* FIXME: check the entire string lies inside debug_str,
             not just the first byte of it. */
-         str = cc->debug_str_img + uw;
-         TRACE_D3("(indirect string, offset: 0x%lx): %s", uw, str);
-         *cts = (ULong)(UWord)str;
-         *ctsMemSzB = 1 + (ULong)VG_(strlen)(str);
+         DiCursor str
+            = ML_(cur_plus)( ML_(cur_from_sli)(cc->escn_debug_str), uw );
+         if (td3) {
+            HChar* tmp = ML_(cur_read_strdup)(str, "di.getFC.1");
+            TRACE_D3("(indirect string, offset: 0x%lx): %s", uw, tmp);
+            ML_(dinfo_free)(tmp);
+         }
+         cts->u.cur = str;
+         cts->szB   = - (Long)(1 + (ULong)ML_(cur_strlen)(str));
          break;
       }
       case DW_FORM_string: {
-         HChar* str = get_AsciiZ(c);
-         TRACE_D3("%s", str);
-         *cts = (ULong)(UWord)str;
+         DiCursor str = get_AsciiZ(c);
+         if (td3) {
+            HChar* tmp = ML_(cur_read_strdup)(str, "di.getFC.2");
+            TRACE_D3("%s", tmp);
+            ML_(dinfo_free)(tmp);
+         }
+         cts->u.cur = str;
          /* strlen is safe because get_AsciiZ already 'vetted' the
             entire string */
-         *ctsMemSzB = 1 + (ULong)VG_(strlen)(str);
+         cts->szB   = - (Long)(1 + (ULong)ML_(cur_strlen)(str));
          break;
       }
       case DW_FORM_ref1: {
-         UChar  u8 = get_UChar(c);
-         UWord res = cc->cu_start_offset + (UWord)u8;
-         *cts = (ULong)res;
-         *ctsSzB = sizeof(UWord);
+         UChar u8   = get_UChar(c);
+         UWord res  = cc->cu_start_offset + (UWord)u8;
+         cts->u.val = (ULong)res;
+         cts->szB   = sizeof(UWord);
          TRACE_D3("<%lx>", res);
          break;
       }
       case DW_FORM_ref2: {
-         UShort  u16 = get_UShort(c);
-         UWord res = cc->cu_start_offset + (UWord)u16;
-         *cts = (ULong)res;
-         *ctsSzB = sizeof(UWord);
+         UShort u16 = get_UShort(c);
+         UWord  res = cc->cu_start_offset + (UWord)u16;
+         cts->u.val = (ULong)res;
+         cts->szB   = sizeof(UWord);
          TRACE_D3("<%lx>", res);
          break;
       }
       case DW_FORM_ref4: {
-         UInt  u32 = get_UInt(c);
-         UWord res = cc->cu_start_offset + (UWord)u32;
-         *cts = (ULong)res;
-         *ctsSzB = sizeof(UWord);
+         UInt  u32  = get_UInt(c);
+         UWord res  = cc->cu_start_offset + (UWord)u32;
+         cts->u.val = (ULong)res;
+         cts->szB   = sizeof(UWord);
          TRACE_D3("<%lx>", res);
          break;
       }
       case DW_FORM_ref8: {
-         ULong  u64 = get_ULong(c);
-         UWord res = cc->cu_start_offset + (UWord)u64;
-         *cts = (ULong)res;
-         *ctsSzB = sizeof(UWord);
+         ULong u64  = get_ULong(c);
+         UWord res  = cc->cu_start_offset + (UWord)u64;
+         cts->u.val = (ULong)res;
+         cts->szB   = sizeof(UWord);
          TRACE_D3("<%lx>", res);
          break;
       }
       case DW_FORM_ref_udata: {
-         ULong  u64 = get_ULEB128(c);
-         UWord res = cc->cu_start_offset + (UWord)u64;
-         *cts = (ULong)res;
-         *ctsSzB = sizeof(UWord);
+         ULong u64  = get_ULEB128(c);
+         UWord res  = cc->cu_start_offset + (UWord)u64;
+         cts->u.val = (ULong)res;
+         cts->szB   = sizeof(UWord);
          TRACE_D3("<%lx>", res);
          break;
       }
       case DW_FORM_flag: {
          UChar u8 = get_UChar(c);
          TRACE_D3("%u", (UInt)u8);
-         *cts = (ULong)u8;
-         *ctsSzB = 1;
+         cts->u.val = (ULong)u8;
+         cts->szB   = 1;
          break;
       }
       case DW_FORM_flag_present:
          TRACE_D3("1");
-         *cts = 1;
-         *ctsSzB = 1;
+         cts->u.val = 1;
+         cts->szB   = 1;
          break;
       case DW_FORM_block1: {
-         ULong  u64b;
-         ULong  u64 = (ULong)get_UChar(c);
-         UChar* block = get_address_of_Cursor(c);
+         ULong    u64b;
+         ULong    u64   = (ULong)get_UChar(c);
+         DiCursor block = get_DiCursor_from_Cursor(c);
          TRACE_D3("%llu byte block: ", u64);
          for (u64b = u64; u64b > 0; u64b--) {
             UChar u8 = get_UChar(c);
             TRACE_D3("%x ", (UInt)u8);
          }
-         *cts = (ULong)(UWord)block;
-         *ctsMemSzB = (UWord)u64;
+         cts->u.cur = block;
+         cts->szB   = - (Long)u64;
          break;
       }
       case DW_FORM_block2: {
-         ULong  u64b;
-         ULong  u64 = (ULong)get_UShort(c);
-         UChar* block = get_address_of_Cursor(c);
+         ULong    u64b;
+         ULong    u64   = (ULong)get_UShort(c);
+         DiCursor block = get_DiCursor_from_Cursor(c);
          TRACE_D3("%llu byte block: ", u64);
          for (u64b = u64; u64b > 0; u64b--) {
             UChar u8 = get_UChar(c);
             TRACE_D3("%x ", (UInt)u8);
          }
-         *cts = (ULong)(UWord)block;
-         *ctsMemSzB = (UWord)u64;
+         cts->u.cur = block;
+         cts->szB   = - (Long)u64;
          break;
       }
       case DW_FORM_block4: {
-         ULong  u64b;
-         ULong  u64 = (ULong)get_UInt(c);
-         UChar* block = get_address_of_Cursor(c);
+         ULong    u64b;
+         ULong    u64   = (ULong)get_UInt(c);
+         DiCursor block = get_DiCursor_from_Cursor(c);
          TRACE_D3("%llu byte block: ", u64);
          for (u64b = u64; u64b > 0; u64b--) {
             UChar u8 = get_UChar(c);
             TRACE_D3("%x ", (UInt)u8);
          }
-         *cts = (ULong)(UWord)block;
-         *ctsMemSzB = (UWord)u64;
+         cts->u.cur = block;
+         cts->szB   = - (Long)u64;
          break;
       }
       case DW_FORM_exprloc:
       case DW_FORM_block: {
-         ULong  u64b;
-         ULong  u64 = (ULong)get_ULEB128(c);
-         UChar* block = get_address_of_Cursor(c);
+         ULong    u64b;
+         ULong    u64   = (ULong)get_ULEB128(c);
+         DiCursor block = get_DiCursor_from_Cursor(c);
          TRACE_D3("%llu byte block: ", u64);
          for (u64b = u64; u64b > 0; u64b--) {
             UChar u8 = get_UChar(c);
             TRACE_D3("%x ", (UInt)u8);
          }
-         *cts = (ULong)(UWord)block;
-         *ctsMemSzB = (UWord)u64;
+         cts->u.cur = block;
+         cts->szB   = - (Long)u64;
          break;
       }
       case DW_FORM_ref_sig8: {
@@ -1316,24 +1327,23 @@
          /* Due to the way that the hash table is constructed, the
             resulting DIE offset here is already "cooked".  See
             cook_die_using_form.  */
-         *cts = lookup_signatured_type (cc->signature_types, signature,
-                                        c->barf);
-         *ctsSzB = sizeof(UWord);
+         cts->u.val = lookup_signatured_type (cc->signature_types, signature,
+                                              c->barf);
+         cts->szB   = sizeof(UWord);
          break;
       }
       case DW_FORM_indirect:
-         get_Form_contents (cts, ctsSzB, ctsMemSzB, cc, c, td3,
-                            (DW_FORM)get_ULEB128(c));
+         get_Form_contents (cts, cc, c, td3, (DW_FORM)get_ULEB128(c));
          return;
 
       case DW_FORM_GNU_ref_alt:
-         *cts = get_Dwarfish_UWord(c, cc->is_dw64);
-         *ctsSzB = cc->is_dw64 ? sizeof(ULong) : sizeof(UInt);
-         TRACE_D3("0x%lx", (UWord)*cts);
-         if (0) VG_(printf)("DW_FORM_GNU_ref_alt 0x%lx\n", (UWord)*cts);
-         if (/* the following 2 are surely impossible, but ... */
-             cc->debug_info_alt_img == NULL || cc->debug_info_alt_sz == 0
-             || *cts >= (ULong)cc->debug_info_alt_sz) {
+         cts->u.val = get_Dwarfish_UWord(c, cc->is_dw64);
+         cts->szB   = cc->is_dw64 ? sizeof(ULong) : sizeof(UInt);
+         TRACE_D3("0x%lx", (UWord)cts->u.val);
+         if (0) VG_(printf)("DW_FORM_GNU_ref_alt 0x%lx\n", (UWord)cts->u.val);
+         if (/* the following is surely impossible, but ... */
+             !ML_(sli_is_valid)(cc->escn_debug_info_alt)
+             || cts->u.val >= (ULong)cc->escn_debug_info_alt.szB) {
             /* Hmm.  Offset is nonsensical for this object's .debug_info
                section.  Be safe and reject it. */
             cc->barf("get_Form_contents: DW_FORM_ref_addr points "
@@ -1343,23 +1353,28 @@
 
       case DW_FORM_GNU_strp_alt: {
          /* this is an offset into alternate .debug_str */
-         HChar* str;
-         UWord uw = (UWord)get_Dwarfish_UWord( c, cc->is_dw64 );
-         if (cc->debug_str_alt_img == NULL || uw >= cc->debug_str_alt_sz)
+         SizeT uw = (UWord)get_Dwarfish_UWord( c, cc->is_dw64 );
+         if (!ML_(sli_is_valid)(cc->escn_debug_str_alt)
+             || uw >= cc->escn_debug_str_alt.szB)
             cc->barf("get_Form_contents: DW_FORM_GNU_strp_alt "
                      "points outside alternate .debug_str");
          /* FIXME: check the entire string lies inside debug_str,
             not just the first byte of it. */
-         str = cc->debug_str_alt_img + uw;
-         TRACE_D3("(indirect alt string, offset: 0x%lx): %s", uw, str);
-         *cts = (ULong)(UWord)str;
-         *ctsMemSzB = 1 + (ULong)VG_(strlen)(str);
+         DiCursor str
+            = ML_(cur_plus)( ML_(cur_from_sli)(cc->escn_debug_str_alt), uw);
+         if (td3) {
+            HChar* tmp = ML_(cur_read_strdup)(str, "di.getFC.3");
+            TRACE_D3("(indirect alt string, offset: 0x%lx): %s", uw, tmp);
+            ML_(dinfo_free)(tmp);
+         }
+         cts->u.cur = str;
+         cts->szB   = - (Long)(1 + (ULong)ML_(cur_strlen)(str));
          break;
       }
 
       default:
          VG_(printf)(
-            "get_Form_contents: unhandled %d (%s) at <%lx>\n",
+            "get_Form_contents: unhandled %d (%s) at <%llx>\n",
             form, ML_(pp_DW_FORM)(form), get_position_of_Cursor(c));
          c->barf("get_Form_contents: unhandled DW_FORM");
    }
@@ -1434,7 +1449,7 @@
       GExpr*  fbGX[N_D3_VAR_STACK];   /* if isFunc, contains the FB
                                          expr, else NULL */
       /* The file name table.  Is a mapping from integer index to the
-         (permanent) copy of the string, iow a non-img area. */
+         (permanent) copy of the string in in DebugInfo's .strchunks. */
       XArray* /* of UChar* */ filenameTable;
    }
    D3VarParser;
@@ -1529,27 +1544,26 @@
 }
 
 
-/* cts, ctsSzB, ctsMemSzB are derived from a DW_AT_location and so
-   refer either to a location expression or to a location list.
-   Figure out which, and in both cases bundle the expression or
-   location list into a so-called GExpr (guarded expression). */
+/* cts is derived from a DW_AT_location and so refers either to a
+   location expression or to a location list.  Figure out which, and
+   in both cases bundle the expression or location list into a
+   so-called GExpr (guarded expression). */
 __attribute__((noinline))
-static GExpr* get_GX ( CUConst* cc, Bool td3, 
-                       ULong cts, Int ctsSzB, UWord ctsMemSzB )
+static GExpr* get_GX ( CUConst* cc, Bool td3, const FormContents* cts )
 {
    GExpr* gexpr = NULL;
-   if (ctsMemSzB > 0 && ctsSzB == 0) {
-      /* represents an in-line location expression, and cts points
-         right at it */
-      gexpr = make_singleton_GX( (UChar*)(UWord)cts, ctsMemSzB );
+   if (cts->szB < 0) {
+      /* represents a non-empty in-line location expression, and
+         cts->u.cur points at the image bytes */
+      gexpr = make_singleton_GX( cts->u.cur, (ULong)(- cts->szB) );
    }
    else 
-   if (ctsMemSzB == 0 && ctsSzB > 0) {
-      /* represents location list.  cts is the offset of it in
-         .debug_loc. */
+   if (cts->szB > 0) {
+      /* represents a location list.  cts->u.val is the offset of it
+         in .debug_loc. */
       if (!cc->cu_svma_known)
          cc->barf("get_GX: location list, but CU svma is unknown");
-      gexpr = make_general_GX( cc, td3, (UWord)cts, cc->cu_svma );
+      gexpr = make_general_GX( cc, td3, cts->u.val, cc->cu_svma );
    }
    else {
       vg_assert(0); /* else caller is bogus */
@@ -1560,7 +1574,7 @@
 
 static 
 void read_filename_table( /*MOD*/D3VarParser* parser,
-                          CUConst* cc, UWord debug_line_offset,
+                          CUConst* cc, ULong debug_line_offset,
                           Bool td3 )
 {
    Bool   is_dw64;
@@ -1571,12 +1585,12 @@
    HChar* str;
 
    vg_assert(parser && cc && cc->barf);
-   if ((!cc->debug_line_img) 
-       || cc->debug_line_sz <= debug_line_offset)
+   if (!ML_(sli_is_valid)(cc->escn_debug_line)
+       || cc->escn_debug_line.szB <= debug_line_offset) {
       cc->barf("read_filename_table: .debug_line is missing?");
+   }
 
-   init_Cursor( &c, cc->debug_line_img, 
-                cc->debug_line_sz, debug_line_offset, cc->barf, 
+   init_Cursor( &c, cc->escn_debug_line, debug_line_offset, cc->barf, 
                 "Overrun whilst reading .debug_line section(1)" );
 
    /* unit_length = */
@@ -1612,10 +1626,10 @@
    str = ML_(addStr)( cc->di, "<unknown_file>", -1 );
    VG_(addToXA)( parser->filenameTable, &str );
    while (peek_UChar(&c) != 0) {
-      str = get_AsciiZ(&c);
+      DiCursor cur = get_AsciiZ(&c);
+      str = ML_(addStrFromCursor)( cc->di, cur );
       TRACE_D3("  read_filename_table: %ld %s\n",
                VG_(sizeXA)(parser->filenameTable), str);
-      str = ML_(addStr)( cc->di, str, -1 );
       VG_(addToXA)( parser->filenameTable, &str );
       (void)get_ULEB128( &c ); /* skip directory index # */
       (void)get_ULEB128( &c ); /* skip last mod time */
@@ -1640,9 +1654,7 @@
    Bool td3
 )
 {
-   ULong       cts;
-   Int         ctsSzB;
-   UWord       ctsMemSzB;
+   FormContents cts;
 
    UWord saved_die_c_offset  = get_position_of_Cursor( c_die );
    UWord saved_abbv_c_offset = get_position_of_Cursor( c_abbv );
@@ -1665,24 +1677,23 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_low_pc && ctsSzB > 0) {
-            ip_lo   = cts;
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_low_pc && cts.szB > 0) {
+            ip_lo   = cts.u.val;
             have_lo = True;
          }
-         if (attr == DW_AT_high_pc && ctsSzB > 0) {
-            ip_hi1   = cts;
+         if (attr == DW_AT_high_pc && cts.szB > 0) {
+            ip_hi1   = cts.u.val;
             have_hi1 = True;
             if (form != DW_FORM_addr)
                hiIsRelative = True;
          }
-         if (attr == DW_AT_ranges && ctsSzB > 0) {
-            rangeoff = cts;
+         if (attr == DW_AT_ranges && cts.szB > 0) {
+            rangeoff   = cts.u.val;
             have_range = True;
          }
-         if (attr == DW_AT_stmt_list && ctsSzB > 0) {
-            read_filename_table( parser, cc, (UWord)cts, td3 );
+         if (attr == DW_AT_stmt_list && cts.szB > 0) {
+            read_filename_table( parser, cc, cts.u.val, td3 );
          }
       }
       if (have_lo && have_hi1 && hiIsRelative)
@@ -1777,27 +1788,25 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_low_pc && ctsSzB > 0) {
-            ip_lo   = cts;
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_low_pc && cts.szB > 0) {
+            ip_lo   = cts.u.val;
             have_lo = True;
          }
-         if (attr == DW_AT_high_pc && ctsSzB > 0) {
-            ip_hi1   = cts;
+         if (attr == DW_AT_high_pc && cts.szB > 0) {
+            ip_hi1   = cts.u.val;
             have_hi1 = True;
             if (form != DW_FORM_addr)
                hiIsRelative = True;
          }
-         if (attr == DW_AT_ranges && ctsSzB > 0) {
-            rangeoff = cts;
+         if (attr == DW_AT_ranges && cts.szB > 0) {
+            rangeoff   = cts.u.val;
             have_range = True;
          }
          if (isFunc
              && attr == DW_AT_frame_base
-             && ((ctsMemSzB > 0 && ctsSzB == 0)
-                 || (ctsMemSzB == 0 && ctsSzB > 0))) {
-            fbGX = get_GX( cc, False/*td3*/, cts, ctsSzB, ctsMemSzB );
+             && cts.szB != 0 /* either scalar or nonempty block */) {
+            fbGX = get_GX( cc, False/*td3*/, &cts );
             vg_assert(fbGX);
             VG_(addToXA)(gexprs, &fbGX);
          }
@@ -1863,36 +1872,34 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
          n_attrs++;
-         if (attr == DW_AT_name && ctsMemSzB > 0) {
-            name = ML_(addStr)( cc->di, (HChar*)(UWord)cts, -1 );
+         if (attr == DW_AT_name && cts.szB < 0) {
+            name = ML_(addStrFromCursor)( cc->di, cts.u.cur );
          }
          if (attr == DW_AT_location
-             && ((ctsMemSzB > 0 && ctsSzB == 0)
-                 || (ctsMemSzB == 0 && ctsSzB > 0))) {
-            gexpr = get_GX( cc, False/*td3*/, cts, ctsSzB, ctsMemSzB );
+             && cts.szB != 0 /* either scalar or nonempty block */) {
+            gexpr = get_GX( cc, False/*td3*/, &cts );
             vg_assert(gexpr);
             VG_(addToXA)(gexprs, &gexpr);
          }
-         if (attr == DW_AT_type && ctsSzB > 0) {
-            typeR = cook_die_using_form( cc, (UWord)cts, form );
+         if (attr == DW_AT_type && cts.szB > 0) {
+            typeR = cook_die_using_form( cc, cts.u.val, form );
          }
-         if (attr == DW_AT_external && ctsSzB > 0 && cts > 0) {
+         if (attr == DW_AT_external && cts.szB > 0 && cts.u.val > 0) {
             global = True;
          }
-         if (attr == DW_AT_abstract_origin && ctsSzB > 0) {
-            abs_ori = (UWord)cts;
+         if (attr == DW_AT_abstract_origin && cts.szB > 0) {
+            abs_ori = (UWord)cts.u.val;
          }
-         if (attr == DW_AT_declaration && ctsSzB > 0 && cts > 0) {
+         if (attr == DW_AT_declaration && cts.szB > 0 && cts.u.val > 0) {
             /*declaration = True;*/
          }
-         if (attr == DW_AT_decl_line && ctsSzB > 0) {
-            lineNo = (Int)cts;
+         if (attr == DW_AT_decl_line && cts.szB > 0) {
+            lineNo = (Int)cts.u.val;
          }
-         if (attr == DW_AT_decl_file && ctsSzB > 0) {
-            Int ftabIx = (Int)cts;
+         if (attr == DW_AT_decl_file && cts.szB > 0) {
+            Int ftabIx = (Int)cts.u.val;
             if (ftabIx >= 1
                 && ftabIx < VG_(sizeXA)( parser->filenameTable )) {
                fileName = *(HChar**)
@@ -2132,8 +2139,7 @@
       if (attr == 0 && form == 0) break;
       VG_(printf)("     %18s: ", ML_(pp_DW_AT)(attr));
       /* Get the form contents, so as to print them */
-      get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                         cc, c_die, True, form );
+      get_Form_contents( &cts, cc, c_die, True, form );
       VG_(printf)("\t\n");
    }
    VG_(printf)("\n");
@@ -2298,9 +2304,7 @@
                              CUConst* cc,
                              Bool td3 )
 {
-   ULong cts;
-   Int   ctsSzB;
-   UWord ctsMemSzB;
+   FormContents cts;
    TyEnt typeE;
    TyEnt atomE;
    TyEnt fieldE;
@@ -2331,13 +2335,12 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
          if (attr != DW_AT_language)
             continue;
-         if (ctsSzB == 0)
+         if (cts.szB <= 0)
            goto bad_DIE;
-         switch (cts) {
+         switch (cts.u.val) {
             case DW_LANG_C89: case DW_LANG_C:
             case DW_LANG_C_plus_plus: case DW_LANG_ObjC:
             case DW_LANG_ObjC_plus_plus: case DW_LANG_UPC:
@@ -2370,18 +2373,17 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_name && ctsMemSzB > 0) {
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_name && cts.szB < 0) {
             typeE.Te.TyBase.name
-               = ML_(dinfo_strdup)( "di.readdwarf3.ptD.base_type.1",
-                                    (HChar*)(UWord)cts );
+               = ML_(cur_read_strdup)( cts.u.cur,
+                                       "di.readdwarf3.ptD.base_type.1" );
          }
-         if (attr == DW_AT_byte_size && ctsSzB > 0) {
-            typeE.Te.TyBase.szB = cts;
+         if (attr == DW_AT_byte_size && cts.szB > 0) {
+            typeE.Te.TyBase.szB = cts.u.val;
          }
-         if (attr == DW_AT_encoding && ctsSzB > 0) {
-            switch (cts) {
+         if (attr == DW_AT_encoding && cts.szB > 0) {
+            switch (cts.u.val) {
                case DW_ATE_unsigned: case DW_ATE_unsigned_char:
                case DW_ATE_UTF: /* since DWARF4, e.g. char16_t from C++ */
                case DW_ATE_boolean:/* FIXME - is this correct? */
@@ -2480,13 +2482,13 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_byte_size && ctsSzB > 0) {
-            typeE.Te.TyPorR.szB = cts;
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_byte_size && cts.szB > 0) {
+            typeE.Te.TyPorR.szB = cts.u.val;
          }
-         if (attr == DW_AT_type && ctsSzB > 0) {
-            typeE.Te.TyPorR.typeR = cook_die_using_form( cc, (UWord)cts, form );
+         if (attr == DW_AT_type && cts.szB > 0) {
+            typeE.Te.TyPorR.typeR
+               = cook_die_using_form( cc, (UWord)cts.u.val, form );
          }
       }
       /* Do we have something that looks sane? */
@@ -2510,15 +2512,14 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_name && ctsMemSzB > 0) {
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_name && cts.szB < 0) {
             typeE.Te.TyEnum.name
-              = ML_(dinfo_strdup)( "di.readdwarf3.pTD.enum_type.2",
-                                   (HChar*)(UWord)cts );
+               = ML_(cur_read_strdup)( cts.u.cur,
+                                       "di.readdwarf3.pTD.enum_type.2" );
          }
-         if (attr == DW_AT_byte_size && ctsSzB > 0) {
-            typeE.Te.TyEnum.szB = cts;
+         if (attr == DW_AT_byte_size && cts.szB > 0) {
+            typeE.Te.TyEnum.szB = cts.u.val;
          }
          if (attr == DW_AT_declaration) {
             is_decl = True;
@@ -2590,15 +2591,14 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_name && ctsMemSzB > 0) {
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_name && cts.szB < 0) {
             atomE.Te.Atom.name 
-              = ML_(dinfo_strdup)( "di.readdwarf3.pTD.enumerator.1",
-                                   (HChar*)(UWord)cts );
+              = ML_(cur_read_strdup)( cts.u.cur,
+                                      "di.readdwarf3.pTD.enumerator.1" );
          }
-         if (attr == DW_AT_const_value && ctsSzB > 0) {
-            atomE.Te.Atom.value = cts;
+         if (attr == DW_AT_const_value && cts.szB > 0) {
+            atomE.Te.Atom.value      = cts.u.val;
             atomE.Te.Atom.valueKnown = True;
          }
       }
@@ -2643,21 +2643,20 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_name && ctsMemSzB > 0) {
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_name && cts.szB < 0) {
             typeE.Te.TyStOrUn.name
-               = ML_(dinfo_strdup)( "di.readdwarf3.ptD.struct_type.2",
-                                    (HChar*)(UWord)cts );
+               = ML_(cur_read_strdup)( cts.u.cur,
+                                       "di.readdwarf3.ptD.struct_type.2" );
          }
-         if (attr == DW_AT_byte_size && ctsSzB >= 0) {
-            typeE.Te.TyStOrUn.szB = cts;
+         if (attr == DW_AT_byte_size && cts.szB >= 0) {
+            typeE.Te.TyStOrUn.szB = cts.u.val;
             have_szB = True;
          }
-         if (attr == DW_AT_declaration && ctsSzB > 0 && cts > 0) {
+         if (attr == DW_AT_declaration && cts.szB > 0 && cts.u.val > 0) {
             is_decl = True;
          }
-         if (attr == DW_AT_specification && ctsSzB > 0 && cts > 0) {
+         if (attr == DW_AT_specification && cts.szB > 0 && cts.u.val > 0) {
             is_spec = True;
          }
       }
@@ -2713,29 +2712,30 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_name && ctsMemSzB > 0) {
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_name && cts.szB < 0) {
             fieldE.Te.Field.name
-               = ML_(dinfo_strdup)( "di.readdwarf3.ptD.member.1",
-                                    (HChar*)(UWord)cts );
+               = ML_(cur_read_strdup)( cts.u.cur,
+                                       "di.readdwarf3.ptD.member.1" );
          }
-         if (attr == DW_AT_type && ctsSzB > 0) {
-            fieldE.Te.Field.typeR = cook_die_using_form( cc, (UWord)cts, form );
+         if (attr == DW_AT_type && cts.szB > 0) {
+            fieldE.Te.Field.typeR
+               = cook_die_using_form( cc, (UWord)cts.u.val, form );
          }
          /* There are 2 different cases for DW_AT_data_member_location.
             If it is a constant class attribute, it contains byte offset
             from the beginning of the containing entity.
             Otherwise it is a location expression.  */
-         if (attr == DW_AT_data_member_location && ctsSzB > 0) {
+         if (attr == DW_AT_data_member_location && cts.szB > 0) {
             fieldE.Te.Field.nLoc = -1;
-            fieldE.Te.Field.pos.offset = cts;
-         } else if (attr == DW_AT_data_member_location && ctsMemSzB > 0) {
-            fieldE.Te.Field.nLoc = (UWord)ctsMemSzB;
+            fieldE.Te.Field.pos.offset = cts.u.val;
+         }
+         if (attr == DW_AT_data_member_location && cts.szB <= 0) {
+            fieldE.Te.Field.nLoc = (UWord)(-cts.szB);
             fieldE.Te.Field.pos.loc
-               = ML_(dinfo_memdup)( "di.readdwarf3.ptD.member.2",
-                                    (UChar*)(UWord)cts, 
-                                    (SizeT)fieldE.Te.Field.nLoc );
+               = ML_(cur_read_memdup)( cts.u.cur, 
+                                       (SizeT)fieldE.Te.Field.nLoc,
+                                       "di.readdwarf3.ptD.member.2" );
          }
       }
       /* Do we have a plausible parent? */
@@ -2798,11 +2798,10 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_type && ctsSzB > 0) {
-            typeE.Te.TyArray.typeR = cook_die_using_form( cc, (UWord)cts,
-                                                          form );
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_type && cts.szB > 0) {
+            typeE.Te.TyArray.typeR
+               = cook_die_using_form( cc, (UWord)cts.u.val, form );
          }
       }
       if (typeE.Te.TyArray.typeR == D3_INVALID_CUOFF)
@@ -2837,18 +2836,17 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_lower_bound && ctsSzB > 0) {
-            lower      = (Long)cts;
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_lower_bound && cts.szB > 0) {
+            lower      = (Long)cts.u.val;
             have_lower = True;
          }
-         if (attr == DW_AT_upper_bound && ctsSzB > 0) {
-            upper      = (Long)cts;
+         if (attr == DW_AT_upper_bound && cts.szB > 0) {
+            upper      = (Long)cts.u.val;
             have_upper = True;
          }
-         if (attr == DW_AT_count && ctsSzB > 0) {
-            /*count    = (Long)cts;*/
+         if (attr == DW_AT_count && cts.szB > 0) {
+            /*count    = (Long)cts.u.val;*/
             have_count = True;
          }
       }
@@ -2917,16 +2915,15 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_name && ctsMemSzB > 0) {
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_name && cts.szB < 0) {
             typeE.Te.TyTyDef.name
-               = ML_(dinfo_strdup)( "di.readdwarf3.ptD.typedef.1",
-                                    (HChar*)(UWord)cts );
+               = ML_(cur_read_strdup)( cts.u.cur,
+                                       "di.readdwarf3.ptD.typedef.1" );
          }
-         if (attr == DW_AT_type && ctsSzB > 0) {
-            typeE.Te.TyTyDef.typeR = cook_die_using_form( cc, (UWord)cts,
-                                                          form );
+         if (attr == DW_AT_type && cts.szB > 0) {
+            typeE.Te.TyTyDef.typeR
+               = cook_die_using_form( cc, (UWord)cts.u.val, form );
          }
       }
       /* Do we have something that looks sane? */
@@ -2966,10 +2963,10 @@
          DW_AT   attr = (DW_AT)  get_ULEB128( c_abbv );
          DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
          if (attr == 0 && form == 0) break;
-         get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                            cc, c_die, False/*td3*/, form );
-         if (attr == DW_AT_type && ctsSzB > 0) {
-            typeE.Te.TyQual.typeR = cook_die_using_form( cc, (UWord)cts, form );
+         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
+         if (attr == DW_AT_type && cts.szB > 0) {
+            typeE.Te.TyQual.typeR
+               = cook_die_using_form( cc, (UWord)cts.u.val, form );
             have_ty++;
          }
       }
@@ -3063,8 +3060,7 @@
       if (attr == 0 && form == 0) break;
       VG_(printf)("     %18s: ", ML_(pp_DW_AT)(attr));
       /* Get the form contents, so as to print them */
-      get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                         cc, c_die, True, form );
+      get_Form_contents( &cts, cc, c_die, True, form );
       VG_(printf)("\t\n");
    }
    VG_(printf)("\n");
@@ -3451,17 +3447,14 @@
    start_abbv_c_offset = get_position_of_Cursor( &abbv );
 
    while (True) {
-      ULong cts;
-      Int   ctsSzB;
-      UWord ctsMemSzB;
+      FormContents cts;
       ULong at_name = get_ULEB128( &abbv );
       ULong at_form = get_ULEB128( &abbv );
       if (at_name == 0 && at_form == 0) break;
       TRACE_D3("     %18s: ", ML_(pp_DW_AT)(at_name));
       /* Get the form contents, but ignore them; the only purpose is
          to print them, if td3 is True */
-      get_Form_contents( &cts, &ctsSzB, &ctsMemSzB,
-                         cc, c, td3, (DW_FORM)at_form );
+      get_Form_contents( &cts, cc, c, td3, (DW_FORM)at_form );
       TRACE_D3("\t");
       TRACE_D3("\n");
    }
@@ -3523,17 +3516,12 @@
 void new_dwarf3_reader_wrk ( 
    struct _DebugInfo* di,
    __attribute__((noreturn)) void (*barf)( const HChar* ),
-   UChar* debug_info_img,   SizeT debug_info_sz,
-   UChar* debug_types_img,  SizeT debug_types_sz,
-   UChar* debug_abbv_img,   SizeT debug_abbv_sz,
-   UChar* debug_line_img,   SizeT debug_line_sz,
-   HChar* debug_str_img,    SizeT debug_str_sz,
-   UChar* debug_ranges_img, SizeT debug_ranges_sz,
-   UChar* debug_loc_img,    SizeT debug_loc_sz,
-   UChar* debug_info_alt_img, SizeT debug_info_alt_sz,
-   UChar* debug_abbv_alt_img, SizeT debug_abbv_alt_sz,
-   UChar* debug_line_alt_img, SizeT debug_line_alt_sz,
-   HChar* debug_str_alt_img,  SizeT debug_str_alt_sz
+   DiSlice escn_debug_info,      DiSlice escn_debug_types,
+   DiSlice escn_debug_abbv,      DiSlice escn_debug_line,
+   DiSlice escn_debug_str,       DiSlice escn_debug_ranges,
+   DiSlice escn_debug_loc,       DiSlice escn_debug_info_alt,
+   DiSlice escn_debug_abbv_alt,  DiSlice escn_debug_line_alt,
+   DiSlice escn_debug_str_alt
 )
 {
    XArray* /* of TyEnt */     tyents;
@@ -3620,71 +3608,74 @@
    TRACE_SYMTAB("\n");
    TRACE_SYMTAB("\n------ The contents of .debug_ranges ------\n");
    TRACE_SYMTAB("    Offset   Begin    End\n");
-   init_Cursor( &ranges, debug_ranges_img, 
-                debug_ranges_sz, 0, barf, 
-                "Overrun whilst reading .debug_ranges section(1)" );
-   dr_base = 0;
-   dr_offset = 0;
-   while (True) {
-      UWord  w1, w2;
+   if (ML_(sli_is_valid)(escn_debug_ranges)) {
+      init_Cursor( &ranges, escn_debug_ranges, 0, barf, 
+                   "Overrun whilst reading .debug_ranges section(1)" );
+      dr_base = 0;
+      dr_offset = 0;
+      while (True) {
+         UWord  w1, w2;
 
-      if (is_at_end_Cursor( &ranges ))
-         break;
+         if (is_at_end_Cursor( &ranges ))
+            break;
 
-      /* Read a (host-)word pair.  This is something of a hack since
-         the word size to read is really dictated by the ELF file;
-         however, we assume we're reading a file with the same
-         word-sizeness as the host.  Reasonably enough. */
-      w1 = get_UWord( &ranges );
-      w2 = get_UWord( &ranges );
+         /* Read a (host-)word pair.  This is something of a hack since
+            the word size to read is really dictated by the ELF file;
+            however, we assume we're reading a file with the same
+            word-sizeness as the host.  Reasonably enough. */
+         w1 = get_UWord( &ranges );
+         w2 = get_UWord( &ranges );
 
-      if (w1 == 0 && w2 == 0) {
-         /* end of list.  reset 'base' */
-         TRACE_D3("    %08lx <End of list>\n", dr_offset);
-         dr_base = 0;
-         dr_offset = get_position_of_Cursor( &ranges );
-         continue;
+         if (w1 == 0 && w2 == 0) {
+            /* end of list.  reset 'base' */
+            TRACE_D3("    %08lx <End of list>\n", dr_offset);
+            dr_base = 0;
+            dr_offset = get_position_of_Cursor( &ranges );
+            continue;
+         }
+
+         if (w1 == -1UL) {
+            /* new value for 'base' */
+            TRACE_D3("    %08lx %16lx %08lx (base address)\n",
+                     dr_offset, w1, w2);
+            dr_base = w2;
+            continue;
+         }
+
+         /* else a range [w1+base, w2+base) is denoted */
+         TRACE_D3("    %08lx %08lx %08lx\n",
+                  dr_offset, w1 + dr_base, w2 + dr_base);
       }
-
-      if (w1 == -1UL) {
-         /* new value for 'base' */
-         TRACE_D3("    %08lx %16lx %08lx (base address)\n",
-                  dr_offset, w1, w2);
-         dr_base = w2;
-         continue;
-      }
-
-      /* else a range [w1+base, w2+base) is denoted */
-      TRACE_D3("    %08lx %08lx %08lx\n",
-               dr_offset, w1 + dr_base, w2 + dr_base);
    }
 
    /* Display .debug_abbrev */
-   init_Cursor( &abbv, debug_abbv_img, debug_abbv_sz, 0, barf, 
-                "Overrun whilst reading .debug_abbrev section" );
    TRACE_SYMTAB("\n");
    TRACE_SYMTAB("\n------ The contents of .debug_abbrev ------\n");
-   while (True) {
-      if (is_at_end_Cursor( &abbv ))
-         break;
-      /* Read one abbreviation table */
-      TRACE_D3("  Number TAG\n");
+   if (ML_(sli_is_valid)(escn_debug_abbv)) {
+      init_Cursor( &abbv, escn_debug_abbv, 0, barf, 
+                   "Overrun whilst reading .debug_abbrev section" );
       while (True) {
-         ULong atag;
-         UInt  has_children;
-         ULong acode = get_ULEB128( &abbv );
-         if (acode == 0) break; /* end of the table */
-         atag = get_ULEB128( &abbv );
-         has_children = get_UChar( &abbv );
-         TRACE_D3("   %llu      %s    [%s]\n", 
-                  acode, ML_(pp_DW_TAG)(atag),
-                         ML_(pp_DW_children)(has_children));
+         if (is_at_end_Cursor( &abbv ))
+            break;
+         /* Read one abbreviation table */
+         TRACE_D3("  Number TAG\n");
          while (True) {
-            ULong at_name = get_ULEB128( &abbv );
-            ULong at_form = get_ULEB128( &abbv );
-            if (at_name == 0 && at_form == 0) break;
-            TRACE_D3("    %18s %s\n", 
-                     ML_(pp_DW_AT)(at_name), ML_(pp_DW_FORM)(at_form));
+            ULong atag;
+            UInt  has_children;
+            ULong acode = get_ULEB128( &abbv );
+            if (acode == 0) break; /* end of the table */
+            atag = get_ULEB128( &abbv );
+            has_children = get_UChar( &abbv );
+            TRACE_D3("   %llu      %s    [%s]\n", 
+                     acode, ML_(pp_DW_TAG)(atag),
+                            ML_(pp_DW_children)(has_children));
+            while (True) {
+               ULong at_name = get_ULEB128( &abbv );
+               ULong at_form = get_ULEB128( &abbv );
+               if (at_name == 0 && at_form == 0) break;
+               TRACE_D3("    %18s %s\n", 
+                        ML_(pp_DW_AT)(at_name), ML_(pp_DW_FORM)(at_form));
+            }
          }
       }
    }
@@ -3757,10 +3748,11 @@
       fill in the signatured types hash table.  This lets us handle
       mapping from a type signature to a (cooked) DIE offset directly
       in get_Form_contents.  */
-   if (debug_types_img != NULL) {
-      init_Cursor( &info, debug_types_img, debug_types_sz, 0, barf,
+   if (ML_(sli_is_valid)(escn_debug_types)) {
+      init_Cursor( &info, escn_debug_types, 0, barf,
                    "Overrun whilst reading .debug_types section" );
-      TRACE_D3("\n------ Collecting signatures from .debug_types section ------\n");
+      TRACE_D3("\n------ Collecting signatures from "
+               ".debug_types section ------\n");
 
       while (True) {
          UWord   cu_start_offset, cu_offset_now;
@@ -3771,12 +3763,10 @@
          TRACE_D3("  Compilation Unit @ offset 0x%lx:\n", cu_start_offset);
          /* parse_CU_header initialises the CU's set_abbv_Cursor cache
             (saC_cache) */
-         parse_CU_Header( &cc, td3, &info,
-                          (UChar*)debug_abbv_img, debug_abbv_sz,
-                          True, False );
+         parse_CU_Header( &cc, td3, &info, escn_debug_abbv, True, False );
 
          /* Needed by cook_die.  */
-         cc.types_cuOff_bias = debug_info_sz;
+         cc.types_cuOff_bias = escn_debug_info.szB;
 
          record_signatured_type( signature_types, cc.type_signature,
                                  cook_die( &cc, cc.type_offset ));
@@ -3787,7 +3777,7 @@
          cu_offset_now = (cu_start_offset + cc.unit_length
                           + (cc.is_dw64 ? 12 : 4));
 
-         if (cu_offset_now == debug_types_sz)
+         if (cu_offset_now >= escn_debug_types.szB)
             break;
 
          set_position_of_Cursor ( &info, cu_offset_now );
@@ -3801,19 +3791,19 @@
       require a large number of arguments to be passed in, so it is
       kept inline instead.  */
    for (pass = 0; pass < 3; ++pass) {
-      UWord section_size;
+      ULong section_size;
 
       if (pass == 0) {
-         if (debug_info_alt_img == NULL)
+         if (!ML_(sli_is_valid)(escn_debug_info_alt))
 	    continue;
          /* Now loop over the Compilation Units listed in the alternate
             .debug_info section (see D3SPEC sec 7.5) paras 1 and 2.
             Each compilation unit contains a Compilation Unit Header
             followed by precisely one DW_TAG_compile_unit or
             DW_TAG_partial_unit DIE. */
-         init_Cursor( &info, debug_info_alt_img, debug_info_alt_sz, 0, barf,
+         init_Cursor( &info, escn_debug_info_alt, 0, barf,
                       "Overrun whilst reading alternate .debug_info section" );
-         section_size = debug_info_alt_sz;
+         section_size = escn_debug_info_alt.szB;
 
          TRACE_D3("\n------ Parsing alternate .debug_info section ------\n");
       } else if (pass == 1) {
@@ -3821,23 +3811,23 @@
             section (see D3SPEC sec 7.5) paras 1 and 2.  Each compilation
             unit contains a Compilation Unit Header followed by precisely
             one DW_TAG_compile_unit or DW_TAG_partial_unit DIE. */
-         init_Cursor( &info, debug_info_img, debug_info_sz, 0, barf,
+         init_Cursor( &info, escn_debug_info, 0, barf,
                       "Overrun whilst reading .debug_info section" );
-         section_size = debug_info_sz;
+         section_size = escn_debug_info.szB;
 
          TRACE_D3("\n------ Parsing .debug_info section ------\n");
       } else {
-         if (debug_types_img == NULL)
+         if (!ML_(sli_is_valid)(escn_debug_types))
             continue;
-         init_Cursor( &info, debug_types_img, debug_types_sz, 0, barf,
+         init_Cursor( &info, escn_debug_types, 0, barf,
                       "Overrun whilst reading .debug_types section" );
-         section_size = debug_types_sz;
+         section_size = escn_debug_types.szB;
 
          TRACE_D3("\n------ Parsing .debug_types section ------\n");
       }
 
       while (True) {
-         UWord   cu_start_offset, cu_offset_now;
+         ULong   cu_start_offset, cu_offset_now;
          CUConst cc;
          /* It may be that the stated size of this CU is larger than the
             amount of stuff actually in it.  icc9 seems to generate CUs
@@ -3885,36 +3875,30 @@
 
          cu_start_offset = get_position_of_Cursor( &info );
          TRACE_D3("\n");
-         TRACE_D3("  Compilation Unit @ offset 0x%lx:\n", cu_start_offset);
+         TRACE_D3("  Compilation Unit @ offset 0x%llx:\n", cu_start_offset);
          /* parse_CU_header initialises the CU's set_abbv_Cursor cache
             (saC_cache) */
-         if (pass == 0)
-            parse_CU_Header( &cc, td3, &info,
-                             (UChar*)debug_abbv_alt_img, debug_abbv_alt_sz,
+         if (pass == 0) {
+            parse_CU_Header( &cc, td3, &info, escn_debug_abbv_alt,
                              False, True );
-         else
-            parse_CU_Header( &cc, td3, &info,
-                             (UChar*)debug_abbv_img, debug_abbv_sz,
+         } else {
+            parse_CU_Header( &cc, td3, &info, escn_debug_abbv,
                              pass == 2, False );
-         cc.debug_str_img    = pass == 0 ? debug_str_alt_img : debug_str_img;
-         cc.debug_str_sz     = pass == 0 ? debug_str_alt_sz : debug_str_sz;
-         cc.debug_ranges_img = debug_ranges_img;
-         cc.debug_ranges_sz  = debug_ranges_sz;
-         cc.debug_loc_img    = debug_loc_img;
-         cc.debug_loc_sz     = debug_loc_sz;
-         cc.debug_line_img   = pass == 0 ? debug_line_alt_img : debug_line_img;
-         cc.debug_line_sz    = pass == 0 ? debug_line_alt_sz : debug_line_sz;
-         cc.debug_info_img   = pass == 0 ? debug_info_alt_img : debug_info_img;
-         cc.debug_info_sz    = pass == 0 ? debug_info_alt_sz : debug_info_sz;
-         cc.debug_types_img  = debug_types_img;
-         cc.debug_types_sz   = debug_types_sz;
-         cc.debug_info_alt_img = debug_info_alt_img;
-         cc.debug_info_alt_sz = debug_info_alt_sz;
-         cc.debug_str_alt_img = debug_str_alt_img;
-         cc.debug_str_alt_sz = debug_str_alt_sz;
-         cc.types_cuOff_bias = debug_info_sz;
-         cc.alt_cuOff_bias   = debug_info_sz + debug_types_sz;
-         cc.cu_start_offset  = cu_start_offset;
+         }
+         cc.escn_debug_str      = pass == 0 ? escn_debug_str_alt
+                                            : escn_debug_str;
+         cc.escn_debug_ranges   = escn_debug_ranges;
+         cc.escn_debug_loc      = escn_debug_loc;
+         cc.escn_debug_line     = pass == 0 ? escn_debug_line_alt
+                                            : escn_debug_line;
+         cc.escn_debug_info     = pass == 0 ? escn_debug_info_alt
+                                            : escn_debug_info;
+         cc.escn_debug_types    = escn_debug_types;
+         cc.escn_debug_info_alt = escn_debug_info_alt;
+         cc.escn_debug_str_alt  = escn_debug_str_alt;
+         cc.types_cuOff_bias    = escn_debug_info.szB;
+         cc.alt_cuOff_bias      = escn_debug_info.szB + escn_debug_types.szB;
+         cc.cu_start_offset     = cu_start_offset;
          cc.di = di;
          /* The CU's svma can be deduced by looking at the AT_low_pc
             value in the top level TAG_compile_unit, which is the topmost
@@ -3955,7 +3939,7 @@
 
          cu_offset_now = get_position_of_Cursor( &info );
 
-         if (0) VG_(printf)("Travelled: %lu  size %llu\n",
+         if (0) VG_(printf)("Travelled: %llu  size %llu\n",
                             cu_offset_now - cc.cu_start_offset,
                             cc.unit_length + (cc.is_dw64 ? 12 : 4));
 
@@ -3964,7 +3948,7 @@
          /* .. vs how big we have found it to be */
          cu_amount_used = cu_offset_now - cc.cu_start_offset;
 
-         if (1) TRACE_D3("offset now %ld, d-i-size %ld\n",
+         if (1) TRACE_D3("offset now %lld, d-i-size %lld\n",
                          cu_offset_now, section_size);
          if (cu_offset_now > section_size)
             barf("toplevel DIEs beyond end of CU");
@@ -4093,12 +4077,12 @@
    vg_assert(dioff_lookup_tab);
 
    n = VG_(sizeXA)( tempvars );
-   Word first_primary_var;
+   Word first_primary_var = 0;
    for (first_primary_var = 0;
-        debug_info_alt_sz && first_primary_var < n;
+        escn_debug_info_alt.szB/*really?*/ && first_primary_var < n;
         first_primary_var++) {
       varp = *(TempVar**)VG_(indexXA)( tempvars, first_primary_var );
-      if (varp->dioff < debug_info_sz + debug_types_sz)
+      if (varp->dioff < escn_debug_info.szB + escn_debug_types.szB)
          break;
    }
    for (i = 0; i < n; i++) {
@@ -4353,17 +4337,12 @@
 void 
 ML_(new_dwarf3_reader) (
    struct _DebugInfo* di,
-   UChar* debug_info_img,   SizeT debug_info_sz,
-   UChar* debug_types_img,  SizeT debug_types_sz,
-   UChar* debug_abbv_img,   SizeT debug_abbv_sz,
-   UChar* debug_line_img,   SizeT debug_line_sz,
-   HChar* debug_str_img,    SizeT debug_str_sz,
-   UChar* debug_ranges_img, SizeT debug_ranges_sz,
-   UChar* debug_loc_img,    SizeT debug_loc_sz,
-   UChar* debug_info_alt_img, SizeT debug_info_alt_sz,
-   UChar* debug_abbv_alt_img, SizeT debug_abbv_alt_sz,
-   UChar* debug_line_alt_img, SizeT debug_line_alt_sz,
-   HChar* debug_str_alt_img,  SizeT debug_str_alt_sz
+   DiSlice escn_debug_info,      DiSlice escn_debug_types,
+   DiSlice escn_debug_abbv,      DiSlice escn_debug_line,
+   DiSlice escn_debug_str,       DiSlice escn_debug_ranges,
+   DiSlice escn_debug_loc,       DiSlice escn_debug_info_alt,
+   DiSlice escn_debug_abbv_alt,  DiSlice escn_debug_line_alt,
+   DiSlice escn_debug_str_alt
 )
 {
    volatile Int  jumped;
@@ -4381,17 +4360,12 @@
    if (jumped == 0) {
       /* try this ... */
       new_dwarf3_reader_wrk( di, barf,
-                             debug_info_img,   debug_info_sz,
-                             debug_types_img,  debug_types_sz,
-                             debug_abbv_img,   debug_abbv_sz,
-                             debug_line_img,   debug_line_sz,
-                             debug_str_img,    debug_str_sz,
-                             debug_ranges_img, debug_ranges_sz,
-                             debug_loc_img,    debug_loc_sz,
-                             debug_info_alt_img, debug_info_alt_sz,
-                             debug_abbv_alt_img, debug_abbv_alt_sz,
-                             debug_line_alt_img, debug_line_alt_sz,
-                             debug_str_alt_img,  debug_str_alt_sz);
+                             escn_debug_info,     escn_debug_types,
+                             escn_debug_abbv,     escn_debug_line,
+                             escn_debug_str,      escn_debug_ranges,
+                             escn_debug_loc,      escn_debug_info_alt,
+                             escn_debug_abbv_alt, escn_debug_line_alt,
+                             escn_debug_str_alt );
       d3rd_jmpbuf_valid = False;
       TRACE_D3("\n------ .debug_info reading was successful ------\n");
    } else {
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
index cf7b5d3..7cd4297 100644
--- a/coregrind/m_debuginfo/readelf.c
+++ b/coregrind/m_debuginfo/readelf.c
@@ -37,14 +37,13 @@
 #include "pub_core_libcbase.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_libcassert.h"
-#include "pub_core_libcfile.h"
-#include "pub_core_aspacemgr.h"    /* for mmaping debuginfo files */
 #include "pub_core_machine.h"      /* VG_ELF_CLASS */
 #include "pub_core_options.h"
 #include "pub_core_oset.h"
 #include "pub_core_tooliface.h"    /* VG_(needs) */
 #include "pub_core_xarray.h"
 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
+#include "priv_image.h"
 #include "priv_d3basics.h"
 #include "priv_tytypes.h"
 #include "priv_storage.h"
@@ -107,7 +106,6 @@
    them.  It calls onwards to readdwarf.c to read DWARF2/3 line number
    and call frame info found. */
 
-
 /* Identify an ELF object file by peering at the first few bytes of
    it. */
 
@@ -135,18 +133,33 @@
    ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
           || ehdr->e_type == ET_REL);
 
-   if (ok)
-      return True;
-   else
+   return ok ? True : False;
+}
+
+
+/* The same thing, but operating on a DiImage instead. */
+
+static Bool is_elf_object_file_by_DiImage( DiImage* img, Bool rel_ok )
+{
+   /* Be sure this doesn't make the frame too big. */
+   vg_assert(sizeof(ElfXX_Ehdr) <= 512);
+
+   ElfXX_Ehdr ehdr;
+   if (!ML_(img_valid)(img, 0, sizeof(ehdr)))
       return False;
+
+   ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
+   return ML_(is_elf_object_file)( &ehdr, sizeof(ehdr), rel_ok );
 }
 
 
 /* Show a raw ELF symbol, given its in-image address and name. */
 
 static
-void show_raw_elf_symbol ( Int i, 
-                           ElfXX_Sym* sym, const HChar* sym_name, Addr sym_svma,
+void show_raw_elf_symbol ( DiImage* strtab_img,
+                           Int i, 
+                           ElfXX_Sym* sym,
+                           DiOffT sym_name_ioff, Addr sym_svma,
                            Bool ppc64_linux_format )
 {
    const HChar* space = ppc64_linux_format ? "                  " : "";
@@ -169,10 +182,15 @@
       case STT_HIPROC:  VG_(printf)("hip "); break;
       default:          VG_(printf)("??? "); break;
    }
+   HChar* sym_name = NULL;
+   if (sym->st_name)
+      sym_name = ML_(img_strdup)(strtab_img, "di.sres.1", sym_name_ioff);
    VG_(printf)(": svma %#010lx, %ssz %4ld  %s\n",
                sym_svma, space, sym->st_size + 0UL,
-               ( sym->st_name ? sym_name : "NONAME" ) ); 
-}               
+               (sym_name ? sym_name : "NONAME") ); 
+   if (sym_name)
+      ML_(dinfo_free)(sym_name);
+}
 
 
 /* Decide whether SYM is something we should collect, and if so, copy
@@ -207,21 +225,22 @@
         /* INPUTS */
         struct _DebugInfo* di, /* containing DebugInfo */
         ElfXX_Sym* sym,        /* ELF symbol */
-        HChar*     sym_name,   /* name */
+        DiOffT     sym_name_ioff, /* name, may be absent (DiOffT_INVALID) */
+        DiSlice*   escn_strtab,   /* holds the name */
         Addr       sym_svma,   /* address as stated in the object file */
         Bool       symtab_in_debug, /* symbol table is in the debug file */
-        UChar*     opd_img,    /* oimage of .opd sec (ppc64-linux only) */
+        DiSlice*   escn_opd,   /* the .opd (ppc64-linux only) */
         PtrdiffT   opd_bias,   /* for biasing AVMAs found in .opd */
         /* OUTPUTS */
-        HChar** sym_name_out,  /* name we should record */
-        Addr*  sym_avma_out,   /* addr we should record */
-        Int*   sym_size_out,   /* symbol size */
-        Addr*  sym_tocptr_out, /* ppc64-linux only: R2 value to be
-                                  used on entry */
-        Bool*  from_opd_out,   /* ppc64-linux only: did we deref an
+        DiOffT* sym_name_out_ioff, /* name (in strtab) we should record */
+        Addr*   sym_avma_out,   /* addr we should record */
+        Int*    sym_size_out,   /* symbol size */
+        Addr*   sym_tocptr_out, /* ppc64-linux only: R2 value to be
+                                   used on entry */
+        Bool*   from_opd_out,   /* ppc64-linux only: did we deref an
                                   .opd entry? */
-        Bool*  is_text_out,    /* is this a text symbol? */
-        Bool*  is_ifunc        /* is this a  STT_GNU_IFUNC function ?*/
+        Bool*   is_text_out,    /* is this a text symbol? */
+        Bool*   is_ifunc        /* is this a  STT_GNU_IFUNC function ?*/
      )
 {
    Bool plausible;
@@ -233,12 +252,12 @@
    PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
 
    /* Set defaults */
-   *sym_name_out   = sym_name;
-   *sym_avma_out   = sym_svma; /* we will bias this shortly */
-   *is_text_out    = True;
-   *sym_tocptr_out = 0; /* unknown/inapplicable */
-   *from_opd_out   = False;
-   *is_ifunc       = False;
+   *sym_name_out_ioff = sym_name_ioff;
+   *sym_avma_out      = sym_svma; /* we will bias this shortly */
+   *is_text_out       = True;
+   *sym_tocptr_out    = 0; /* unknown/inapplicable */
+   *from_opd_out      = False;
+   *is_ifunc          = False;
    /* Get the symbol size, but restrict it to fit in a signed 32 bit
       int.  Also, deal with the stupid case of negative size by making
       the size be 1.  Note that sym->st_size has type UWord,
@@ -374,11 +393,16 @@
       return False;
 
    /* Ignore if nameless. */
-   if (sym_name == (ElfXX_Word)0
+   if (sym_name_ioff == DiOffT_INVALID
        || /* VG_(strlen)(sym_name) == 0 */
           /* equivalent but cheaper ... */
-          sym_name[0] == 0) {
-      TRACE_SYMTAB("    ignore -- nameless: %s\n", sym_name);
+          ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') {
+      if (TRACE_SYMTAB_ENABLED) {
+         HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                           "di.gesi.1", sym_name_ioff);
+         TRACE_SYMTAB("    ignore -- nameless: %s\n", sym_name);
+         if (sym_name) ML_(dinfo_free)(sym_name);
+      }
       return False;
    }
 
@@ -399,7 +423,12 @@
 #     if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
       *sym_size_out = 2048;
 #     else
-      TRACE_SYMTAB("    ignore -- size=0: %s\n", sym_name);
+      if (TRACE_SYMTAB_ENABLED) {
+         HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                           "di.gesi.2", sym_name_ioff);
+         TRACE_SYMTAB("    ignore -- size=0: %s\n", sym_name);
+         if (sym_name) ML_(dinfo_free)(sym_name);
+      }
       return False;
 #     endif
    }
@@ -408,7 +437,12 @@
       symbols, and particularly reduces the number of
       overlapping address ranges.  Don't ask me why ... */
    if ((Int)sym->st_value == 0) {
-      TRACE_SYMTAB( "    ignore -- valu=0: %s\n", sym_name);
+      if (TRACE_SYMTAB_ENABLED) {
+         HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                           "di.gesi.3", sym_name_ioff);
+         TRACE_SYMTAB( "    ignore -- valu=0: %s\n", sym_name);
+         if (sym_name) ML_(dinfo_free)(sym_name);
+      }
       return False;
    }
 
@@ -418,14 +452,24 @@
        && di->got_size > 0
        && *sym_avma_out >= di->got_avma 
        && *sym_avma_out <  di->got_avma + di->got_size) {
-      TRACE_SYMTAB("    ignore -- in GOT: %s\n", sym_name);
+      if (TRACE_SYMTAB_ENABLED) {
+         HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                           "di.gesi.4", sym_name_ioff);
+         TRACE_SYMTAB("    ignore -- in GOT: %s\n", sym_name);
+         if (sym_name) ML_(dinfo_free)(sym_name);
+      }
       return False;
    }
    if (di->plt_present
        && di->plt_size > 0
        && *sym_avma_out >= di->plt_avma
        && *sym_avma_out <  di->plt_avma + di->plt_size) {
-      TRACE_SYMTAB("    ignore -- in PLT: %s\n", sym_name);
+      if (TRACE_SYMTAB_ENABLED) {
+         HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                           "di.gesi.5", sym_name_ioff);
+         TRACE_SYMTAB("    ignore -- in PLT: %s\n", sym_name);
+         if (sym_name) ML_(dinfo_free)(sym_name);
+      }
       return False;
    }
 
@@ -446,11 +490,15 @@
        && *sym_avma_out >= di->opd_avma
        && *sym_avma_out <  di->opd_avma + di->opd_size) {
 #     if !defined(VGP_ppc64_linux)
-      TRACE_SYMTAB("    ignore -- in OPD: %s\n", sym_name);
+      if (TRACE_SYMTAB_ENABLED) {
+         HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                           "di.gesi.6", sym_name_ioff);
+         TRACE_SYMTAB("    ignore -- in OPD: %s\n", sym_name);
+         if (sym_name) ML_(dinfo_free)(sym_name);
+      }
       return False;
 #     else
       Int    offset_in_opd;
-      ULong* fn_descr;
       Bool   details = 1||False;
 
       if (details)
@@ -458,7 +506,12 @@
                       (void*)(opd_bias), (void*)*sym_avma_out);
 
       if (!VG_IS_8_ALIGNED(*sym_avma_out)) {
-         TRACE_SYMTAB("    ignore -- not 8-aligned: %s\n", sym_name);
+         if (TRACE_SYMTAB_ENABLED) {
+            HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                              "di.gesi.6a", sym_name_ioff);
+            TRACE_SYMTAB("    ignore -- not 8-aligned: %s\n", sym_name);
+            if (sym_name) ML_(dinfo_free)(sym_name);
+         }
          return False;
       }
 
@@ -468,7 +521,12 @@
 
       offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma);
       if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
-         TRACE_SYMTAB("    ignore -- invalid OPD offset: %s\n", sym_name);
+         if (TRACE_SYMTAB_ENABLED) {
+            HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                              "di.gesi.6a", sym_name_ioff);
+            TRACE_SYMTAB("    ignore -- invalid OPD offset: %s\n", sym_name);
+            if (sym_name) ML_(dinfo_free)(sym_name);
+         }
          return False;
       }
 
@@ -478,7 +536,24 @@
          opd_img is the start address of the .opd in the oimage.
          Hence: */
 
-      fn_descr = (ULong*)(opd_img + offset_in_opd);
+      ULong fn_descr[2]; /* is actually 3 words, but we need only 2 */
+      if (!ML_(img_valid)(escn_opd->img, escn_opd->ioff + offset_in_opd,
+                          sizeof(fn_descr))) {
+         if (TRACE_SYMTAB_ENABLED) {
+            HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
+                                              "di.gesi.6b", sym_name_ioff);
+            TRACE_SYMTAB("    ignore -- invalid OPD fn_descr offset: %s\n",
+                         sym_name);
+            if (sym_name) ML_(dinfo_free)(sym_name);
+
+         }
+         return False;
+      }
+
+      /* This can't fail now, because we just checked the offset
+         above. */
+      ML_(img_get)(&fn_descr[0], escn_opd->img,
+                   escn_opd->ioff + offset_in_opd, sizeof(fn_descr));
 
       if (details) 
          TRACE_SYMTAB("opdXXY: offset %d,  fn_descr %p\n", 
@@ -512,9 +587,10 @@
 #  if defined(VGP_ppc64_linux)
    if (di->opd_size > 0
        && !is_in_opd
-       && sym_name[0] == '.') {
+       && *sym_name_out_ioff != DiOffT_INVALID
+       && ML_(img_get_UChar)(escn_strtab->img, *sym_name_out_ioff) == '.') {
       vg_assert(!(*from_opd_out));
-      *sym_name_out = &sym_name[1];
+      (*sym_name_out_ioff)++;
    }
 #  endif
 
@@ -595,7 +671,7 @@
 #  if defined(VGP_ppc64_linux)
    /* It's crucial that we never add symbol addresses in the .opd
       section.  This would completely mess up function redirection and
-      intercepting.  This assert ensures that anysymbols that make it
+      intercepting.  This assert ensures that any symbols that make it
       into the symbol table on ppc64-linux don't point into .opd. */
    if (di->opd_present && di->opd_size > 0) {
       vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma
@@ -609,27 +685,18 @@
 
 
 /* Read an ELF symbol table (normal or dynamic).  This one is for the
-   "normal" case ({x86,amd64,ppc32}-linux). */
+   "normal" case ({x86,amd64,ppc32,arm,mips32,mips64}-linux). */
 static
 __attribute__((unused)) /* not referred to on all targets */
 void read_elf_symtab__normal( 
         struct _DebugInfo* di, const HChar* tab_name,
-        ElfXX_Sym* symtab_img, SizeT symtab_szB,
-        HChar*     strtab_img, SizeT strtab_szB,
-        Bool       symtab_in_debug,
-        UChar*     opd_img /* ppc64-linux only */ 
+        DiSlice*   escn_symtab,
+        DiSlice*   escn_strtab,
+        DiSlice*   escn_opd, /* ppc64-linux only */ 
+        Bool       symtab_in_debug
      )
 {
-   Word       i;
-   Addr       sym_svma, sym_avma_really;
-   HChar     *sym_name, *sym_name_really;
-   Int        sym_size;
-   Addr       sym_tocptr;
-   Bool       from_opd, is_text, is_ifunc;
-   DiSym      disym;
-   ElfXX_Sym *sym;
-
-   if (strtab_img == NULL || symtab_img == NULL) {
+   if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
       HChar buf[80];
       vg_assert(VG_(strlen)(tab_name) < 40);
       VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
@@ -637,47 +704,61 @@
       return;
    }
 
-   TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%ld entries) ---\n",
-                tab_name, symtab_szB/sizeof(ElfXX_Sym) );
+   TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%lld entries) ---\n",
+                tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
 
    /* Perhaps should start at i = 1; ELF docs suggest that entry
       0 always denotes 'unknown symbol'. */
-   for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
-      sym      = & symtab_img[i];
-      sym_name = strtab_img + sym->st_name;
-      sym_svma = sym->st_value;
+   Word i;
+   for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
+      ElfXX_Sym sym;
+      ML_(img_get)(&sym, escn_symtab->img,
+                   escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
+      DiOffT sym_name = escn_strtab->ioff + sym.st_name;
+      Addr   sym_svma = sym.st_value;
 
       if (di->trace_symtab)
-         show_raw_elf_symbol(i, sym, sym_name, sym_svma, False);
+        show_raw_elf_symbol(escn_strtab->img, i,
+                            &sym, sym_name, sym_svma, False);
 
-      if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
-                              symtab_in_debug,
-                              opd_img, di->text_bias,
+      Addr   sym_avma_really = 0;
+      Int    sym_size = 0;
+      Addr   sym_tocptr = 0;
+      Bool   from_opd = False, is_text = False, is_ifunc = False;
+      DiOffT sym_name_really = DiOffT_INVALID;
+      if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab, 
+                              sym_svma, symtab_in_debug,
+                              escn_opd, di->text_bias,
                               &sym_name_really, 
                               &sym_avma_really,
                               &sym_size,
                               &sym_tocptr,
                               &from_opd, &is_text, &is_ifunc)) {
 
+         DiSym  disym;
+         VG_(memset)(&disym, 0, sizeof(disym));
+         HChar* cstr = ML_(img_strdup)(escn_strtab->img,
+                                       "di.res__n.1", sym_name_really);
          disym.addr      = sym_avma_really;
          disym.tocptr    = sym_tocptr;
-         disym.pri_name  = ML_(addStr) ( di, sym_name_really, -1 );
+         disym.pri_name  = ML_(addStr) ( di, cstr, -1 );
          disym.sec_names = NULL;
          disym.size      = sym_size;
          disym.isText    = is_text;
          disym.isIFunc   = is_ifunc;
+         if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
          vg_assert(disym.pri_name);
          vg_assert(disym.tocptr == 0); /* has no role except on ppc64-linux */
          ML_(addSym) ( di, &disym );
 
-         if (di->trace_symtab) {
-            VG_(printf)("    rec(%c) [%4ld]:          "
-                        "  val %#010lx, sz %4d  %s\n",
-                        is_text ? 't' : 'd',
-                        i,
-                        disym.addr,
-                        (Int)disym.size,
-                        (HChar*)disym.pri_name
+         if (TRACE_SYMTAB_ENABLED) {
+            TRACE_SYMTAB("    rec(%c) [%4ld]:          "
+                         "  val %#010lx, sz %4d  %s\n",
+                         is_text ? 't' : 'd',
+                         i,
+                         disym.addr,
+                         (Int)disym.size,
+                         (HChar*)disym.pri_name
             );
          }
 
@@ -691,8 +772,12 @@
 
 typedef
    struct { 
-      Addr   addr; 
-      HChar* name; 
+      Addr   addr;
+      DiOffT name;
+      /* We have to store also the DiImage* so as to give context for
+         |name|.  This is not part of the key (in terms of lookup) but
+         there's no easy other way to do this.  Ugly. */
+      DiImage* img;
    }
    TempSymKey;
 
@@ -707,37 +792,37 @@
    }
    TempSym;
 
-static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) {
+static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 )
+{
+   /* Stay sane ... */
+   vg_assert(key1->img == elem2->key.img);
+   vg_assert(key1->img != NULL);
    if (key1->addr < elem2->key.addr) return -1;
    if (key1->addr > elem2->key.addr) return 1;
-   return (Word)VG_(strcmp)(key1->name, elem2->key.name);
+   vg_assert(key1->name != DiOffT_INVALID);
+   vg_assert(elem2->key.name != DiOffT_INVALID);
+   return (Word)ML_(img_strcmp)(key1->img, key1->name, elem2->key.name);
 }
 
 static
 __attribute__((unused)) /* not referred to on all targets */
 void read_elf_symtab__ppc64_linux( 
         struct _DebugInfo* di, const HChar* tab_name,
-        ElfXX_Sym* symtab_img, SizeT symtab_szB,
-        HChar*     strtab_img, SizeT strtab_szB,
-        Bool       symtab_in_debug,
-        UChar*     opd_img /* ppc64-linux only */ 
+        DiSlice*   escn_symtab,
+        DiSlice*   escn_strtab,
+        DiSlice*   escn_opd, /* ppc64-linux only */ 
+        Bool       symtab_in_debug
      )
 {
    Word        i;
    Int         old_size;
-   Addr        sym_svma, sym_avma_really;
-   HChar      *sym_name, *sym_name_really;
-   Int         sym_size;
-   Addr        sym_tocptr;
-   Bool        from_opd, modify_size, modify_tocptr, is_text, is_ifunc;
-   DiSym       disym;
-   ElfXX_Sym  *sym;
+   Bool        modify_size, modify_tocptr;
    OSet       *oset;
    TempSymKey  key;
    TempSym    *elem;
    TempSym    *prev;
 
-   if (strtab_img == NULL || symtab_img == NULL) {
+   if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
       HChar buf[80];
       vg_assert(VG_(strlen)(tab_name) < 40);
       VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
@@ -745,8 +830,8 @@
       return;
    }
 
-   TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%ld entries) ---\n",
-                tab_name, symtab_szB/sizeof(ElfXX_Sym) );
+   TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%lld entries) ---\n",
+                tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
 
    oset = VG_(OSetGen_Create)( offsetof(TempSym,key), 
                                (OSetCmp_t)cmp_TempSymKey, 
@@ -756,17 +841,27 @@
 
    /* Perhaps should start at i = 1; ELF docs suggest that entry
       0 always denotes 'unknown symbol'. */
-   for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
-      sym      = & symtab_img[i];
-      sym_name = strtab_img + sym->st_name;
-      sym_svma = sym->st_value;
+   for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
+      ElfXX_Sym sym;
+      ML_(img_get)(&sym, escn_symtab->img,
+                   escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
+      DiOffT sym_name = escn_strtab->ioff + sym.st_name;
+      Addr   sym_svma = sym.st_value;
 
       if (di->trace_symtab)
-         show_raw_elf_symbol(i, sym, sym_name, sym_svma, True);
+         show_raw_elf_symbol(escn_strtab->img, i,
+                             &sym, sym_name, sym_svma, True);
 
-      if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
-                              symtab_in_debug,
-                              opd_img, di->text_bias,
+      Addr   sym_avma_really = 0;
+      Int    sym_size = 0;
+      Addr   sym_tocptr = 0;
+      Bool   from_opd = False, is_text = False, is_ifunc = False;
+      DiOffT sym_name_really = DiOffT_INVALID;
+      DiSym  disym;
+      VG_(memset)(&disym, 0, sizeof(disym));
+      if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
+                              sym_svma, symtab_in_debug,
+                              escn_opd, di->text_bias,
                               &sym_name_really, 
                               &sym_avma_really,
                               &sym_size,
@@ -776,6 +871,7 @@
          /* Check if we've seen this (name,addr) key before. */
          key.addr = sym_avma_really;
          key.name = sym_name_really;
+         key.img  = escn_strtab->img;
          prev = VG_(OSetGen_Lookup)( oset, &key );
 
          if (prev) {
@@ -815,21 +911,21 @@
 
             if (modify_size && di->trace_symtab) {
                VG_(printf)("    modify (old sz %4d)    "
-                           " val %#010lx, toc %#010lx, sz %4d  %s\n",
+                           " val %#010lx, toc %#010lx, sz %4d  %lld\n",
                            old_size,
                            prev->key.addr,
                            prev->tocptr,
-                           (Int)   prev->size, 
-                           (HChar*)prev->key.name
+                           (Int)  prev->size, 
+                           (ULong)prev->key.name
                );
             }
             if (modify_tocptr && di->trace_symtab) {
                VG_(printf)("    modify (upd tocptr)     "
-                           " val %#010lx, toc %#010lx, sz %4d  %s\n",
+                           " val %#010lx, toc %#010lx, sz %4d  %lld\n",
                            prev->key.addr,
                            prev->tocptr,
-                           (Int)   prev->size,
-                           (HChar*)prev->key.name
+                           (Int)  prev->size,
+                           (ULong)prev->key.name
                );
             }
 
@@ -846,14 +942,17 @@
             elem->is_ifunc = is_ifunc;
             VG_(OSetGen_Insert)(oset, elem);
             if (di->trace_symtab) {
+               HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
+                                            elem->key.name);
                VG_(printf)("   to-oset [%4ld]:          "
                            "  val %#010lx, toc %#010lx, sz %4d  %s\n",
                            i,
                            elem->key.addr,
                            elem->tocptr,
-                           (Int)   elem->size,
-                           (HChar*)elem->key.name
+                           (Int)  elem->size,
+                           str
                );
+               if (str) ML_(dinfo_free)(str);
             }
 
          }
@@ -867,13 +966,18 @@
    VG_(OSetGen_ResetIter)( oset );
 
    while ( (elem = VG_(OSetGen_Next)(oset)) ) {
+      DiSym disym;
+      VG_(memset)(&disym, 0, sizeof(disym));
+      HChar* cstr = ML_(img_strdup)(escn_strtab->img,
+                                    "di.res__ppc64.1", elem->key.name);
       disym.addr      = elem->key.addr;
       disym.tocptr    = elem->tocptr;
-      disym.pri_name  = ML_(addStr) ( di, elem->key.name, -1 );
+      disym.pri_name  = ML_(addStr) ( di, cstr, -1 );
       disym.sec_names = NULL;
       disym.size      = elem->size;
       disym.isText    = elem->is_text;
       disym.isIFunc   = elem->is_ifunc;
+      if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
       vg_assert(disym.pri_name != NULL);
 
       ML_(addSym) ( di, &disym );
@@ -900,46 +1004,48 @@
  * can be found here:
  *
  * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
+ *
+ * Returned string must be freed by the caller.
  */
 static
-HChar *find_buildid(Addr image, UWord n_image, Bool rel_ok, Bool search_shdrs)
+HChar* find_buildid(DiImage* img, Bool rel_ok, Bool search_shdrs)
 {
    HChar* buildid = NULL;
-   __attribute__((unused)) /* on Android, at least */
-   ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
 
-#ifdef NT_GNU_BUILD_ID
-   if (n_image >= sizeof(ElfXX_Ehdr) &&
-       ML_(is_elf_object_file)(ehdr, n_image, rel_ok)) {
+#  ifdef NT_GNU_BUILD_ID
+   if (is_elf_object_file_by_DiImage(img, rel_ok)) {
       Word i;
 
-      for (i = 0; i < ehdr->e_phnum; i++) {
-         ElfXX_Phdr* phdr
-            = (ElfXX_Phdr*)(image + ehdr->e_phoff + i * ehdr->e_phentsize);
+      ElfXX_Ehdr ehdr;
+      ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
+      for (i = 0; i < ehdr.e_phnum; i++) {
+         ElfXX_Phdr phdr;
+         ML_(img_get)(&phdr, img,
+                      ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
 
-         if (phdr->p_type == PT_NOTE) {
-            ElfXX_Off offset =  phdr->p_offset;
+         if (phdr.p_type == PT_NOTE) {
+            ElfXX_Off note_ioff = phdr.p_offset;
 
-            while (offset < phdr->p_offset + phdr->p_filesz) {
-               ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
-               HChar *name = (HChar *)note + sizeof(ElfXX_Nhdr);
-               UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
-               Word j;
-
-               if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
-                   note->n_type == NT_GNU_BUILD_ID) {
+            while (note_ioff < phdr.p_offset + phdr.p_filesz) {
+               ElfXX_Nhdr note;
+               ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
+               DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
+               DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
+               if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
+                   && note.n_type == NT_GNU_BUILD_ID) {
                   buildid = ML_(dinfo_zalloc)("di.fbi.1",
-                                              note->n_descsz * 2 + 1);
-                  
-                  for (j = 0; j < note->n_descsz; j++) {
+                                              note.n_descsz * 2 + 1);
+                  Word j;
+                  for (j = 0; j < note.n_descsz; j++) {
+                     UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
                      VG_(sprintf)(buildid + VG_(strlen)(buildid), 
-                                  "%02x", desc[j]);
+                                  "%02x", (UInt)desc_j);
                   }
                }
 
-               offset = offset + sizeof(ElfXX_Nhdr)
-                               + ((note->n_namesz + 3) & ~3)
-                               + ((note->n_descsz + 3) & ~3);
+               note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
+                                     + ((note.n_namesz + 3) & ~3)
+                                     + ((note.n_descsz + 3) & ~3);
             }            
          }
       }
@@ -951,293 +1057,138 @@
       if (buildid || (!rel_ok && !search_shdrs))
          return buildid;
 
-      for (i = 0; i < ehdr->e_shnum; i++) {
-         ElfXX_Shdr* shdr
-            = (ElfXX_Shdr*)(image + ehdr->e_shoff + i * ehdr->e_shentsize);
+      for (i = 0; i < ehdr.e_shnum; i++) {
+         ElfXX_Shdr shdr;
+         ML_(img_get)(&shdr, img,
+                      ehdr.e_shoff + i * ehdr.e_shentsize, sizeof(shdr));
 
-         if (shdr->sh_type == SHT_NOTE) {
-            ElfXX_Off offset =  shdr->sh_offset;
+         if (shdr.sh_type == SHT_NOTE) {
+            ElfXX_Off note_ioff = shdr.sh_offset;
 
-            while (offset < shdr->sh_offset + shdr->sh_size) {
-               ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
-               HChar *name = (HChar *)note + sizeof(ElfXX_Nhdr);
-               UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
-               Word j;
+            while (note_ioff < shdr.sh_offset + shdr.sh_size) {
+               ElfXX_Nhdr note;
+               ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
+               DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
+               DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
 
-               if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
-                   note->n_type == NT_GNU_BUILD_ID) {
-                  buildid = ML_(dinfo_zalloc)("di.fbi.1",
-                                              note->n_descsz * 2 + 1);
-                  
-                  for (j = 0; j < note->n_descsz; j++) {
+               if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
+                   && note.n_type == NT_GNU_BUILD_ID) {
+                  buildid = ML_(dinfo_zalloc)("di.fbi.2",
+                                              note.n_descsz * 2 + 1);
+                  Word j;
+                  for (j = 0; j < note.n_descsz; j++) {
+                     UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
                      VG_(sprintf)(buildid + VG_(strlen)(buildid), 
-                                  "%02x", desc[j]);
+                                  "%02x", (UInt)desc_j);
                   }
                }
 
-               offset = offset + sizeof(ElfXX_Nhdr)
-                               + ((note->n_namesz + 3) & ~3)
-                               + ((note->n_descsz + 3) & ~3);
+               note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
+                                     + ((note.n_namesz + 3) & ~3)
+                                     + ((note.n_descsz + 3) & ~3);
             }            
          }
       }
    }
-#endif
+#  endif /* def NT_GNU_BUILD_ID */
 
    return buildid;
 }
 
-/*
- * This routine for calculating the CRC for a separate debug file
- * is GPLed code borrowed from GNU binutils.
- */
-static UInt
-calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
-{
-  static const UInt crc32_table[256] =
-    {
-      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
-      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
-      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
-      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
-      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
-      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
-      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
-      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
-      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
-      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
-      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
-      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
-      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
-      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
-      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
-      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
-      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
-      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
-      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
-      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
-      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
-      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
-      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
-      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
-      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
-      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
-      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
-      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
-      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
-      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
-      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
-      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
-      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
-      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
-      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
-      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
-      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
-      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
-      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
-      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
-      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
-      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
-      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
-      0x2d02ef8d
-    };
-  const UChar *end;
 
-  crc = ~crc & 0xffffffff;
-  for (end = buf + len; buf < end; ++ buf)
-    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
-  return ~crc & 0xffffffff;;
-}
+/* Try and open a separate debug file, ignoring any where the CRC does
+   not match the value from the main object file.  Returned DiImage
+   must be discarded by the caller.
 
-/*
- * Try and open a separate debug file, ignoring any where the CRC does
- * not match the value from the main object file.
+   If |serverAddr| is NULL, |name| is expected to be a fully qualified
+   (absolute) path to the file in the local filesystem.  If
+   |serverAddr| is non-NULL, it is expected to be an IPv4 and port
+   spec of the form "d.d.d.d:d" or "d.d.d.d", and |name| is expected
+   to be a plain filename (no path components at all).
  */
 static
-Addr open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
-                      Bool rel_ok, /*OUT*/UWord* size )
+DiImage* open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
+                          Bool rel_ok, const HChar* serverAddr )
 {
-   SysRes fd, sres;
-   struct vg_stat stat_buf;
-   UInt calccrc;
+   DiImage* dimg 
+     = serverAddr ? ML_(img_from_di_server)(name, serverAddr)
+                  : ML_(img_from_local_file)(name);
+   if (dimg == NULL)
+      return NULL;
 
-   fd = VG_(open)(name, VKI_O_RDONLY, 0);
-   if (sr_isError(fd))
-      return 0;
-
-   if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
-      VG_(close)(sr_Res(fd));
-      return 0;
+   if (VG_(clo_verbosity) > 1) {
+      if (serverAddr)
+         VG_(message)(Vg_DebugMsg, "  Considering %s on server %s ..\n",
+                                   name, serverAddr);
+      else
+         VG_(message)(Vg_DebugMsg, "  Considering %s ..\n", name);
    }
 
-   if (VG_(clo_verbosity) > 1)
-      VG_(message)(Vg_DebugMsg, "  Considering %s ..\n", name);
-   
-   *size = stat_buf.size;
-   
-   sres = VG_(am_mmap_file_float_valgrind)
-             ( *size, VKI_PROT_READ, sr_Res(fd), 0 );
-
-   VG_(close)(sr_Res(fd));
-   
-   if (sr_isError(sres))
-      return 0;
-
    if (buildid) {
-      HChar* debug_buildid = find_buildid(sr_Res(sres), *size, rel_ok, True);
+      HChar* debug_buildid = find_buildid(dimg, rel_ok, True);
       if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
-         SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
-         vg_assert(!sr_isError(res));
+         ML_(img_done)(dimg);
          if (VG_(clo_verbosity) > 1)
             VG_(message)(Vg_DebugMsg, 
                "  .. build-id mismatch (found %s wanted %s)\n", 
                debug_buildid, buildid);
          ML_(dinfo_free)(debug_buildid);
-         return 0;
+         return NULL;
       }
       ML_(dinfo_free)(debug_buildid);
-
       if (VG_(clo_verbosity) > 1)
          VG_(message)(Vg_DebugMsg, "  .. build-id is valid\n");
    } else {
-      calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size);
+      UInt calccrc = ML_(img_calc_gnu_debuglink_crc32)(dimg);
       if (calccrc != crc) {
-         SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
-         vg_assert(!sr_isError(res));
+         ML_(img_done)(dimg);
          if (VG_(clo_verbosity) > 1)
             VG_(message)(Vg_DebugMsg, 
                "  .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
-         return 0;
+         return NULL;
       }
 
       if (VG_(clo_verbosity) > 1)
          VG_(message)(Vg_DebugMsg, "  .. CRC is valid\n");
    }
    
-   return sr_Res(sres);
-}
-
-
-/* Try to find and map in a debuginfo file by some totally ad-hoc
-   scheme.  If successful, set *dimage and *n_dimage to point to the
-   image, and return True, else return False.  A temporary hack for
-   Android; does nothing on any other platform. */
-static
-Bool find_ad_hoc_debug_image( struct _DebugInfo* di, 
-                              HChar* filename,
-                              /*OUT*/Addr* dimage,
-                              /*OUT*/SizeT* n_dimage )
-{
-   vg_assert(*dimage == 0 && *n_dimage == 0);
-
-#  if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android)
-   return False; /* we don't know narfink */
-
-#  else /* android specific hacks; look away now. */
-
-   /* The deal is: if we're looking for for a debuginfo file for some
-      object /path/to/object (which can be any path), see if we can
-      find the file /sdcard/symbols/path/to/object.  So for example it
-      produces the following mappings, both of which are important for
-      Memcheck:
-
-      /system/bin/linker  --> /sdcard/symbols/system/bin/linker
-      /system/lib/libc.so --> /sdcard/symbols/system/lib/libc.so
-
-      These /symbols files come from the AOSP build tree for your
-      device, for example out/target/product/crespo/symbols/system
-      (for a Nexus S), so one simple thing you can do is take the tree
-      rooted at out/target/product/crespo/symbols/system on the host
-      and park it at /sdcard/symbols/system on the device.  Then,
-      assuming it matches what's actually running on the device,
-      you'll have full debuginfo for all the libraries on the device.
-  
-      But beware: there is no checking that the debuginfo file, if
-      found, matches the main file in any way.
-   */
-   if (!filename || *filename != '/')
-      return False;
-
-   HChar* nm = ML_(dinfo_zalloc)("di.fahdi.1", 
-                                 50 + VG_(strlen)(filename));
-   VG_(sprintf)(nm, "/sdcard/symbols%s", filename);
-
-   SysRes fd = VG_(open)(nm, VKI_O_RDONLY, 0);
-   if (sr_isError(fd)) goto fail;
-
-   struct vg_stat stat_buf;
-   if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
-      VG_(close)(sr_Res(fd));
-      goto fail;
-   }
-
-   *n_dimage = stat_buf.size;
-
-   SysRes sres = VG_(am_mmap_file_float_valgrind)
-                    ( *n_dimage, VKI_PROT_READ, sr_Res(fd), 0 );
-
-   VG_(close)(sr_Res(fd));
-   if (sr_isError(sres))
-     goto fail;
-
-   *dimage = sr_Res(sres);
-
-   if (VG_(clo_verbosity) > 1)
-      VG_(dmsg)("  Using debuginfo from %s\n", nm);
-
-   ML_(dinfo_free)(nm);
-   return True;
-
-  fail:
-   if (nm) ML_(dinfo_free)(nm);
-   return False;
-
-#  endif
+   return dimg;
 }
 
 
 /* Try to find a separate debug file for a given object file.  If
-   found, it will be mapped in and the address and size returned in
-   *dimage and *n_dimage.  If not, *dimage and *n_dimage will be
-   unchanged.  The caller should set them to zero before the call. */
+   found, return its DiImage, which should be freed by the caller.  If
+   |buildid| is non-NULL, then a debug object matching it is
+   acceptable.  If |buildid| is NULL or doesn't specify a findable
+   debug object, then we look in various places to find a file with
+   the specified CRC.  And if that doesn't work out then we give
+   up. */
 static
-void find_debug_file( struct _DebugInfo* di,
-                      const HChar* objpath, const HChar* buildid,
-                      const HChar* debugname, UInt crc, Bool rel_ok,
-                      /*OUT*/Addr*  dimage,
-                      /*OUT*/SizeT* n_dimage )
+DiImage* find_debug_file( struct _DebugInfo* di,
+                          const HChar* objpath, const HChar* buildid,
+                          const HChar* debugname, UInt crc, Bool rel_ok )
 {
-   HChar* debugpath = NULL;
-   const HChar* extrapath = VG_(clo_extra_debuginfo_path);
-   Addr  addr = 0;
-   UWord size = 0;
+   const HChar* extrapath  = VG_(clo_extra_debuginfo_path);
+   const HChar* serverpath = VG_(clo_debuginfo_server);
 
-   vg_assert(*dimage == 0 && *n_dimage == 0);
+   DiImage* dimg      = NULL; /* the img that we found */
+   HChar*   debugpath = NULL; /* where we found it */
 
    if (buildid != NULL) {
-      debugpath = ML_(dinfo_zalloc)(
-                     "di.fdf.1",
-                     VG_(strlen)(buildid) + 33);
+      debugpath = ML_(dinfo_zalloc)("di.fdf.1",
+                                    VG_(strlen)(buildid) + 33);
 
       VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
                    buildid[0], buildid[1], buildid + 2);
 
-      if ((addr = open_debug_file(debugpath, buildid, 0,
-                                  rel_ok, &size)) == 0) {
+      dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
+      if (!dimg) {
          ML_(dinfo_free)(debugpath);
          debugpath = NULL;
       }
    }
 
-   if (addr == 0 && debugname != NULL && !rel_ok) {
+   if (dimg == NULL && debugname != NULL && !rel_ok) {
       HChar *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
       HChar *objdirptr;
 
@@ -1246,53 +1197,134 @@
 
       debugpath = ML_(dinfo_zalloc)(
                      "di.fdf.3",
-                     VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32 +
-                     (extrapath ? VG_(strlen)(extrapath) : 0));
+                     VG_(strlen)(objdir) + VG_(strlen)(debugname) + 64
+                     + (extrapath ? VG_(strlen)(extrapath) : 0)
+                     + (serverpath ? VG_(strlen)(serverpath) : 0));
 
       VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
+      dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
+      if (dimg != NULL) goto dimg_ok;
 
-      if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
-         VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
-         if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
-            VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
-            addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size);
-            if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
-               if (extrapath) {
-                  VG_(sprintf)(debugpath, "%s%s/%s", extrapath,
-                              objdir, debugname);
-                  addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size);
-               }
-            }
-         }
+      VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
+      dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
+      if (dimg != NULL) goto dimg_ok;
+      
+      VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
+      dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
+      if (dimg != NULL) goto dimg_ok;
+
+      if (extrapath) {
+         VG_(sprintf)(debugpath, "%s%s/%s", extrapath,
+                                            objdir, debugname);
+         dimg = open_debug_file(debugpath, NULL, crc, rel_ok, NULL);
+         if (dimg != NULL) goto dimg_ok;
       }
 
+      if (serverpath) {
+         /* When looking on the debuginfo server, always just pass the
+            basename. */
+         const HChar* basename = debugname;
+         if (VG_(strstr)(basename, "/") != NULL) {
+            basename = VG_(strrchr)(basename, '/') + 1;
+         }
+         VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
+         dimg = open_debug_file(basename, NULL, crc, rel_ok, serverpath);
+         if (dimg) goto dimg_ok;
+      }
+
+      dimg_ok:
+
       ML_(dinfo_free)(objdir);
    }
 
-   if (addr > 0 && size > 0) {
+   if (dimg != NULL) {
+      vg_assert(debugpath);
       TRACE_SYMTAB("\n");
       TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
-      *dimage = addr;
-      *n_dimage = size;
    }
 
-   ML_(dinfo_free)(debugpath);
+   if (debugpath)
+      ML_(dinfo_free)(debugpath);
+
+   return dimg;
 }
 
 
-static Bool contained_within ( Addr outer, UWord n_outer,
-                               Addr inner, UWord n_inner )
+/* Try to find a separate debug file for a given object file, in a
+   hacky and dangerous way: check only the --extra-debuginfo-path and
+   the --debuginfo-server.  And don't do a consistency check. */
+static
+DiImage* find_debug_file_ad_hoc( struct _DebugInfo* di,
+                                 const HChar* objpath )
 {
-   if (n_outer == 0 || n_inner == 0)
-      return False;
-   /* Simplistic .. assumes no wraparound (reasonably enough) */
-   if (inner >= outer && inner+n_inner <= outer+n_outer)
-      return True;
-   return False;
+   const HChar* extrapath  = VG_(clo_extra_debuginfo_path);
+   const HChar* serverpath = VG_(clo_debuginfo_server);
+
+   DiImage* dimg      = NULL; /* the img that we found */
+   HChar*   debugpath = NULL; /* where we found it */
+
+   HChar *objdir = ML_(dinfo_strdup)("di.fdfah.1", objpath);
+   HChar *objdirptr;
+
+   if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
+      *objdirptr = '\0';
+
+   debugpath = ML_(dinfo_zalloc)(
+                  "di.fdfah.3",
+                  VG_(strlen)(objdir) + 64
+                  + (extrapath ? VG_(strlen)(extrapath) : 0)
+                  + (serverpath ? VG_(strlen)(serverpath) : 0));
+
+   if (extrapath) {
+      VG_(sprintf)(debugpath, "%s/%s", extrapath, objpath);
+      dimg = ML_(img_from_local_file)(debugpath);
+      if (dimg != NULL) {
+         if (VG_(clo_verbosity) > 1) {
+            VG_(message)(Vg_DebugMsg, "  Using (POSSIBLY MISMATCHED) %s\n",
+                                      debugpath);
+         }
+         goto dimg_ok;
+      }
+   }
+   if (serverpath) {
+      /* When looking on the debuginfo server, always just pass the
+         basename. */
+      const HChar* basename = objpath;
+      if (VG_(strstr)(basename, "/") != NULL) {
+         basename = VG_(strrchr)(basename, '/') + 1;
+      }
+      VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
+      dimg = ML_(img_from_di_server)(basename, serverpath);
+      if (dimg != NULL) {
+         if (VG_(clo_verbosity) > 1) {
+            VG_(message)(Vg_DebugMsg, "  Using (POSSIBLY MISMATCHED) %s\n",
+                                      debugpath);
+         }
+         goto dimg_ok;
+      }
+   }
+
+   dimg_ok:
+
+   ML_(dinfo_free)(objdir);
+
+   if (dimg != NULL) {
+      vg_assert(debugpath);
+      TRACE_SYMTAB("\n");
+      TRACE_SYMTAB("------ Found an ad_hoc debuginfo file: %s\n", debugpath);
+   }
+
+   if (debugpath)
+      ML_(dinfo_free)(debugpath);
+
+   return dimg;
 }
 
-static void* INDEX_BIS ( void* base, Word idx, Word scale ) {
-   return (void*)( ((UChar*)base) + idx * scale );
+
+static DiOffT INDEX_BIS ( DiOffT base, UWord idx, UWord scale ) {
+   // This is a bit stupid.  Really, idx and scale ought to be
+   // 64-bit quantities, always.
+   return base + (DiOffT)idx * (DiOffT)scale;
 }
 
 
@@ -1302,20 +1334,22 @@
 static
 Word file_offset_from_svma ( /*OUT*/Bool* ok,
                              Addr         svma,
-                             ElfXX_Phdr*  phdr_img,
+                             DiImage*     img,
+                             DiOffT       phdr_ioff,
                              Word         phdr_nent,
                              Word         phdr_ent_szB )
 {
-   Word        i;
-   ElfXX_Phdr* seg;
+   Word i;
    for (i = 0; i < phdr_nent; i++) {
-      seg = INDEX_BIS( phdr_img, i, phdr_ent_szB );
-      if (seg->p_type != PT_LOAD)
+      ElfXX_Phdr seg;
+      ML_(img_get)(&seg, img,
+                   INDEX_BIS(phdr_ioff, i, phdr_ent_szB), sizeof(seg));
+      if (seg.p_type != PT_LOAD)
          continue;
-      if (svma >= (seg->p_vaddr & -seg->p_align)
-          && svma + 1 <= seg->p_vaddr + seg->p_filesz) {
+      if (svma >= (seg.p_vaddr & -seg.p_align)
+          && svma + 1 <= seg.p_vaddr + seg.p_filesz) {
          *ok = True;
-         return svma - seg->p_vaddr + seg->p_offset;
+         return svma - seg.p_vaddr + seg.p_offset;
       }
    }
    *ok = False;
@@ -1338,40 +1372,58 @@
       follow, points executed exactly once -- that is, those which are
       the top level of the function -- are marked TOPLEVEL.
    */
-   /* TOPLEVEL */
-   Bool          res, ok;
-   SysRes        fd, sres;
-   Word          i, j;
-   Bool          dynbss_present = False;
-   Bool          sdynbss_present = False;
+   /* Consistent terminology for local variable names, without which
+      it's almost unfollowably complex:
 
-   /* Image addresses for the ELF file we're working with. */
-   Addr          oimage   = 0;
-   UWord         n_oimage = 0;
+      In which file?
+         in the main ELF file         *_m*
+         in the debuginfo file        *_d*
+         in the alt debuginfo file    *_a*
+
+      What kind of thing?
+         _{m,d,a}img       a DiImage*
+         _{m,d,a}ioff      an offset in the image (DiOffT)
+         _{m,d,a}nent      "number of entries"
+         _{m,d,a}ent_szB   "size in bytes of an entry"
+         ehdr_{m,d,a}      ELF header
+         phdr              Program header
+         shdr              Section header
+         a_X               a temporary X
+         _escn             an DiSlice (elf section info) variable
+         szB               size in bytes
+   */
+
+
+   /* TOPLEVEL */
+   Bool     res, ok;
+   Word     i, j;
+   Bool     dynbss_present = False;
+   Bool     sdynbss_present = False;
+
+   /* Image for the main ELF file we're working with. */
+   DiImage* mimg = NULL;
 
    /* Ditto for any ELF debuginfo file that we might happen to load. */
-   Addr          dimage   = 0;
-   UWord         n_dimage = 0;
+   DiImage* dimg = NULL;
 
    /* Ditto for alternate ELF debuginfo file that we might happen to load. */
-   Addr          aimage   = 0;
-   UWord         n_aimage = 0;
+   DiImage* aimg = NULL;
 
-   /* ELF header for the main file.  Should == oimage since is at
-      start of file. */
-   ElfXX_Ehdr* ehdr_img = NULL;
+   /* ELF header offset for the main file.  Should be zero since the
+      ELF header is at start of file. */
+   DiOffT   ehdr_mioff = 0;
 
    /* Program header table image addr, # entries, entry size */
-   ElfXX_Phdr* phdr_img     = NULL;
-   UWord       phdr_nent    = 0;
-   UWord       phdr_ent_szB = 0;
+   DiOffT   phdr_mioff    = 0;
+   UWord    phdr_mnent    = 0;
+   UWord    phdr_ment_szB = 0;
 
    /* Section header image addr, # entries, entry size.  Also the
       associated string table. */
-   ElfXX_Shdr* shdr_img        = NULL;
-   UWord       shdr_nent       = 0;
-   UWord       shdr_ent_szB    = 0;
-   HChar*      shdr_strtab_img = NULL;
+   DiOffT   shdr_mioff        = 0;
+   UWord    shdr_mnent        = 0;
+   UWord    shdr_ment_szB     = 0;
+   DiOffT   shdr_strtab_mioff = 0;
 
    /* SVMAs covered by rx and rw segments and corresponding biases.
       Normally each object would provide just one rx and one rw area,
@@ -1388,9 +1440,6 @@
 
    XArray* /* of RangeAndBias */ svma_ranges = NULL;
 
-   /* Build ID */
-   HChar* buildid = NULL;
-
    vg_assert(di);
    vg_assert(di->fsm.have_rx_map == True);
    vg_assert(di->fsm.have_rw_map == True);
@@ -1436,62 +1485,24 @@
 
    res = False;
 
-   oimage = (Addr)NULL;
    if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
       VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
                                 di->fsm.filename );
 
-   /* mmap the object image aboard, so that we can read symbols and
-      line number info out of it.  It will be munmapped immediately
-      thereafter; it is only aboard transiently. */
-
-   fd = VG_(open)(di->fsm.filename, VKI_O_RDONLY, 0);
-   if (sr_isError(fd)) {
-      ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!");
-      return False;
-   }
-
-   { Long n_oimageLL = VG_(fsize)(sr_Res(fd));
-     if (n_oimageLL <= 0) {
-        ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!");
-        VG_(close)(sr_Res(fd));
-        return False;
-     }
-     n_oimage = (UWord)(ULong)n_oimageLL;
-   }
-
-   sres = VG_(am_mmap_file_float_valgrind)
-             ( n_oimage, VKI_PROT_READ, sr_Res(fd), 0 );
-
-   VG_(close)(sr_Res(fd));
-
-   if (sr_isError(sres)) {
-      VG_(message)(Vg_UserMsg, "warning: mmap failed on %s\n",
+   /* Connect to the primary object image, so that we can read symbols
+      and line number info out of it.  It will be disconnected
+      immediately thereafter; it is only connected transiently. */
+   mimg = ML_(img_from_local_file)(di->fsm.filename);
+   if (mimg == NULL) {
+      VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
                                di->fsm.filename );
       VG_(message)(Vg_UserMsg, "         no symbols or debug info loaded\n" );
       return False;
    }
 
-   oimage = sr_Res(sres);
-   /* Check against wraparound.  am_mmap_file_float_valgrind should
-      not produce a wrapped-around mapping. */
-   vg_assert(n_oimage > 0);
-   vg_assert(oimage + n_oimage > oimage);
-
-   if (0) {
-      VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n", 
-                  (void*)oimage, (void*)(oimage + (UWord)n_oimage));
-   }
-
-   /* Ok, the object image is safely in oimage[0 .. n_oimage-1].  Now
-      verify that it is a valid ELF .so or executable image. */
-   res      = False;
-   ok       = (n_oimage >= sizeof(ElfXX_Ehdr));
-   ehdr_img = (ElfXX_Ehdr*)oimage;
-
-   if (ok)
-      ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage, False);
-
+   /* Ok, the object image is available.  Now verify that it is a
+      valid ELF .so or executable image. */
+   ok = is_elf_object_file_by_DiImage(mimg, False);
    if (!ok) {
       ML_(symerr)(di, True, "Invalid ELF Header");
       goto out;
@@ -1499,21 +1510,27 @@
 
    /* Find where the program and section header tables are, and give
       up if either is missing or outside the image (bogus). */
-   phdr_img     = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff );
-   phdr_nent    = ehdr_img->e_phnum;
-   phdr_ent_szB = ehdr_img->e_phentsize;
+   ElfXX_Ehdr ehdr_m;
+   vg_assert(ehdr_mioff == 0); // ensured by its initialisation
+   ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
+   vg_assert(ok); // ML_(is_elf_object_file) should ensure this
+   ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
 
-   shdr_img     = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff );
-   shdr_nent    = ehdr_img->e_shnum;
-   shdr_ent_szB = ehdr_img->e_shentsize;
+   phdr_mioff    = ehdr_mioff + ehdr_m.e_phoff;
+   phdr_mnent    = ehdr_m.e_phnum;
+   phdr_ment_szB = ehdr_m.e_phentsize;
+
+   shdr_mioff    = ehdr_mioff + ehdr_m.e_shoff;
+   shdr_mnent    = ehdr_m.e_shnum;
+   shdr_ment_szB = ehdr_m.e_shentsize;
 
    TRACE_SYMTAB("------ Basic facts about the object ------\n");
-   TRACE_SYMTAB("object:  img %p n_oimage %ld\n",
-               (void*)oimage, n_oimage);
-   TRACE_SYMTAB("phdr:    img %p nent %ld ent_szB %ld\n",
-               phdr_img, phdr_nent, phdr_ent_szB);
-   TRACE_SYMTAB("shdr:    img %p nent %ld ent_szB %ld\n",
-               shdr_img, shdr_nent, shdr_ent_szB);
+   TRACE_SYMTAB("object:  n_oimage %llu\n",
+                (ULong)ML_(img_size)(mimg));
+   TRACE_SYMTAB("phdr:    ioff %llu nent %ld ent_szB %ld\n",
+               phdr_mioff, phdr_mnent, phdr_ment_szB);
+   TRACE_SYMTAB("shdr:    ioff %llu nent %ld ent_szB %ld\n",
+               shdr_mioff, shdr_mnent, shdr_ment_szB);
    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
       struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
       if (map->rx)
@@ -1527,37 +1544,39 @@
                       map->avma, map->size, map->foff);
    }
 
-   if (phdr_nent == 0
-       || !contained_within(
-             oimage, n_oimage,
-             (Addr)phdr_img, phdr_nent * phdr_ent_szB)) {
+   if (phdr_mnent == 0
+       || !ML_(img_valid)(mimg, phdr_mioff, phdr_mnent * phdr_ment_szB)) {
       ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
       goto out;
    }
 
-   if (shdr_nent == 0
-       || !contained_within(
-             oimage, n_oimage,
-             (Addr)shdr_img, shdr_nent * shdr_ent_szB)) {
+   if (shdr_mnent == 0
+       || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
       ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
       goto out;
    }
 
    /* Also find the section header's string table, and validate. */
    /* checked previously by is_elf_object_file: */
-   vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF );
+   vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
 
-   shdr_strtab_img
-      = ((HChar*)ehdr_img)
-                  + shdr_img[ehdr_img->e_shstrndx].sh_offset;
-   if (!contained_within( oimage, n_oimage,
-                          (Addr)shdr_strtab_img,
-                          1/*bogus, but we don't know the real size*/ )) {
-      ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
-      goto out;
+   // shdr_mioff is the offset of the section header table
+   // and we need the ehdr_m.e_shstrndx'th entry
+   { ElfXX_Shdr a_shdr;
+     ML_(img_get)(&a_shdr, mimg,
+                  INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
+                  sizeof(a_shdr));
+     shdr_strtab_mioff
+        = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
+
+     if (!ML_(img_valid)(mimg, shdr_strtab_mioff, 
+                         1/*bogus, but we don't know the real size*/ )) {
+        ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
+        goto out;
+     }
    }
 
-   TRACE_SYMTAB("shdr:    string table at %p\n", shdr_strtab_img );
+   TRACE_SYMTAB("shdr:    string table at %llu\n", shdr_strtab_mioff);
 
    svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
                             ML_(dinfo_free), sizeof(RangeAndBias));
@@ -1574,52 +1593,57 @@
       /* TOPLEVEL */
       ElfXX_Addr prev_svma = 0;
 
-      for (i = 0; i < phdr_nent; i++) {
-         ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB );
+      for (i = 0; i < phdr_mnent; i++) {
+         ElfXX_Phdr a_phdr;
+         ML_(img_get)(&a_phdr, mimg,
+                      INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
+                      sizeof(a_phdr));
 
          /* Make sure the PT_LOADable entries are in order and
             non-overlapping.  This in turn means the address ranges
             slurped into svma_ranges are in order and
             non-overlapping. */
 
-         if (phdr->p_type == PT_LOAD) {
+         if (a_phdr.p_type == PT_LOAD) {
             TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
-                         i, (UWord)phdr->p_vaddr, (UWord)prev_svma);
+                         i, (UWord)a_phdr.p_vaddr, (UWord)prev_svma);
             TRACE_SYMTAB("PT_LOAD[%ld]:   p_offset %lu, p_filesz %lu,"
                          " perms %c%c%c\n",
-                         i, (UWord)phdr->p_offset, (UWord)phdr->p_filesz,
-                         phdr->p_flags & PF_R ? 'r' : '-',
-                         phdr->p_flags & PF_W ? 'w' : '-',
-                         phdr->p_flags & PF_X ? 'x' : '-');
-            if (phdr->p_vaddr < prev_svma) {
+                         i, (UWord)a_phdr.p_offset, (UWord)a_phdr.p_filesz,
+                         a_phdr.p_flags & PF_R ? 'r' : '-',
+                         a_phdr.p_flags & PF_W ? 'w' : '-',
+                         a_phdr.p_flags & PF_X ? 'x' : '-');
+            if (a_phdr.p_vaddr < prev_svma) {
                ML_(symerr)(di, True,
                            "ELF Program Headers are not in ascending order");
                goto out;
             }
-            prev_svma = phdr->p_vaddr;
-            if (phdr->p_memsz > 0) {
+            prev_svma = a_phdr.p_vaddr;
+            if (a_phdr.p_memsz > 0) {
                Bool loaded = False;
                for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
                   struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
                   if (   (map->rx || map->rw)
-                      && phdr->p_offset >= map->foff
-                      && phdr->p_offset <  map->foff + map->size
-                      && phdr->p_offset + phdr->p_filesz <= map->foff
-                                                            + map->size) {
+                      && a_phdr.p_offset >= map->foff
+                      && a_phdr.p_offset <  map->foff + map->size
+                      && a_phdr.p_offset + a_phdr.p_filesz 
+                         <= map->foff + map->size) {
                      RangeAndBias item;
-                     item.svma_base  = phdr->p_vaddr;
-                     item.svma_limit = phdr->p_vaddr + phdr->p_memsz;
+                     item.svma_base  = a_phdr.p_vaddr;
+                     item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
                      item.bias       = map->avma - map->foff
-                                       + phdr->p_offset - phdr->p_vaddr;
-                     if (   map->rw
-                         && (phdr->p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) {
+                                       + a_phdr.p_offset - a_phdr.p_vaddr;
+                     if (map->rw
+                         && (a_phdr.p_flags & (PF_R | PF_W))
+                            == (PF_R | PF_W)) {
                         item.exec = False;
                         VG_(addToXA)(svma_ranges, &item);
                         TRACE_SYMTAB("PT_LOAD[%ld]:   acquired as rw\n", i);
                         loaded = True;
                      }
-                     if (   map->rx
-                         && (phdr->p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) {
+                     if (map->rx
+                         && (a_phdr.p_flags & (PF_R | PF_X))
+                            == (PF_R | PF_X)) {
                         item.exec = True;
                         VG_(addToXA)(svma_ranges, &item);
                         TRACE_SYMTAB("PT_LOAD[%ld]:   acquired as rx\n", i);
@@ -1639,28 +1663,37 @@
             The seginfo needs to have some kind of soname in order to
             facilitate writing redirect functions, since all redirect
             specifications require a soname (pattern). */
-         if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) {
-            ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img)
-                                               + phdr->p_offset);
-            Word   stroff = -1;
-            HChar* strtab = NULL;
-            for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) {
-               switch (dyn_img[j].d_tag) {
+         if (a_phdr.p_type == PT_DYNAMIC && di->soname == NULL) {
+            Word   stroff       = -1;
+            DiOffT strtab_mioff = DiOffT_INVALID;
+            for (j = 0; True/*exit check is in the loop*/; j++) {
+               ElfXX_Dyn t_dyn_m; /* dyn_img[j] */
+               ML_(img_get)(&t_dyn_m, mimg,
+                            INDEX_BIS(ehdr_mioff + a_phdr.p_offset,
+                                      j, sizeof(ElfXX_Dyn)),
+                            sizeof(t_dyn_m));
+               if (t_dyn_m.d_tag == DT_NULL)
+                  break;
+
+               switch (t_dyn_m.d_tag) {
                   case DT_SONAME: {
-                     stroff = dyn_img[j].d_un.d_val;
+                     stroff = t_dyn_m.d_un.d_val;
                      break;
                   }
                   case DT_STRTAB: {
                      Bool ok2 = False;
                      Word offset = file_offset_from_svma(
-                                      &ok2,
-                                      dyn_img[j].d_un.d_ptr,
-                                      phdr_img,
-                                      phdr_nent, phdr_ent_szB
+                                      &ok2, t_dyn_m.d_un.d_ptr, mimg,
+                                      phdr_mioff, phdr_mnent, phdr_ment_szB
                                    );
-                     if (ok2 && strtab == NULL) {
-                        vg_assert(offset >= 0 && offset <= n_oimage);
-                        strtab = ((HChar*)ehdr_img) + offset;
+                     if (ok2 && strtab_mioff == DiOffT_INVALID) {
+                        // Check for obviously bogus offsets.
+                        if (!ML_(img_valid)(mimg, offset, 1)) {
+                           ML_(symerr)(di, True, "Invalid DT_STRTAB offset");
+                           goto out;
+                        }
+                        strtab_mioff = ehdr_mioff + offset;
+                        vg_assert(ehdr_mioff == 0); // should always be
                      }
                      break;
                   }
@@ -1668,12 +1701,13 @@
                      break;
                }
             }
-            if (stroff != -1 && strtab != NULL) {
-               TRACE_SYMTAB("Found soname = %s\n", strtab+stroff);
-               di->soname = ML_(dinfo_strdup)("di.redi.1", strtab+stroff);
+            if (stroff != -1 && strtab_mioff != DiOffT_INVALID) {
+               di->soname = ML_(img_strdup)(mimg, "di.redi.1",
+                                            strtab_mioff + stroff);
+               TRACE_SYMTAB("Found soname = %s\n", di->soname);
             }
          }
-      } /* for (i = 0; i < phdr_nent; i++) ... */
+      } /* for (i = 0; i < phdr_Mnent; i++) ... */
       /* TOPLEVEL */
 
    } /* examine the program headers (local scope) */
@@ -1721,14 +1755,17 @@
 
    /* TOPLEVEL */
    /* Iterate over section headers */
-   for (i = 0; i < shdr_nent; i++) {
-      ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB );
-      HChar* name = shdr_strtab_img + shdr->sh_name;
-      Addr   svma = shdr->sh_addr;
-      OffT   foff = shdr->sh_offset;
-      UWord  size = shdr->sh_size; /* Do not change this to be signed. */
-      UInt   alyn = shdr->sh_addralign;
-      Bool   bits = !(shdr->sh_type == SHT_NOBITS);
+   for (i = 0; i < shdr_mnent; i++) {
+      ElfXX_Shdr a_shdr;
+      ML_(img_get)(&a_shdr, mimg,
+                   INDEX_BIS(shdr_mioff, i, shdr_ment_szB), sizeof(a_shdr));
+      DiOffT name_mioff = shdr_strtab_mioff + a_shdr.sh_name;
+      HChar* name = ML_(img_strdup)(mimg, "di.redi_name.1", name_mioff);
+      Addr   svma = a_shdr.sh_addr;
+      OffT   foff = a_shdr.sh_offset;
+      UWord  size = a_shdr.sh_size; /* Do not change this to be signed. */
+      UInt   alyn = a_shdr.sh_addralign;
+      Bool   bits = !(a_shdr.sh_type == SHT_NOBITS);
       /* Look through our collection of info obtained from the PT_LOAD
          headers, and make 'inrx' and 'inrw' point to the first entry
          in each that intersects 'avma'.  If in each case none is found,
@@ -1749,13 +1786,14 @@
       }
 
       TRACE_SYMTAB(" [sec %2ld]  %s %s  al%2u  foff %6ld .. %6ld  "
-                  "  svma %p  name \"%s\"\n", 
-                  i, inrx ? "rx" : "  ", inrw ? "rw" : "  ", alyn,
-                  foff, foff+size-1, (void*)svma, name );
+                   "  svma %p  name \"%s\"\n", 
+                   i, inrx ? "rx" : "  ", inrw ? "rw" : "  ", alyn,
+                   foff, foff+size-1, (void*)svma, name);
 
       /* Check for sane-sized segments.  SHT_NOBITS sections have zero
          size in the file. */
-      if ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage)) {
+      if ((foff >= ML_(img_size)(mimg)) 
+          || (foff + (bits ? size : 0) > ML_(img_size)(mimg))) {
          ML_(symerr)(di, True, "ELF Section extends beyond image end");
          goto out;
       }
@@ -1770,6 +1808,7 @@
       /* Ignore zero sized sections. */
       if (size == 0) {
          TRACE_SYMTAB("zero sized section \"%s\", ignoring\n", name);
+         ML_(dinfo_free)(name);
          continue;
       }
 
@@ -2125,7 +2164,9 @@
          }
       }
 
-#    undef BAD
+      ML_(dinfo_free)(name);
+
+#     undef BAD
 
    } /* iterate over the section headers */
 
@@ -2143,73 +2184,49 @@
                 "for debug-info sections ------\n");
 
    /* TOPLEVEL */
-   /* Find interesting sections, read the symbol table(s), read any debug
-      information */
+   /* Find interesting sections, read the symbol table(s), read any
+      debug information.  Each section is located either in the main,
+      debug or alt-debug files, but only in one.  For each section,
+      |section_escn| records which of |mimg|, |dimg| or |aimg| we
+      found it in, along with the section's image offset and its size.
+      The triples (section_img, section_ioff, section_szB) are
+      consistent, in that they are always either (NULL,
+      DiOffT_INVALID, 0), or refer to the same image, and are all
+      assigned together. */
    {
-      /* IMAGE addresses: pointers to start of sections in the
-         transiently loaded oimage, not in the fragments of the file
-         mapped in by the guest's dynamic linker. */
       /* TOPLEVEL */
-      HChar*     strtab_img       = NULL; /* .strtab */
-      ElfXX_Sym* symtab_img       = NULL; /* .symtab */
-      HChar*     dynstr_img       = NULL; /* .dynstr */
-      ElfXX_Sym* dynsym_img       = NULL; /* .dynsym */
-      HChar*     debuglink_img    = NULL; /* .gnu_debuglink */
-      UChar*     debugaltlink_img = NULL; /* .gnu_debugaltlink */
-      UChar*     stab_img         = NULL; /* .stab         (stabs)  */
-      HChar*     stabstr_img      = NULL; /* .stabstr      (stabs)  */
-      UChar*     debug_line_img   = NULL; /* .debug_line   (dwarf2) */
-      UChar*     debug_info_img   = NULL; /* .debug_info   (dwarf2) */
-      UChar*     debug_types_img  = NULL; /* .debug_types  (dwarf4) */
-      UChar*     debug_abbv_img   = NULL; /* .debug_abbrev (dwarf2) */
-      HChar*     debug_str_img    = NULL; /* .debug_str    (dwarf2) */
-      UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
-      UChar*     debug_loc_img    = NULL; /* .debug_loc    (dwarf2) */
-      UChar*     debug_frame_img  = NULL; /* .debug_frame  (dwarf2) */
-      UChar*     debug_line_alt_img = NULL; /* .debug_line (alternate) */
-      UChar*     debug_info_alt_img = NULL; /* .debug_info (alternate) */
-      UChar*     debug_abbv_alt_img = NULL; /* .debug_abbrev (alternate) */
-      HChar*     debug_str_alt_img = NULL; /* .debug_str   (alternate) */
-      UChar*     dwarf1d_img      = NULL; /* .debug        (dwarf1) */
-      UChar*     dwarf1l_img      = NULL; /* .line         (dwarf1) */
-      UChar*     opd_img          = NULL; /* .opd (dwarf2,
-                                                   ppc64-linux) */
-      UChar*     ehframe_img[N_EHFRAME_SECTS]; /* .eh_frame (dwarf2) */
+      DiSlice strtab_escn         = DiSlice_INVALID; // .strtab
+      DiSlice symtab_escn         = DiSlice_INVALID; // .symtab
+      DiSlice dynstr_escn         = DiSlice_INVALID; // .dynstr
+      DiSlice dynsym_escn         = DiSlice_INVALID; // .dynsym
+      DiSlice debuglink_escn      = DiSlice_INVALID; // .gnu_debuglink
+      DiSlice debugaltlink_escn   = DiSlice_INVALID; // .gnu_debugaltlink
+      DiSlice stab_escn           = DiSlice_INVALID; // .stab         (stabs) 
+      DiSlice stabstr_escn        = DiSlice_INVALID; // .stabstr      (stabs) 
+      DiSlice debug_line_escn     = DiSlice_INVALID; // .debug_line   (dwarf2)
+      DiSlice debug_info_escn     = DiSlice_INVALID; // .debug_info   (dwarf2)
+      DiSlice debug_types_escn    = DiSlice_INVALID; // .debug_types  (dwarf4)
+      DiSlice debug_abbv_escn     = DiSlice_INVALID; // .debug_abbrev (dwarf2)
+      DiSlice debug_str_escn      = DiSlice_INVALID; // .debug_str    (dwarf2)
+      DiSlice debug_ranges_escn   = DiSlice_INVALID; // .debug_ranges (dwarf2)
+      DiSlice debug_loc_escn      = DiSlice_INVALID; // .debug_loc    (dwarf2)
+      DiSlice debug_frame_escn    = DiSlice_INVALID; // .debug_frame  (dwarf2)
+      DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line   (alt)
+      DiSlice debug_info_alt_escn = DiSlice_INVALID; // .debug_info   (alt)
+      DiSlice debug_abbv_alt_escn = DiSlice_INVALID; // .debug_abbrev (alt)
+      DiSlice debug_str_alt_escn  = DiSlice_INVALID; // .debug_str    (alt)
+      DiSlice dwarf1d_escn        = DiSlice_INVALID; // .debug        (dwarf1)
+      DiSlice dwarf1l_escn        = DiSlice_INVALID; // .line         (dwarf1)
+      DiSlice opd_escn            = DiSlice_INVALID; // .opd (dwarf2, 
+                                                     //       ppc64-linux)
+      DiSlice ehframe_escn[N_EHFRAME_SECTS];         // .eh_frame (dwarf2)
 
-      /* Section sizes, in bytes */
-      SizeT      strtab_sz       = 0;
-      SizeT      symtab_sz       = 0;
-      SizeT      dynstr_sz       = 0;
-      SizeT      dynsym_sz       = 0;
-      SizeT      debuglink_sz    = 0;
-      SizeT      debugaltlink_sz = 0;
-      SizeT      stab_sz         = 0;
-      SizeT      stabstr_sz      = 0;
-      SizeT      debug_line_sz   = 0;
-      SizeT      debug_info_sz   = 0;
-      SizeT      debug_types_sz  = 0;
-      SizeT      debug_abbv_sz   = 0;
-      SizeT      debug_str_sz    = 0;
-      SizeT      debug_ranges_sz = 0;
-      SizeT      debug_loc_sz    = 0;
-      SizeT      debug_frame_sz  = 0;
-      SizeT      debug_line_alt_sz = 0;
-      SizeT      debug_info_alt_sz = 0;
-      SizeT      debug_abbv_alt_sz = 0;
-      SizeT      debug_str_alt_sz = 0;
-      SizeT      dwarf1d_sz      = 0;
-      SizeT      dwarf1l_sz      = 0;
-      SizeT      opd_sz_unused   = 0;
-      SizeT      ehframe_sz[N_EHFRAME_SECTS];
-
-      for (i = 0; i < N_EHFRAME_SECTS; i++) {
-         ehframe_img[i] = NULL;
-         ehframe_sz[i]  = 0;
-      }
+      for (i = 0; i < N_EHFRAME_SECTS; i++)
+         ehframe_escn[i] = DiSlice_INVALID;
 
       /* Find all interesting sections */
 
-      UInt ehframe_ix = 0;
+      UInt ehframe_mix = 0;
 
       /* What FIND does: it finds the section called _SEC_NAME.  The
          size of it is assigned to _SEC_SIZE.  The address of the
@@ -2225,23 +2242,29 @@
 
       /* TOPLEVEL */
       /* Iterate over section headers (again) */
-      for (i = 0; i < ehdr_img->e_shnum; i++) {
+      for (i = 0; i < ehdr_m.e_shnum; i++) {
 
-#        define FINDX(_sec_name, _sec_size, _sec_img, _post_fx)     \
-         do { ElfXX_Shdr* shdr \
-                 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \
-           if (0 == VG_(strcmp)(_sec_name, (HChar *)(shdr_strtab_img    \
-                                                     + shdr->sh_name))) { \
+#        define FINDX(_sec_name, _sec_escn, _post_fx) \
+         do { \
+            ElfXX_Shdr a_shdr; \
+            ML_(img_get)(&a_shdr, mimg, \
+                         INDEX_BIS(shdr_mioff, i, shdr_ment_szB), \
+                         sizeof(a_shdr)); \
+            if (0 == ML_(img_strcmp_c)(mimg, shdr_strtab_mioff \
+                                              + a_shdr.sh_name, _sec_name)) { \
                Bool nobits; \
-               _sec_img  = (void*)(oimage + shdr->sh_offset); \
-               _sec_size = shdr->sh_size; \
-               nobits    = shdr->sh_type == SHT_NOBITS; \
-               TRACE_SYMTAB( "%18s:  img %p .. %p\n", \
-                             _sec_name, (UChar*)_sec_img, \
-                             ((UChar*)_sec_img) + _sec_size - 1); \
+               _sec_escn.img  = mimg; \
+               _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
+               _sec_escn.szB  = a_shdr.sh_size; \
+               nobits         = a_shdr.sh_type == SHT_NOBITS; \
+               vg_assert(_sec_escn.img  != NULL); \
+               vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
+               TRACE_SYMTAB( "%18s:  ioff %llu .. %llu\n", \
+                             _sec_name, (ULong)_sec_escn.ioff, \
+                             ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
                /* SHT_NOBITS sections have zero size in the file. */ \
-               if ( shdr->sh_offset \
-                    + (nobits ? 0 : _sec_size) > n_oimage ) { \
+               if ( a_shdr.sh_offset \
+                    + (nobits ? 0 : _sec_escn.szB) > ML_(img_size)(mimg) ) { \
                   ML_(symerr)(di, True, \
                               "   section beyond image end?!"); \
                   goto out; \
@@ -2251,50 +2274,48 @@
          } while (0);
 
          /* Version with no post-effects */
-#        define FIND(_sec_name, _sec_size, _sec_img) \
-            FINDX(_sec_name, _sec_size, _sec_img, /**/)
+#        define FIND(_sec_name, _sec_escn) \
+            FINDX(_sec_name, _sec_escn, /**/)
 
-         /*   NAME              SIZE             IMAGE addr */
-         FIND(".dynsym",        dynsym_sz,       dynsym_img)
-         FIND(".dynstr",        dynstr_sz,       dynstr_img)
-         FIND(".symtab",        symtab_sz,       symtab_img)
-         FIND(".strtab",        strtab_sz,       strtab_img)
+         /*   NAME                  ElfSec */
+         FIND(".dynsym",            dynsym_escn)
+         FIND(".dynstr",            dynstr_escn)
+         FIND(".symtab",            symtab_escn)
+         FIND(".strtab",            strtab_escn)
 
-         FIND(".gnu_debuglink", debuglink_sz,    debuglink_img)
-         FIND(".gnu_debugaltlink", debugaltlink_sz, debugaltlink_img)
+         FIND(".gnu_debuglink",     debuglink_escn)
+         FIND(".gnu_debugaltlink",  debugaltlink_escn)
 
-         FIND(".stab",          stab_sz,         stab_img)
-         FIND(".stabstr",       stabstr_sz,      stabstr_img)
+         FIND(".stab",              stab_escn)
+         FIND(".stabstr",           stabstr_escn)
 
-         FIND(".debug_line",    debug_line_sz,   debug_line_img)
-         FIND(".debug_info",    debug_info_sz,   debug_info_img)
-         FIND(".debug_types",   debug_types_sz,  debug_types_img)
-         FIND(".debug_abbrev",  debug_abbv_sz,   debug_abbv_img)
-         FIND(".debug_str",     debug_str_sz,    debug_str_img)
-         FIND(".debug_ranges",  debug_ranges_sz, debug_ranges_img)
-         FIND(".debug_loc",     debug_loc_sz,    debug_loc_img)
-         FIND(".debug_frame",   debug_frame_sz,  debug_frame_img)
+         FIND(".debug_line",        debug_line_escn)
+         FIND(".debug_info",        debug_info_escn)
+         FIND(".debug_types",       debug_types_escn)
+         FIND(".debug_abbrev",      debug_abbv_escn)
+         FIND(".debug_str",         debug_str_escn)
+         FIND(".debug_ranges",      debug_ranges_escn)
+         FIND(".debug_loc",         debug_loc_escn)
+         FIND(".debug_frame",       debug_frame_escn)
 
-         FIND(".debug",         dwarf1d_sz,      dwarf1d_img)
-         FIND(".line",          dwarf1l_sz,      dwarf1l_img)
+         FIND(".debug",             dwarf1d_escn)
+         FIND(".line",              dwarf1l_escn)
 
-         FIND(".opd",           opd_sz_unused,   opd_img)
+         FIND(".opd",               opd_escn)
 
-         FINDX(".eh_frame",     ehframe_sz[ehframe_ix],
-                                                 ehframe_img[ehframe_ix], 
-               do { ehframe_ix++; vg_assert(ehframe_ix <= N_EHFRAME_SECTS); }
-                    while (0)
+         FINDX(".eh_frame",         ehframe_escn[ehframe_mix],
+               do { ehframe_mix++; vg_assert(ehframe_mix <= N_EHFRAME_SECTS);
+               } while (0)
          )
          /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
             multi-instance kludgery, how are we assured that the order
-            in which we fill in ehframe_sz[] and ehframe_img[] is
-            consistent with the order in which we previously filled in
-            di->ehframe_avma[] and di->ehframe_size[] ?  By the fact
-            that in both cases, these arrays were filled in by
-            iterating over the section headers top-to-bottom.  So both
-            loops (this one and the previous one) encounter the
-            .eh_frame entries in the same order and so fill in these
-            arrays in a consistent order.
+            in which we fill in ehframe_escn[] is consistent with the
+            order in which we previously filled in di->ehframe_avma[]
+            and di->ehframe_size[] ?  By the fact that in both cases,
+            these arrays were filled in by iterating over the section
+            headers top-to-bottom.  So both loops (this one and the
+            previous one) encounter the .eh_frame entries in the same
+            order and so fill in these arrays in a consistent order.
          */
 
 #        undef FINDX
@@ -2302,32 +2323,43 @@
       } /* Iterate over section headers (again) */
 
       /* TOPLEVEL */
-      /* Now, see if we can find a debuginfo object, and if so map it in, and
-         put the mapping address and size in dimage and n_dimage. */
-      vg_assert(dimage == 0 && n_dimage == 0);
+      /* Now, see if we can find a debuginfo object, and if so connect
+         |dimg| to it. */
+      vg_assert(dimg == NULL && aimg == NULL);
 
       /* Look for a build-id */
-      buildid = find_buildid(oimage, n_oimage, False, False);
+      HChar* buildid = find_buildid(mimg, False, False);
 
-      /* Look for a debug image */
-      if (buildid != NULL || debuglink_img != NULL) {
+      /* Look for a debug image that matches either the build-id or
+         the debuglink-CRC32 in the main image.  If the main image
+         doesn't contain either of those then this won't even bother
+         to try looking.  This looks in all known places, including
+         the --extra-debuginfo-path if specified and on the
+         --debuginfo-server if specified. */
+      if (buildid != NULL || debuglink_escn.img != NULL) {
          /* Do have a debuglink section? */
-         if (debuglink_img != NULL) {
-            UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
-            UInt crc;
-
-            vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
+         if (debuglink_escn.img != NULL) {
+            UInt crc_offset 
+               = VG_ROUNDUP(ML_(img_strlen)(debuglink_escn.img,
+                                            debuglink_escn.ioff)+1, 4);
+            vg_assert(crc_offset + sizeof(UInt) <= debuglink_escn.szB);
 
             /* Extract the CRC from the debuglink section */
-            crc = ML_(read_UInt)((UChar *)debuglink_img + crc_offset);
+            UInt crc = ML_(img_get_UInt)(debuglink_escn.img,
+                                         debuglink_escn.ioff + crc_offset);
 
             /* See if we can find a matching debug file */
-            find_debug_file( di, di->fsm.filename, buildid,
-                             debuglink_img, crc, False, &dimage, &n_dimage );
+            HChar* debuglink_str_m
+               = ML_(img_strdup)(debuglink_escn.img,
+                                 "di.redi_dlk.1", debuglink_escn.ioff);
+            dimg = find_debug_file( di, di->fsm.filename, buildid,
+                                    debuglink_str_m, crc, False );
+            if (debuglink_str_m)
+               ML_(dinfo_free)(debuglink_str_m);
          } else {
             /* See if we can find a matching debug file */
-            find_debug_file( di, di->fsm.filename, buildid,
-                             NULL, 0, False, &dimage, &n_dimage );
+            dimg = find_debug_file( di, di->fsm.filename, buildid,
+                                    NULL, 0, False );
          }
       }
 
@@ -2336,33 +2368,42 @@
          buildid = NULL; /* paranoia */
       }
 
-      /* Still no luck?  Let's have one last roll of the dice. */
-      if (dimage == 0) {
-         vg_assert(n_dimage == 0);
-         Bool found = find_ad_hoc_debug_image( di, di->fsm.filename,
-                                               &dimage, &n_dimage );
-         if (found)
-            vg_assert(dimage != 0);
+      /* As a last-ditch measure, try looking for in the
+         --extra-debuginfo-path and/or on the --debuginfo-server, but
+         only in the case where --allow-mismatched-debuginfo=yes.
+         This is dangerous in that (1) it gives no assurance that the
+         debuginfo object matches the main one, and hence (2) we will
+         very likely get an assertion in the code below, if indeed
+         there is a mismatch.  Hence it is disabled by default
+         (--allow-mismatched-debuginfo=no).  Nevertheless it's
+         sometimes a useful way of getting out of a tight spot.
+
+         Note that we're ignoring the name in the .gnu_debuglink
+         section here, and just looking for a file of the same name
+         either the extra-path or on the server. */
+      if (dimg == NULL && VG_(clo_allow_mismatched_debuginfo)) {
+         dimg = find_debug_file_ad_hoc( di, di->fsm.filename );
       }
 
       /* TOPLEVEL */
       /* If we were successful in finding a debug image, pull various
          SVMA/bias/size and image addresses out of it. */
-      if (dimage != 0 
-          && n_dimage >= sizeof(ElfXX_Ehdr)
-          && ML_(is_elf_object_file)((void*)dimage, n_dimage, False)) {
+      if (dimg != NULL && is_elf_object_file_by_DiImage(dimg, False)) {
 
          /* Pull out and validate program header and section header info */
-         ElfXX_Ehdr* ehdr_dimg     = (ElfXX_Ehdr*)dimage;
-         ElfXX_Phdr* phdr_dimg     = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg)
-                                                       + ehdr_dimg->e_phoff );
-         UWord       phdr_dnent    = ehdr_dimg->e_phnum;
-         UWord       phdr_dent_szB = ehdr_dimg->e_phentsize;
-         ElfXX_Shdr* shdr_dimg     = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg)
-                                                       + ehdr_dimg->e_shoff );
-         UWord       shdr_dnent       = ehdr_dimg->e_shnum;
-         UWord       shdr_dent_szB    = ehdr_dimg->e_shentsize;
-         UChar*      shdr_strtab_dimg = NULL;
+         DiOffT      ehdr_dioff = 0;
+         ElfXX_Ehdr  ehdr_dimg;
+         ML_(img_get)(&ehdr_dimg, dimg, ehdr_dioff, sizeof(ehdr_dimg));
+
+         DiOffT   phdr_dioff        = ehdr_dimg.e_phoff;
+         UWord    phdr_dnent        = ehdr_dimg.e_phnum;
+         UWord    phdr_dent_szB     = ehdr_dimg.e_phentsize;
+
+         DiOffT   shdr_dioff        = ehdr_dimg.e_shoff;
+         UWord    shdr_dnent        = ehdr_dimg.e_shnum;
+         UWord    shdr_dent_szB     = ehdr_dimg.e_shentsize;
+
+         DiOffT   shdr_strtab_dioff = DiOffT_INVALID;
 
          /* SVMAs covered by rx and rw segments and corresponding bias. */
          Addr     rx_dsvma_limit = 0;
@@ -2373,9 +2414,8 @@
          Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
 
          if (phdr_dnent == 0
-             || !contained_within(
-                    dimage, n_dimage,
-                    (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) {
+             || !ML_(img_valid)(dimg, phdr_dioff,
+                                phdr_dnent * phdr_dent_szB)) {
             ML_(symerr)(di, True,
                         "Missing or invalid ELF Program Header Table"
                         " (debuginfo file)");
@@ -2383,9 +2423,8 @@
          }
 
          if (shdr_dnent == 0
-             || !contained_within(
-                    dimage, n_dimage,
-                    (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) {
+             || !ML_(img_valid)(dimg, shdr_dioff,
+                                shdr_dnent * shdr_dent_szB)) {
             ML_(symerr)(di, True,
                         "Missing or invalid ELF Section Header Table"
                         " (debuginfo file)");
@@ -2394,46 +2433,46 @@
 
          /* Also find the section header's string table, and validate. */
          /* checked previously by is_elf_object_file: */
-         vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF );
+         vg_assert(ehdr_dimg.e_shstrndx != SHN_UNDEF);
 
-         shdr_strtab_dimg
-            = (UChar*)( ((UChar*)ehdr_dimg)
-                        + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset);
-         if (!contained_within( 
-                 dimage, n_dimage,
-                 (Addr)shdr_strtab_dimg,
-                 1/*bogus, but we don't know the real size*/ )) {
-            ML_(symerr)(di, True, 
-                        "Invalid ELF Section Header String Table"
-                        " (debuginfo file)");
-            goto out;
+         // shdr_dioff is the offset of the section header table
+         // and we need the ehdr_dimg.e_shstrndx'th entry
+         { ElfXX_Shdr a_shdr;
+           ML_(img_get)(&a_shdr, dimg,
+                        INDEX_BIS(shdr_dioff, ehdr_dimg.e_shstrndx,
+                                              shdr_dent_szB),
+                        sizeof(a_shdr));
+           shdr_strtab_dioff = a_shdr.sh_offset;
+           if (!ML_(img_valid)(dimg, shdr_strtab_dioff,
+                               1/*bogus, but we don't know the real size*/)) {
+              ML_(symerr)(di, True, 
+                          "Invalid ELF Section Header String Table"
+                          " (debuginfo file)");
+              goto out;
+           }
          }
 
-         need_symtab = (NULL == symtab_img);
-         need_stabs  = (NULL == stab_img);
-         need_dwarf2 = (NULL == debug_info_img);
-         need_dwarf1 = (NULL == dwarf1d_img);
-
-         for (i = 0; i < ehdr_dimg->e_phnum; i++) {
-            ElfXX_Phdr* phdr 
-               = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff), 
-                                       i, phdr_ent_szB );
-            if (phdr->p_type == PT_LOAD) {
+         for (i = 0; i < ehdr_dimg.e_phnum; i++) {
+            ElfXX_Phdr a_phdr;
+            ML_(img_get)(&a_phdr, dimg, INDEX_BIS(ehdr_dimg.e_phoff,
+                                                  i, phdr_dent_szB), 
+                           sizeof(a_phdr));
+            if (a_phdr.p_type == PT_LOAD) {
                for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
                   struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
-                  if (   phdr->p_offset >= map->foff
-                      && phdr->p_offset <  map->foff + map->size
-                      && phdr->p_offset + phdr->p_filesz < map->foff
-                                                           + map->size) {
+                  if (   a_phdr.p_offset >= map->foff
+                      && a_phdr.p_offset <  map->foff + map->size
+                      && a_phdr.p_offset + a_phdr.p_filesz
+                         < map->foff + map->size) {
                      if (map->rx && rx_dsvma_limit == 0) {
-                        rx_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
-                        rx_dbias = map->avma - map->foff + phdr->p_offset
-                                   - phdr->p_vaddr;
+                        rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
+                        rx_dbias = map->avma - map->foff + a_phdr.p_offset
+                                   - a_phdr.p_vaddr;
                      }
                      if (map->rw && rw_dsvma_limit == 0) {
-                        rw_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
-                        rw_dbias = map->avma - map->foff + phdr->p_offset
-                                   - phdr->p_vaddr;
+                        rw_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
+                        rw_dbias = map->avma - map->foff + a_phdr.p_offset
+                                   - a_phdr.p_vaddr;
                      }
                      break;
                   }
@@ -2441,35 +2480,45 @@
             }
          }
 
-         /* Find all interesting sections */
-         for (i = 0; i < ehdr_dimg->e_shnum; i++) {
+         need_symtab = (symtab_escn.img == NULL);
+         need_stabs  = (stab_escn.img == NULL);
+         need_dwarf2 = (debug_info_escn.img == NULL);
+         need_dwarf1 = (dwarf1d_escn.img == NULL);
+
+         /* Find all interesting sections in the debug image */
+         for (i = 0; i < ehdr_dimg.e_shnum; i++) {
 
             /* Find debug svma and bias information for sections
                we found in the main file. */ 
 
-#           define FIND(sec, seg) \
-            do { ElfXX_Shdr* shdr \
-                    = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
-               if (di->sec##_present \
-                   && 0 == VG_(strcmp)("." #sec, \
-                                       (HChar *)(shdr_strtab_dimg + shdr->sh_name))) { \
-                  vg_assert(di->sec##_size == shdr->sh_size); \
-                  vg_assert(di->sec##_avma +  shdr->sh_addr + seg##_dbias); \
+#           define FIND(_sec, _seg) \
+            do { \
+               ElfXX_Shdr a_shdr; \
+               ML_(img_get)(&a_shdr, dimg, \
+                            INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
+                            sizeof(a_shdr)); \
+               if (di->_sec##_present \
+                   && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
+                                             + a_shdr.sh_name, "." #_sec)) { \
+                  vg_assert(di->_sec##_size == a_shdr.sh_size); \
+                  /* JRS 2013-Jun-01: the following assert doesn't contain */ \
+                  /* any ==s, which seems to me to be suspicious. */ \
+                  vg_assert(di->_sec##_avma +  a_shdr.sh_addr + _seg##_dbias); \
                   /* Assume we have a correct value for the main */ \
                   /* object's bias.  Use that to derive the debuginfo */ \
                   /* object's bias, by adding the difference in SVMAs */ \
                   /* for the corresponding sections in the two files. */ \
                   /* That should take care of all prelinking effects. */ \
-                  di->sec##_debug_svma = shdr->sh_addr; \
-                  di->sec##_debug_bias \
-                     = di->sec##_bias + \
-                       di->sec##_svma - di->sec##_debug_svma; \
-                  TRACE_SYMTAB("acquiring ." #sec \
+                  di->_sec##_debug_svma = a_shdr.sh_addr; \
+                  di->_sec##_debug_bias \
+                     = di->_sec##_bias + \
+                       di->_sec##_svma - di->_sec##_debug_svma; \
+                  TRACE_SYMTAB("acquiring ." #_sec \
                                " debug svma = %#lx .. %#lx\n",       \
-                               di->sec##_debug_svma, \
-                               di->sec##_debug_svma + di->sec##_size - 1); \
-                  TRACE_SYMTAB("acquiring ." #sec " debug bias = %#lx\n", \
-                               di->sec##_debug_bias); \
+                               di->_sec##_debug_svma, \
+                               di->_sec##_debug_svma + di->_sec##_size - 1); \
+                  TRACE_SYMTAB("acquiring ." #_sec " debug bias = %#lx\n", \
+                               di->_sec##_debug_bias); \
                } \
             } while (0);
 
@@ -2484,28 +2533,37 @@
 #           undef FIND
 
             /* Same deal as previous FIND, except only do it for those
-               sections for which we didn't find anything useful in
-               the main file. */
+               sections which we didn't find in the main file. */
 
-#           define FIND(condition, sec_name, sec_size, sec_img) \
-            do { ElfXX_Shdr* shdr \
-                    = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
-               if (condition \
-                   && 0 == VG_(strcmp)(sec_name, \
-                                       (HChar *)(shdr_strtab_dimg + shdr->sh_name))) { \
+#           define FIND(_condition, _sec_name, _sec_escn) \
+            do { \
+               ElfXX_Shdr a_shdr; \
+               ML_(img_get)(&a_shdr, dimg, \
+                            INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
+                            sizeof(a_shdr)); \
+               if (_condition \
+                   && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
+                                             + a_shdr.sh_name, _sec_name)) { \
                   Bool nobits; \
-                  if (0 != sec_img) \
-                     VG_(core_panic)("repeated section!\n"); \
-                  sec_img  = (void*)(dimage + shdr->sh_offset); \
-                  sec_size = shdr->sh_size; \
-                  nobits   = shdr->sh_type == SHT_NOBITS; \
-                  TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \
-                                sec_name, \
-                                (UChar*)sec_img, \
-                                ((UChar*)sec_img) + sec_size - 1); \
+                  if (_sec_escn.img != NULL) { \
+                     ML_(symerr)(di, True, \
+                                 "   debuginfo section duplicates a" \
+                                 " section in the main ELF file"); \
+                     goto out; \
+                  } \
+                  _sec_escn.img  = dimg; \
+                  _sec_escn.ioff = (DiOffT)a_shdr.sh_offset;  \
+                  _sec_escn.szB  = a_shdr.sh_size; \
+                  nobits         = a_shdr.sh_type == SHT_NOBITS; \
+                  vg_assert(_sec_escn.img  != NULL); \
+                  vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
+                  TRACE_SYMTAB( "%18s: dioff %llu .. %llu\n", \
+                                _sec_name, \
+                                (ULong)_sec_escn.ioff, \
+                                ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
                   /* SHT_NOBITS sections have zero size in the file. */ \
-                  if ( shdr->sh_offset \
-                       + (nobits ? 0 : sec_size) > n_dimage ) { \
+                  if (a_shdr.sh_offset \
+                      + (nobits ? 0 : _sec_escn.szB) > ML_(img_size)(dimg)) { \
                      ML_(symerr)(di, True, \
                                  "   section beyond image end?!"); \
                      goto out; \
@@ -2513,49 +2571,56 @@
                } \
             } while (0);
 
-            /* NEEDED?        NAME             SIZE           IMAGE addr */
-            FIND(need_symtab, ".symtab",       symtab_sz,     symtab_img)
-            FIND(need_symtab, ".strtab",       strtab_sz,     strtab_img)
-            FIND(need_stabs,  ".stab",         stab_sz,       stab_img)
-            FIND(need_stabs,  ".stabstr",      stabstr_sz,    stabstr_img)
-            FIND(need_dwarf2, ".debug_line",   debug_line_sz, debug_line_img)
-            FIND(need_dwarf2, ".debug_info",   debug_info_sz, debug_info_img)
-            FIND(need_dwarf2, ".debug_types",  debug_types_sz,
-		                                            debug_types_img)
-            FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
-            FIND(need_dwarf2, ".debug_str",    debug_str_sz,  debug_str_img)
-            FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz, 
-                                                            debug_ranges_img)
-            FIND(need_dwarf2, ".debug_loc",    debug_loc_sz,  debug_loc_img)
-            FIND(need_dwarf2, ".debug_frame",  debug_frame_sz,
-                                                            debug_frame_img)
-            FIND(need_dwarf2, ".gnu_debugaltlink", debugaltlink_sz,
-                                                            debugaltlink_img)
-            FIND(need_dwarf1, ".debug",        dwarf1d_sz,    dwarf1d_img)
-            FIND(need_dwarf1, ".line",         dwarf1l_sz,    dwarf1l_img)
+            /* NEEDED?        NAME             ElfSec */
+            FIND(need_symtab, ".symtab",       symtab_escn)
+            FIND(need_symtab, ".strtab",       strtab_escn)
+            FIND(need_stabs,  ".stab",         stab_escn)
+            FIND(need_stabs,  ".stabstr",      stabstr_escn)
+            FIND(need_dwarf2, ".debug_line",   debug_line_escn)
+            FIND(need_dwarf2, ".debug_info",   debug_info_escn)
+            FIND(need_dwarf2, ".debug_types",  debug_types_escn)
+
+            FIND(need_dwarf2, ".debug_abbrev", debug_abbv_escn)
+            FIND(need_dwarf2, ".debug_str",    debug_str_escn)
+            FIND(need_dwarf2, ".debug_ranges", debug_ranges_escn)
+
+            FIND(need_dwarf2, ".debug_loc",    debug_loc_escn)
+            FIND(need_dwarf2, ".debug_frame",  debug_frame_escn)
+
+            FIND(need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn)
+
+            FIND(need_dwarf1, ".debug",        dwarf1d_escn)
+            FIND(need_dwarf1, ".line",         dwarf1l_escn)
 
 #           undef FIND
          } /* Find all interesting sections */
       } /* do we have a debug image? */
 
-      /* Look for alternate debug image */
-      if (debugaltlink_img != NULL) {
-         UInt buildid_offset = VG_(strlen)((HChar *)debugaltlink_img)+1;
+      /* TOPLEVEL */
+      /* Look for alternate debug image, and if found, connect |aimg|
+         to it. */
+      vg_assert(aimg == NULL);
 
-         vg_assert(buildid_offset < debugaltlink_sz);
+      if (debugaltlink_escn.img != NULL) {
+         UInt buildid_offset = ML_(img_strlen)(debugaltlink_escn.img, 0)+1;
+
+         vg_assert(buildid_offset < debugaltlink_escn.szB);
 
          HChar *altbuildid
             = ML_(dinfo_zalloc)("di.fbi.4",
-                                (debugaltlink_sz - buildid_offset)
+                                (debugaltlink_escn.szB - buildid_offset)
                                 * 2 + 1);
 
-         for (j = 0; j < debugaltlink_sz - buildid_offset; j++)
-            VG_(sprintf)(altbuildid + 2 * j, 
-                         "%02x", debugaltlink_img[buildid_offset + j]);
+         for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
+            VG_(sprintf)(
+               altbuildid + 2 * j, "%02x",
+               (UInt)ML_(img_get_UChar)(debugaltlink_escn.img,
+                                        debugaltlink_escn.ioff 
+                                        + buildid_offset + j));
 
          /* See if we can find a matching debug file */
-         find_debug_file( di, di->fsm.filename, altbuildid,
-                          NULL, 0, True, &aimage, &n_aimage );
+         aimg = find_debug_file( di, di->fsm.filename, altbuildid,
+                                 NULL, 0, True );
 
          ML_(dinfo_free)(altbuildid);
       }
@@ -2563,22 +2628,22 @@
       /* TOPLEVEL */
       /* If we were successful in finding alternate debug image, pull various
          size and image addresses out of it. */
-      if (aimage != 0 
-          && n_aimage >= sizeof(ElfXX_Ehdr)
-          && ML_(is_elf_object_file)((void*)aimage, n_aimage, True)) {
+      if (aimg != NULL && is_elf_object_file_by_DiImage(aimg, True)) {
 
          /* Pull out and validate program header and section header info */
-         ElfXX_Ehdr* ehdr_aimg     = (ElfXX_Ehdr*)aimage;
-         ElfXX_Shdr* shdr_aimg     = (ElfXX_Shdr*)( ((UChar*)ehdr_aimg)
-                                                       + ehdr_aimg->e_shoff );
-         UWord       shdr_dnent       = ehdr_aimg->e_shnum;
-         UWord       shdr_dent_szB    = ehdr_aimg->e_shentsize;
-         UChar*      shdr_strtab_aimg = NULL;
+         DiOffT      ehdr_aioff = 0;
+         ElfXX_Ehdr  ehdr_aimg;
+         ML_(img_get)(&ehdr_aimg, aimg, ehdr_aioff, sizeof(ehdr_aimg));
 
-         if (shdr_dnent == 0
-             || !contained_within(
-                    aimage, n_aimage,
-                    (Addr)shdr_aimg, shdr_dnent * shdr_dent_szB)) {
+         DiOffT   shdr_aioff        = ehdr_aimg.e_shoff;
+         UWord    shdr_anent        = ehdr_aimg.e_shnum;
+         UWord    shdr_aent_szB     = ehdr_aimg.e_shentsize;
+
+         DiOffT   shdr_strtab_aioff = DiOffT_INVALID;
+
+         if (shdr_anent == 0
+             || !ML_(img_valid)(aimg, shdr_aioff,
+                                shdr_anent * shdr_aent_szB)) {
             ML_(symerr)(di, True,
                         "Missing or invalid ELF Section Header Table"
                         " (alternate debuginfo file)");
@@ -2587,45 +2652,59 @@
 
          /* Also find the section header's string table, and validate. */
          /* checked previously by is_elf_object_file: */
-         vg_assert( ehdr_aimg->e_shstrndx != SHN_UNDEF );
+         vg_assert(ehdr_aimg.e_shstrndx != SHN_UNDEF);
 
-         shdr_strtab_aimg
-            = (UChar*)( ((UChar*)ehdr_aimg)
-                        + shdr_aimg[ehdr_aimg->e_shstrndx].sh_offset);
-         if (!contained_within( 
-                 aimage, n_aimage,
-                 (Addr)shdr_strtab_aimg,
-                 1/*bogus, but we don't know the real size*/ )) {
-            ML_(symerr)(di, True, 
-                        "Invalid ELF Section Header String Table"
-                        " (alternate debuginfo file)");
-            goto out;
+         // shdr_aioff is the offset of the section header table
+         // and we need the ehdr_aimg.e_shstrndx'th entry
+         { ElfXX_Shdr a_shdr;
+           ML_(img_get)(&a_shdr, aimg,
+                        INDEX_BIS(shdr_aioff, ehdr_aimg.e_shstrndx,
+                                              shdr_aent_szB),
+                        sizeof(a_shdr));
+           shdr_strtab_aioff = a_shdr.sh_offset;
+           if (!ML_(img_valid)(aimg, shdr_strtab_aioff,
+                               1/*bogus, but we don't know the real size*/)) {
+              ML_(symerr)(di, True, 
+                          "Invalid ELF Section Header String Table"
+                          " (alternate debuginfo file)");
+              goto out;
+           }
          }
 
          /* Find all interesting sections */
-         for (i = 0; i < ehdr_aimg->e_shnum; i++) {
+         for (i = 0; i < ehdr_aimg.e_shnum; i++) {
 
-#           define FIND(sec_name, sec_size, sec_img) \
-            do { ElfXX_Shdr* shdr \
-                    = INDEX_BIS( shdr_aimg, i, shdr_dent_szB ); \
-               if (0 == VG_(strcmp)(sec_name, \
-                                    (HChar *)(shdr_strtab_aimg + shdr->sh_name))) { \
-                  if (0 != sec_img) \
-                     VG_(core_panic)("repeated section!\n"); \
-                  sec_img  = (void*)(aimage + shdr->sh_offset); \
-                  sec_size = shdr->sh_size; \
-                  TRACE_SYMTAB( "%18s: aimg %p .. %p\n", \
-                                sec_name, \
-                                (UChar*)sec_img, \
-                                ((UChar*)sec_img) + sec_size - 1); \
+#           define FIND(_sec_name, _sec_escn) \
+            do { \
+               ElfXX_Shdr a_shdr; \
+               ML_(img_get)(&a_shdr, aimg, \
+                            INDEX_BIS(shdr_aioff, i, shdr_aent_szB), \
+                            sizeof(a_shdr)); \
+               if (0 == ML_(img_strcmp_c)(aimg, shdr_strtab_aioff \
+                                          + a_shdr.sh_name, _sec_name)) { \
+                  if (_sec_escn.img != NULL) { \
+                     ML_(symerr)(di, True, \
+                                 "   alternate debuginfo section duplicates a" \
+                                 " section in the main ELF file"); \
+                     goto out; \
+                  } \
+                  _sec_escn.img  = aimg; \
+                  _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
+                  _sec_escn.szB  = a_shdr.sh_size; \
+                  vg_assert(_sec_escn.img  != NULL); \
+                  vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
+                  TRACE_SYMTAB( "%18s: aioff %llu .. %llu\n", \
+                                _sec_name, \
+                                (ULong)_sec_escn.ioff, \
+                                ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
                } \
             } while (0);
 
-            /*   NAME             SIZE           IMAGE addr */
-            FIND(".debug_line",   debug_line_alt_sz, debug_line_alt_img)
-            FIND(".debug_info",   debug_info_alt_sz, debug_info_alt_img)
-            FIND(".debug_abbrev", debug_abbv_alt_sz, debug_abbv_alt_img)
-            FIND(".debug_str",    debug_str_alt_sz,  debug_str_alt_img)
+            /*   NAME             ElfSec */
+            FIND(".debug_line",   debug_line_alt_escn)
+            FIND(".debug_info",   debug_info_alt_escn)
+            FIND(".debug_abbrev", debug_abbv_alt_escn)
+            FIND(".debug_str",    debug_str_alt_escn)
 
 #           undef FIND
          } /* Find all interesting sections */
@@ -2634,32 +2713,26 @@
 
       /* TOPLEVEL */
       /* Check some sizes */
-      vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
-      vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0);
+      vg_assert((dynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
+      vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
 
       /* Read symbols */
       {
          void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
-                                 ElfXX_Sym*,SizeT,
-                                 HChar*,SizeT,
-                                 Bool,UChar*);
+                                 DiSlice*, DiSlice*, DiSlice*, Bool);
          Bool symtab_in_debug;
 #        if defined(VGP_ppc64_linux)
          read_elf_symtab = read_elf_symtab__ppc64_linux;
 #        else
          read_elf_symtab = read_elf_symtab__normal;
 #        endif
-         symtab_in_debug = (Addr)symtab_img >= dimage
-                           && (Addr)symtab_img < dimage + n_dimage;
+         symtab_in_debug = symtab_escn.img == dimg;
          read_elf_symtab(di, "symbol table",
-                         symtab_img, symtab_sz,
-                         strtab_img, strtab_sz, 
-                         symtab_in_debug, opd_img);
-
+                         &symtab_escn, &strtab_escn, &opd_escn,
+                         symtab_in_debug);
          read_elf_symtab(di, "dynamic symbol table",
-                         dynsym_img, dynsym_sz,
-                         dynstr_img, dynstr_sz, 
-                         False, opd_img);
+                         &dynsym_escn, &dynstr_escn, &opd_escn,
+                         False);
       } /* Read symbols */
 
       /* TOPLEVEL */
@@ -2669,16 +2742,16 @@
       for (i = 0; i < di->n_ehframe; i++) {
          /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
             this next assertion should hold. */
-         vg_assert(ehframe_sz[i] == di->ehframe_size[i]);
+         vg_assert(ML_(sli_is_valid)(ehframe_escn[i]));
+         vg_assert(ehframe_escn[i].szB == di->ehframe_size[i]);
          ML_(read_callframe_info_dwarf3)( di,
-                                          ehframe_img[i],
-                                          ehframe_sz[i],
+                                          ehframe_escn[i],
                                           di->ehframe_avma[i],
                                           True/*is_ehframe*/ );
       }
-      if (debug_frame_sz) {
+      if (ML_(sli_is_valid)(debug_frame_escn)) {
          ML_(read_callframe_info_dwarf3)( di,
-                                          debug_frame_img, debug_frame_sz,
+                                          debug_frame_escn,
                                           0/*assume zero avma*/,
                                           False/*!is_ehframe*/ );
       }
@@ -2695,28 +2768,29 @@
          && !defined(VGPV_arm_linux_android) \
          && !defined(VGPV_x86_linux_android) \
          && !defined(VGP_mips64_linux)
+#if 0
       if (stab_img && stabstr_img) {
          ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz, 
                                          stabstr_img, stabstr_sz );
       }
+#endif
 #     endif
       /* jrs 2006-01-01: icc-8.1 has been observed to generate
          binaries without debug_str sections.  Don't preclude
          debuginfo reading for that reason, but, in
          read_unitinfo_dwarf2, do check that debugstr is non-NULL
          before using it. */
-      if (debug_info_img && debug_abbv_img && debug_line_img
-                                           /* && debug_str_img */) {
-
+      if (ML_(sli_is_valid)(debug_info_escn) 
+          && ML_(sli_is_valid)(debug_abbv_escn)
+          && ML_(sli_is_valid)(debug_line_escn)) {
          /* The old reader: line numbers and unwind info only */
          ML_(read_debuginfo_dwarf3) ( di,
-                                      debug_info_img, debug_info_sz,
-                                      debug_types_img, debug_types_sz,
-                                      debug_abbv_img, debug_abbv_sz,
-                                      debug_line_img, debug_line_sz,
-                                      debug_str_img,  debug_str_sz,
-                                      debug_str_alt_img, debug_str_alt_sz );
-
+                                      debug_info_escn,
+                                      debug_types_escn,
+                                      debug_abbv_escn,
+                                      debug_line_escn,
+                                      debug_str_escn,
+                                      debug_str_alt_escn );
          /* The new reader: read the DIEs in .debug_info to acquire
             information on variable types and locations.  But only if
             the tool asks for it, or the user requests it on the
@@ -2724,24 +2798,21 @@
          if (VG_(needs).var_info /* the tool requires it */
              || VG_(clo_read_var_info) /* the user asked for it */) {
             ML_(new_dwarf3_reader)(
-               di, debug_info_img,   debug_info_sz,
-                   debug_types_img,   debug_types_sz,
-                   debug_abbv_img,   debug_abbv_sz,
-                   debug_line_img,   debug_line_sz,
-                   debug_str_img,    debug_str_sz,
-                   debug_ranges_img, debug_ranges_sz,
-                   debug_loc_img,    debug_loc_sz,
-                   debug_info_alt_img, debug_info_alt_sz,
-                   debug_abbv_alt_img, debug_abbv_alt_sz,
-                   debug_line_alt_img, debug_line_alt_sz,
-                   debug_str_alt_img,  debug_str_alt_sz
+               di, debug_info_escn,     debug_types_escn,
+                   debug_abbv_escn,     debug_line_escn,
+                   debug_str_escn,      debug_ranges_escn,
+                   debug_loc_escn,      debug_info_alt_escn,
+                   debug_abbv_alt_escn, debug_line_alt_escn,
+                   debug_str_alt_escn
             );
          }
       }
+#if 0
       if (dwarf1d_img && dwarf1l_img) {
          ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz, 
                                           dwarf1l_img, dwarf1l_sz );
       }
+#endif
       /* TOPLEVEL */
 
    } /* "Find interesting sections, read the symbol table(s), read any debug
@@ -2781,17 +2852,12 @@
 
   out: 
    {
-      SysRes m_res;
-      /* Last, but not least, heave the image(s) back overboard. */
-      if (dimage) {
-         m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage );
-         vg_assert(!sr_isError(m_res));
-      }
-      m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage );
-      vg_assert(!sr_isError(m_res));
+      /* Last, but not least, detach from the image(s). */
+      if (mimg) ML_(img_done)(mimg);
+      if (dimg) ML_(img_done)(dimg);
+      if (aimg) ML_(img_done)(aimg);
 
-      if (svma_ranges)
-         VG_(deleteXA)(svma_ranges);
+      if (svma_ranges) VG_(deleteXA)(svma_ranges);
 
       return res;
    } /* out: */ 
diff --git a/coregrind/m_debuginfo/readmacho.c b/coregrind/m_debuginfo/readmacho.c
index c089669..94865cb 100644
--- a/coregrind/m_debuginfo/readmacho.c
+++ b/coregrind/m_debuginfo/readmacho.c
@@ -47,8 +47,9 @@
 #include "pub_core_clientstate.h"
 #include "pub_core_debuginfo.h"
 
-#include "priv_d3basics.h"
 #include "priv_misc.h"
+#include "priv_image.h"
+#include "priv_d3basics.h"
 #include "priv_tytypes.h"
 #include "priv_storage.h"
 #include "priv_readmacho.h"
@@ -85,23 +86,15 @@
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
-typedef
-   struct {
-      /* These two describe the entire mapped-in ("primary") image,
-         fat headers, kitchen sink, whatnot: the entire file.  The
-         image is mapped into img[0 .. img_szB-1]. */
-      UChar* img;
-      SizeT  img_szB;
-      /* These two describe the Mach-O object of interest, which is
-         presumably somewhere inside the primary image.
-         map_image_aboard() below, which generates this info, will
-         carefully check that the macho_ fields denote a section of
-         memory that falls entirely inside img[0 .. img_szB-1]. */
-      UChar* macho_img;
-      SizeT  macho_img_szB;
-   }
-   ImageInfo;
-
+/* A DiSlice is used to handle the thin/fat distinction for MachO images.
+   (1) the entire mapped-in ("primary") image, fat headers, kitchen sink,
+       whatnot: the entire file.  This is the DiImage* that is the backing
+       for the DiSlice.
+   (2) the Mach-O object of interest, which is presumably somewhere inside
+       the primary image.  map_image_aboard() below, which generates this
+       info, will carefully check that the macho_ fields denote a section of
+       memory that falls entirely inside the primary image.
+*/
 
 Bool ML_(is_macho_object_file)( const void* buf, SizeT szB )
 {
@@ -137,174 +130,158 @@
 
 
 /* Unmap an image mapped in by map_image_aboard. */
-static void unmap_image ( /*MOD*/ImageInfo* ii )
+static void unmap_image ( /*MOD*/DiSlice* sli )
 {
-   SysRes sres;
-   vg_assert(ii->img);
-   vg_assert(ii->img_szB > 0);
-   sres = VG_(am_munmap_valgrind)( (Addr)ii->img, ii->img_szB );
-   /* Do we care if this fails?  I suppose so; it would indicate
-      some fairly serious snafu with the mapping of the file. */
-   vg_assert( !sr_isError(sres) );
-   VG_(memset)(ii, 0, sizeof(*ii));
+   vg_assert(sli);
+   if (ML_(sli_is_valid)(*sli)) {
+      ML_(img_done)(sli->img);
+      *sli = DiSlice_INVALID;
+   }
 }
 
 
-/* Map a given fat or thin object aboard, find the thin part if
-   necessary, do some checks, and write details of both the fat and
-   thin parts into *ii.  Returns False (and leaves the file unmapped)
-   on failure.  Guarantees to return pointers to a valid(ish) Mach-O
-   image if it succeeds. */
-static Bool map_image_aboard ( DebugInfo* di, /* only for err msgs */
-                               /*OUT*/ImageInfo* ii, UChar* filename )
+/* Open the given file, find the thin part if necessary, do some
+   checks, and return a DiSlice containing details of both the thin
+   part and (implicitly, via the contained DiImage*) the fat part.
+   returns DiSlice_INVALID if it fails.  If it succeeds, the returned
+   slice is guaranteed to refer to a valid(ish) Mach-O image. */
+static DiSlice map_image_aboard ( DebugInfo* di, /* only for err msgs */
+                                  const HChar* filename )
 {
-   VG_(memset)(ii, 0, sizeof(*ii));
+   DiSlice sli = DiSlice_INVALID;
 
    /* First off, try to map the thing in. */
-   { SizeT  size;
-     SysRes fd, sres;
-     struct vg_stat stat_buf;
-
-     fd = VG_(stat)(filename, &stat_buf);
-     if (sr_isError(fd)) {
-        ML_(symerr)(di, True, "Can't stat image (to determine its size)?!");
-        return False;
-     }
-     size = stat_buf.size;
-
-     fd = VG_(open)(filename, VKI_O_RDONLY, 0);
-     if (sr_isError(fd)) {
-       ML_(symerr)(di, True, "Can't open image to read symbols?!");
-        return False;
-     }
-
-     sres = VG_(am_mmap_file_float_valgrind)
-               ( size, VKI_PROT_READ, sr_Res(fd), 0 );
-     if (sr_isError(sres)) {
-        ML_(symerr)(di, True, "Can't mmap image to read symbols?!");
-        return False;
-     }
-
-     VG_(close)(sr_Res(fd));
-
-     ii->img     = (UChar*)sr_Res(sres);
-     ii->img_szB = size;
+   DiImage* mimg = ML_(img_from_local_file)(filename);
+   if (mimg == NULL) {
+      VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
+                               filename );
+      VG_(message)(Vg_UserMsg, "         no symbols or debug info loaded\n" );
+      return DiSlice_INVALID;
    }
 
-   /* Now it's mapped in and we have .img and .img_szB set.  Look for
-      the embedded Mach-O object.  If not findable, unmap and fail. */
-   { struct fat_header*  fh_be;
-     struct fat_header   fh;
-     struct MACH_HEADER* mh;
+   /* Now we have a viable DiImage* for it.  Look for the embedded
+      Mach-O object.  If not findable, close the image and fail. */
+   DiOffT            fh_be_ioff = 0;
+   struct fat_header fh_be;
+   struct fat_header fh;
      
-     // Assume initially that we have a thin image, and update
-     // these if it turns out to be fat.
-     ii->macho_img     = ii->img;
-     ii->macho_img_szB = ii->img_szB;
+   // Assume initially that we have a thin image, and narrow
+   // the bounds if it turns out to be fat.  This stores |mimg| as
+   // |sli.img|, so NULL out |mimg| after this point, for the sake of
+   // clarity.
+   sli  = ML_(sli_from_img)(mimg);
+   mimg = NULL;
 
-     // Check for fat header.
-     if (ii->img_szB < sizeof(struct fat_header)) {
-        ML_(symerr)(di, True, "Invalid Mach-O file (0 too small).");
-        goto unmap_and_fail;
-     }
-
-     // Fat header is always BIG-ENDIAN
-     fh_be = (struct fat_header *)ii->img;
-     fh.magic = VG_(ntohl)(fh_be->magic);
-     fh.nfat_arch = VG_(ntohl)(fh_be->nfat_arch);
-     if (fh.magic == FAT_MAGIC) {
-        // Look for a good architecture.
-        struct fat_arch *arch_be;
-        struct fat_arch arch;
-        Int f;
-        if (ii->img_szB < sizeof(struct fat_header)
-                          + fh.nfat_arch * sizeof(struct fat_arch)) {
-           ML_(symerr)(di, True, "Invalid Mach-O file (1 too small).");
-           goto unmap_and_fail;
-        }
-        for (f = 0, arch_be = (struct fat_arch *)(fh_be+1); 
-             f < fh.nfat_arch;
-             f++, arch_be++) {
-           Int cputype;
-#          if defined(VGA_ppc)
-           cputype = CPU_TYPE_POWERPC;
-#          elif defined(VGA_ppc64)
-           cputype = CPU_TYPE_POWERPC64;
-#          elif defined(VGA_x86)
-           cputype = CPU_TYPE_X86;
-#          elif defined(VGA_amd64)
-           cputype = CPU_TYPE_X86_64;
-#          else
-#            error "unknown architecture"
-#          endif
-           arch.cputype    = VG_(ntohl)(arch_be->cputype);
-           arch.cpusubtype = VG_(ntohl)(arch_be->cpusubtype);
-           arch.offset     = VG_(ntohl)(arch_be->offset);
-           arch.size       = VG_(ntohl)(arch_be->size);
-           if (arch.cputype == cputype) {
-              if (ii->img_szB < arch.offset + arch.size) {
-                 ML_(symerr)(di, True, "Invalid Mach-O file (2 too small).");
-                 goto unmap_and_fail;
-              }
-              ii->macho_img     = ii->img + arch.offset;
-              ii->macho_img_szB = arch.size;
-              break;
-           }
-        }
-        if (f == fh.nfat_arch) {
-           ML_(symerr)(di, True,
-                       "No acceptable architecture found in fat file.");
-           goto unmap_and_fail;
-        }
-     }
-
-     /* Sanity check what we found. */
-
-     /* assured by logic above */
-     vg_assert(ii->img_szB >= sizeof(struct fat_header));
-
-     if (ii->macho_img_szB < sizeof(struct MACH_HEADER)) {
-        ML_(symerr)(di, True, "Invalid Mach-O file (3 too small).");
-        goto unmap_and_fail;
-     }
-
-     if (ii->macho_img_szB > ii->img_szB) {
-        ML_(symerr)(di, True, "Invalid Mach-O file (thin bigger than fat).");
-        goto unmap_and_fail;
-     }
-
-     if (ii->macho_img >= ii->img
-         && ii->macho_img + ii->macho_img_szB <= ii->img + ii->img_szB) {
-        /* thin entirely within fat, as expected */
-     } else {
-        ML_(symerr)(di, True, "Invalid Mach-O file (thin not inside fat).");
-        goto unmap_and_fail;
-     }
-
-     mh = (struct MACH_HEADER *)ii->macho_img;
-     if (mh->magic != MAGIC) {
-        ML_(symerr)(di, True, "Invalid Mach-O file (bad magic).");
-        goto unmap_and_fail;
-     }
-
-     if (ii->macho_img_szB < sizeof(struct MACH_HEADER) + mh->sizeofcmds) {
-        ML_(symerr)(di, True, "Invalid Mach-O file (4 too small).");
-        goto unmap_and_fail;
-     }
+   // Check for fat header.
+   if (ML_(img_size)(sli.img) < sizeof(struct fat_header)) {
+      ML_(symerr)(di, True, "Invalid Mach-O file (0 too small).");
+      goto close_and_fail;
    }
 
-   vg_assert(ii->img);
-   vg_assert(ii->macho_img);
-   vg_assert(ii->img_szB > 0);
-   vg_assert(ii->macho_img_szB > 0);
-   vg_assert(ii->macho_img >= ii->img);
-   vg_assert(ii->macho_img + ii->macho_img_szB <= ii->img + ii->img_szB);
-   return True;  /* success */
+   // Fat header is always BIG-ENDIAN
+   ML_(img_get)(&fh_be, sli.img, fh_be_ioff, sizeof(fh_be));
+   VG_(memset)(&fh, 0, sizeof(fh));
+   fh.magic     = VG_(ntohl)(fh_be.magic);
+   fh.nfat_arch = VG_(ntohl)(fh_be.nfat_arch);
+   if (fh.magic == FAT_MAGIC) {
+      // Look for a good architecture.
+      if (ML_(img_size)(sli.img) < sizeof(struct fat_header)
+                                   + fh.nfat_arch * sizeof(struct fat_arch)) {
+         ML_(symerr)(di, True, "Invalid Mach-O file (1 too small).");
+         goto close_and_fail;
+      }
+      DiOffT arch_be_ioff;
+      Int    f;
+      for (f = 0, arch_be_ioff = sizeof(struct fat_header);
+           f < fh.nfat_arch;
+           f++, arch_be_ioff += sizeof(struct fat_arch)) {
+#        if defined(VGA_ppc)
+         Int cputype = CPU_TYPE_POWERPC;
+#        elif defined(VGA_ppc64)
+         Int cputype = CPU_TYPE_POWERPC64;
+#        elif defined(VGA_x86)
+         Int cputype = CPU_TYPE_X86;
+#        elif defined(VGA_amd64)
+         Int cputype = CPU_TYPE_X86_64;
+#        else
+#          error "unknown architecture"
+#        endif
+         struct fat_arch arch_be;
+         struct fat_arch arch;
+         ML_(img_get)(&arch_be, sli.img, arch_be_ioff, sizeof(arch_be));
+         VG_(memset)(&arch, 0, sizeof(arch));
+         arch.cputype    = VG_(ntohl)(arch_be.cputype);
+         arch.cpusubtype = VG_(ntohl)(arch_be.cpusubtype);
+         arch.offset     = VG_(ntohl)(arch_be.offset);
+         arch.size       = VG_(ntohl)(arch_be.size);
+         if (arch.cputype == cputype) {
+            if (ML_(img_size)(sli.img) < arch.offset + arch.size) {
+               ML_(symerr)(di, True, "Invalid Mach-O file (2 too small).");
+               goto close_and_fail;
+            }
+            /* Found a suitable arch.  Narrow down the slice accordingly. */
+            sli.ioff = arch.offset;
+            sli.szB  = arch.size;
+            break;
+         }
+      }
+      if (f == fh.nfat_arch) {
+         ML_(symerr)(di, True,
+                     "No acceptable architecture found in fat file.");
+         goto close_and_fail;
+      }
+   }
+
+   /* Sanity check what we found. */
+
+   /* assured by logic above */
+   vg_assert(ML_(img_size)(sli.img) >= sizeof(struct fat_header));
+
+   if (sli.szB < sizeof(struct MACH_HEADER)) {
+      ML_(symerr)(di, True, "Invalid Mach-O file (3 too small).");
+      goto close_and_fail;
+   }
+
+   if (sli.szB > ML_(img_size)(sli.img)) {
+      ML_(symerr)(di, True, "Invalid Mach-O file (thin bigger than fat).");
+      goto close_and_fail;
+   }
+
+   if (sli.ioff >= 0 && sli.ioff + sli.szB <= ML_(img_size)(sli.img)) {
+      /* thin entirely within fat, as expected */
+   } else {
+      ML_(symerr)(di, True, "Invalid Mach-O file (thin not inside fat).");
+      goto close_and_fail;
+   }
+
+   /* Peer at the Mach header for the thin object, starting at the
+      beginning of the slice, to check it's at least marginally
+      sane. */
+   struct MACH_HEADER mh;
+   ML_(cur_read_get)(&mh, ML_(cur_from_sli)(sli), sizeof(mh));
+   if (mh.magic != MAGIC) {
+      ML_(symerr)(di, True, "Invalid Mach-O file (bad magic).");
+      goto close_and_fail;
+   }
+
+   if (sli.szB < sizeof(struct MACH_HEADER) + mh.sizeofcmds) {
+      ML_(symerr)(di, True, "Invalid Mach-O file (4 too small).");
+      goto close_and_fail;
+   }
+
+   /* "main image is plausible" */
+   vg_assert(sli.img);
+   vg_assert(ML_(img_size)(sli.img) > 0);
+   /* "thin image exists and is a sub-part (or all) of main image" */
+   vg_assert(sli.ioff >= 0);
+   vg_assert(sli.szB > 0);
+   vg_assert(sli.ioff + sli.szB <= ML_(img_size)(sli.img));
+   return sli;  /* success */
    /*NOTREACHED*/
 
-  unmap_and_fail:
-   unmap_image(ii);
-   return False; /* bah! */
+  close_and_fail:
+   unmap_image(&sli);
+   return DiSlice_INVALID; /* bah! */
 }
 
 
@@ -320,30 +297,38 @@
 static
 void read_symtab( /*OUT*/XArray* /* DiSym */ syms,
                   struct _DebugInfo* di, 
-                  struct NLIST* o_symtab, UInt o_symtab_count,
-                  UChar*     o_strtab, UInt o_strtab_sz )
+                  DiCursor symtab_cur, UInt symtab_count,
+                  DiCursor strtab_cur, UInt strtab_sz )
 {
    Int    i;
-   Addr   sym_addr;
    DiSym  disym;
-   UChar* name;
 
-   static UChar* s_a_t_v = NULL; /* do not make non-static */
+   // "start_according_to_valgrind"
+   static HChar* s_a_t_v = NULL; /* do not make non-static */
 
-   for (i = 0; i < o_symtab_count; i++) {
-      struct NLIST *nl = o_symtab+i;
-      if ((nl->n_type & N_TYPE) == N_SECT) {
-         sym_addr = di->text_bias + nl->n_value;
-    /*} else if ((nl->n_type & N_TYPE) == N_ABS) {
+   for (i = 0; i < symtab_count; i++) {
+      struct NLIST nl;
+      ML_(cur_read_get)(&nl,
+                        ML_(cur_plus)(symtab_cur, i * sizeof(struct NLIST)),
+                        sizeof(nl));
+
+      Addr sym_addr = 0;
+      if ((nl.n_type & N_TYPE) == N_SECT) {
+         sym_addr = di->text_bias + nl.n_value;
+      /*} else if ((nl.n_type & N_TYPE) == N_ABS) {
          GrP fixme don't ignore absolute symbols?
-         sym_addr = nl->n_value; */
+         sym_addr = nl.n_value; */
       } else {
          continue;
       }
       
-      if (di->trace_symtab)
-         VG_(printf)("nlist raw: avma %010lx  %s\n",
-                     sym_addr, o_strtab + nl->n_un.n_strx );
+      if (di->trace_symtab) {
+         HChar* str = ML_(cur_read_strdup)(
+                         ML_(cur_plus)(strtab_cur, nl.n_un.n_strx),
+                         "di.read_symtab.1");
+         VG_(printf)("nlist raw: avma %010lx  %s\n", sym_addr, str );
+         ML_(dinfo_free)(str);
+      }
 
       /* If no part of the symbol falls within the mapped range,
          ignore it. */
@@ -354,14 +339,20 @@
 
       /* skip names which point outside the string table;
          following these risks segfaulting Valgrind */
-      name = o_strtab + nl->n_un.n_strx;
-      if (name < o_strtab || name >= o_strtab + o_strtab_sz)
+      if (nl.n_un.n_strx < 0 || nl.n_un.n_strx >= strtab_sz) {
          continue;
+      }
+
+      HChar* name
+         = ML_(cur_read_strdup)( ML_(cur_plus)(strtab_cur, nl.n_un.n_strx),
+                                 "di.read_symtab.2");
 
       /* skip nameless symbols; these appear to be common, but
          useless */
-      if (*name == 0)
+      if (*name == 0) {
+         ML_(dinfo_free)(name);
          continue;
+      }
 
       disym.addr      = sym_addr;
       disym.tocptr    = 0;
@@ -389,6 +380,7 @@
 
       vg_assert(disym.pri_name);
       VG_(addToXA)( syms, &disym );
+      ML_(dinfo_free)(name);
    }
 }
 
@@ -496,7 +488,7 @@
 #endif
 
 
-static Bool file_exists_p(const Char *path)
+static Bool file_exists_p(const HChar *path)
 {
    struct vg_stat sbuf;
    SysRes res = VG_(stat)(path, &sbuf);
@@ -506,13 +498,13 @@
 
 /* Search for an existing dSYM file as a possible separate debug file.  
    Adapted from gdb. */
-static Char *
-find_separate_debug_file (const Char *executable_name)
+static HChar *
+find_separate_debug_file (const HChar *executable_name)
 {
-   const Char *basename_str;
-   Char *dot_ptr;
-   Char *slash_ptr;
-   Char *dsymfile;
+   const HChar *basename_str;
+   HChar *dot_ptr;
+   HChar *slash_ptr;
+   HChar *dsymfile;
     
    /* Make sure the object file name itself doesn't contain ".dSYM" in it or we
       will end up with an infinite loop where after we add a dSYM symbol file,
@@ -593,53 +585,85 @@
 }
 
 
-static UChar *getsectdata(UChar* base, SizeT size, 
-                          const Char *segname, const Char *sectname,
-                          /*OUT*/Word *sect_size)
+/* Given a DiSlice covering the entire Mach-O thin image, find the
+   DiSlice for the specified (segname, sectname) pairing, if
+   possible. */
+static DiSlice getsectdata ( DiSlice img,
+                             const HChar *segname, const HChar *sectname )
 {
-   struct MACH_HEADER *mh = (struct MACH_HEADER *)base;
-   struct load_command *cmd;          
-   Int c;
+   DiCursor cur = ML_(cur_from_sli)(img);
 
-   for (c = 0, cmd = (struct load_command *)(mh+1);
-        c < mh->ncmds;
-        c++, cmd = (struct load_command *)(cmd->cmdsize + (Addr)cmd))
-   {
-      if (cmd->cmd == LC_SEGMENT_CMD) {
-         struct SEGMENT_COMMAND *seg = (struct SEGMENT_COMMAND *)cmd;
-         if (0 == VG_(strncmp(seg->segname, segname, sizeof(seg->segname)))) {
-            struct SECTION *sects = (struct SECTION *)(seg+1);
+   struct MACH_HEADER mh;
+   ML_(cur_step_get)(&mh, &cur, sizeof(mh));
+
+   Int c;
+   for (c = 0; c < mh.ncmds; c++) {
+      struct load_command cmd;          
+      ML_(cur_read_get)(&cmd, cur, sizeof(cmd));
+      if (cmd.cmd == LC_SEGMENT_CMD) {
+         struct SEGMENT_COMMAND seg;
+         ML_(cur_read_get)(&seg, cur, sizeof(seg));
+         if (0 == VG_(strncmp(&seg.segname[0],
+                              segname, sizeof(seg.segname)))) {
+            DiCursor sects_cur = ML_(cur_plus)(cur, sizeof(seg));
             Int s;
-            for (s = 0; s < seg->nsects; s++) {
-               if (0 == VG_(strncmp(sects[s].sectname, sectname, 
-                                    sizeof(sects[s].sectname)))) 
-               {
-                  if (sect_size) *sect_size = sects[s].size;
-                  return (UChar *)(base + sects[s].offset);
+            for (s = 0; s < seg.nsects; s++) {
+               struct SECTION sect;
+               ML_(cur_step_get)(&sect, &sects_cur, sizeof(sect));
+               if (0 == VG_(strncmp(sect.sectname, sectname, 
+                                    sizeof(sect.sectname)))) {
+                  DiSlice res = img;
+                  res.ioff = sect.offset;
+                  res.szB = sect.size;
+                  return res;
                }
             }
+
          }
       }
+      cur = ML_(cur_plus)(cur, cmd.cmdsize);
    }
 
-   if (sect_size) *sect_size = 0;
-   return 0;
+   return DiSlice_INVALID;
 }
 
 
-/* Brute force just simply search for uuid[0..15] in img[0..n_img-1] */
-static Bool check_uuid_matches ( Addr imgA, Word n_img, UChar* uuid )
+/* Brute force just simply search for uuid[0..15] in |sli| */
+static Bool check_uuid_matches ( DiSlice sli, UChar* uuid )
 {
-   Word   i;
-   UChar* img = (UChar*)imgA;
-   UChar  first = uuid[0];
-   if (n_img < 16)
+   if (sli.szB < 16)
       return False;
-   for (i = 0; i < n_img-16; i++) {
-      if (img[i] != first)
-         continue;
-      if (0 == VG_(memcmp)( &img[i], &uuid[0], 16 ))
-         return True;
+
+   /* Work through the slice in 1 KB chunks. */
+   UChar  first    = uuid[0];
+   DiOffT min_off  = sli.ioff;
+   DiOffT max1_off = sli.ioff + sli.szB;
+   DiOffT curr_off = min_off;
+   vg_assert(min_off < max1_off);
+   while (1) {
+      vg_assert(curr_off >= min_off && curr_off <= max1_off);
+      if (curr_off == max1_off) break;
+      DiOffT avail = max1_off - curr_off;
+      vg_assert(avail > 0 && avail <= max1_off);
+      if (avail > 1024) avail = 1024;
+      UChar buf[1024];
+      SizeT nGot = ML_(img_get_some)(buf, sli.img, curr_off, avail);
+      vg_assert(nGot >= 1 && nGot <= avail);
+      UInt i;
+      /* Scan through the 1K chunk we got, looking for the start char. */
+      for (i = 0; i < (UInt)nGot; i++) {
+         if (buf[i] != first)
+            continue;
+         /* first char matches.  See if we can get 16 bytes at this
+            offset, and compare. */
+         if (curr_off + i < max1_off && max1_off - (curr_off + i) >= 16) {
+            UChar buff16[16];
+            ML_(img_get)(&buff16[0], sli.img, curr_off + i, 16);
+            if (0 == VG_(memcmp)(&buff16[0], &uuid[0], 16))
+               return True;
+         }
+         curr_off += nGot;
+      }
    }
    return False;
 }
@@ -648,7 +672,7 @@
 /* Heuristic kludge: return True if this looks like an installed
    standard library; hence we shouldn't consider automagically running
    dsymutil on it. */
-static Bool is_systemish_library_name ( UChar* name )
+static Bool is_systemish_library_name ( HChar* name )
 {
    vg_assert(name);
    if (0 == VG_(strncasecmp)(name, "/usr/", 5)
@@ -668,15 +692,14 @@
 
 Bool ML_(read_macho_debug_info)( struct _DebugInfo* di )
 {
-   struct symtab_command *symcmd = NULL;
-   struct dysymtab_command *dysymcmd = NULL;
-   HChar* dsymfilename = NULL;
-   Bool have_uuid = False;
-   UChar uuid[16];
-   ImageInfo ii;  /* main file */
-   ImageInfo iid; /* auxiliary .dSYM file */
-   Bool ok;
-   Word i;
+   DiSlice  msli         = DiSlice_INVALID; // the main image
+   DiSlice  dsli         = DiSlice_INVALID; // the debuginfo image
+   DiCursor sym_cur      = DiCursor_INVALID;
+   DiCursor dysym_cur    = DiCursor_INVALID;
+   HChar*   dsymfilename = NULL;
+   Bool     have_uuid    = False;
+   UChar    uuid[16];
+   Word     i;
    struct _DebugInfoMapping* rx_map = NULL;
    struct _DebugInfoMapping* rw_map = NULL;
 
@@ -705,14 +728,15 @@
                    "%s (rx at %#lx, rw at %#lx)\n", di->fsm.filename,
                    rx_map->avma, rw_map->avma );
 
-   VG_(memset)(&ii,   0, sizeof(ii));
-   VG_(memset)(&iid,  0, sizeof(iid));
    VG_(memset)(&uuid, 0, sizeof(uuid));
 
-   ok = map_image_aboard( di, &ii, di->fsm.filename );
-   if (!ok) goto fail;
+   msli = map_image_aboard( di, di->fsm.filename );
+   if (!ML_(sli_is_valid)(msli)) {
+      ML_(symerr)(di, False, "Connect to main image failed.");
+      goto fail;
+   }
 
-   vg_assert(ii.macho_img != NULL && ii.macho_img_szB > 0);
+   vg_assert(msli.img != NULL && msli.szB > 0);
 
    /* Poke around in the Mach-O header, to find some important
       stuff. */
@@ -725,38 +749,55 @@
 
    di->text_bias = 0;
 
-   { struct MACH_HEADER *mh = (struct MACH_HEADER *)ii.macho_img;
-      struct load_command *cmd;
-      Int c;
+   { 
+      DiCursor cmd_cur = ML_(cur_from_sli)(msli);
 
-      for (c = 0, cmd = (struct load_command *)(mh+1);
-           c < mh->ncmds;
-           c++, cmd = (struct load_command *)(cmd->cmdsize
-                                              + (unsigned long)cmd)) {
-         if (cmd->cmd == LC_SYMTAB) {
-            symcmd = (struct symtab_command *)cmd;
+      struct MACH_HEADER mh;
+      ML_(cur_step_get)(&mh, &cmd_cur, sizeof(mh));
+
+      /* Now cur_cmd points just after the Mach header, right at the
+         start of the load commands, which is where we need it to start
+         the following loop. */
+
+      Int c;
+      for (c = 0; c < mh.ncmds; c++) {
+         struct load_command cmd;
+         ML_(cur_read_get)(&cmd, cmd_cur, sizeof(cmd));
+ 
+         if (cmd.cmd == LC_SYMTAB) {
+            sym_cur = cmd_cur;
          } 
-         else if (cmd->cmd == LC_DYSYMTAB) {
-            dysymcmd = (struct dysymtab_command *)cmd;
+         else if (cmd.cmd == LC_DYSYMTAB) {
+            dysym_cur = cmd_cur;
          } 
-         else if (cmd->cmd == LC_ID_DYLIB && mh->filetype == MH_DYLIB) {
+         else if (cmd.cmd == LC_ID_DYLIB && mh.filetype == MH_DYLIB) {
             // GrP fixme bundle?
-            struct dylib_command *dcmd = (struct dylib_command *)cmd;
-            UChar *dylibname = dcmd->dylib.name.offset + (UChar *)dcmd;
-            UChar *soname = VG_(strrchr)(dylibname, '/');
+            struct dylib_command dcmd;
+            ML_(cur_read_get)(&dcmd, cmd_cur, sizeof(dcmd));
+            DiCursor dylibname_cur
+               = ML_(cur_plus)(cmd_cur, dcmd.dylib.name.offset);
+            HChar* dylibname
+               = ML_(cur_read_strdup)(dylibname_cur, "di.rmdi.1");
+            HChar* soname = VG_(strrchr)(dylibname, '/');
             if (!soname) soname = dylibname;
             else soname++;
             di->soname = ML_(dinfo_strdup)("di.readmacho.dylibname",
                                            soname);
+            ML_(dinfo_free)(dylibname);
          }
-         else if (cmd->cmd==LC_ID_DYLINKER  &&  mh->filetype==MH_DYLINKER) {
-            struct dylinker_command *dcmd = (struct dylinker_command *)cmd;
-            UChar *dylinkername = dcmd->name.offset + (UChar *)dcmd;
-            UChar *soname = VG_(strrchr)(dylinkername, '/');
+         else if (cmd.cmd==LC_ID_DYLINKER  &&  mh.filetype==MH_DYLINKER) {
+            struct dylinker_command dcmd;
+            ML_(cur_read_get)(&dcmd, cmd_cur, sizeof(dcmd));
+            DiCursor dylinkername_cur
+               = ML_(cur_plus)(cmd_cur, dcmd.name.offset);
+            HChar* dylinkername
+               = ML_(cur_read_strdup)(dylinkername_cur, "di.rmdi.2");
+            HChar* soname = VG_(strrchr)(dylinkername, '/');
             if (!soname) soname = dylinkername;
             else soname++;
             di->soname = ML_(dinfo_strdup)("di.readmacho.dylinkername",
                                            soname);
+            ML_(dinfo_free)(dylinkername);
          }
 
          // A comment from Julian about why varinfo[35] fail:
@@ -786,17 +827,18 @@
          // {text,data,bss}_{avma,svma}, from which the _bias numbers are
          // then trivially derived.  Then I think the debuginfo reader should
          // work pretty well.
-         else if (cmd->cmd == LC_SEGMENT_CMD) {
-            struct SEGMENT_COMMAND *seg = (struct SEGMENT_COMMAND *)cmd;
+         else if (cmd.cmd == LC_SEGMENT_CMD) {
+            struct SEGMENT_COMMAND seg;
+            ML_(cur_read_get)(&seg, cmd_cur, sizeof(seg));
             /* Try for __TEXT */
             if (!di->text_present
-                && 0 == VG_(strcmp)(seg->segname, "__TEXT")
+                && 0 == VG_(strcmp)(&seg.segname[0], "__TEXT")
                 /* DDD: is the  next line a kludge? -- JRS */
-                && seg->fileoff == 0 && seg->filesize != 0) {
+                && seg.fileoff == 0 && seg.filesize != 0) {
                di->text_present = True;
-               di->text_svma = (Addr)seg->vmaddr;
+               di->text_svma = (Addr)seg.vmaddr;
                di->text_avma = rx_map->avma;
-               di->text_size = seg->vmsize;
+               di->text_size = seg.vmsize;
                di->text_bias = di->text_avma - di->text_svma;
                /* Make the _debug_ values be the same as the
                   svma/bias for the primary object, since there is
@@ -808,22 +850,23 @@
             }
             /* Try for __DATA */
             if (!di->data_present
-                && 0 == VG_(strcmp)(seg->segname, "__DATA")
-                /* && DDD:seg->fileoff == 0 */ && seg->filesize != 0) {
+                && 0 == VG_(strcmp)(&seg.segname[0], "__DATA")
+                /* && DDD:seg->fileoff == 0 */ && seg.filesize != 0) {
                di->data_present = True;
-               di->data_svma = (Addr)seg->vmaddr;
+               di->data_svma = (Addr)seg.vmaddr;
                di->data_avma = rw_map->avma;
-               di->data_size = seg->vmsize;
+               di->data_size = seg.vmsize;
                di->data_bias = di->data_avma - di->data_svma;
                di->data_debug_svma = di->data_svma;
                di->data_debug_bias = di->data_bias;
             }
          }
-         else if (cmd->cmd == LC_UUID) {
-             struct uuid_command *uuid_cmd = (struct uuid_command *)cmd;
-             VG_(memcpy)(uuid, uuid_cmd->uuid, sizeof(uuid));
+         else if (cmd.cmd == LC_UUID) {
+             ML_(cur_read_get)(&uuid, cmd_cur, sizeof(uuid));
              have_uuid = True;
          }
+         // Move the cursor along
+         cmd_cur = ML_(cur_plus)(cmd_cur, cmd.cmdsize);
       }
    }
 
@@ -839,33 +882,42 @@
 
    /* Now we have the base object to hand.  Read symbols from it. */
 
-   if (ii.macho_img && ii.macho_img_szB > 0 && symcmd && dysymcmd) {
+   // We already asserted that ..
+   vg_assert(msli.img != NULL && msli.szB > 0);
+
+   if (ML_(cur_is_valid)(sym_cur) && ML_(cur_is_valid)(dysym_cur)) {
+
+      struct symtab_command   symcmd;
+      struct dysymtab_command dysymcmd;
+
+      ML_(cur_read_get)(&symcmd,   sym_cur,   sizeof(symcmd));
+      ML_(cur_read_get)(&dysymcmd, dysym_cur, sizeof(dysymcmd));
 
       /* Read nlist symbol table */
-      struct NLIST *syms;
-      UChar *strs;
+      DiCursor syms = DiCursor_INVALID;
+      DiCursor strs = DiCursor_INVALID;
       XArray* /* DiSym */ candSyms = NULL;
       Word nCandSyms;
 
-      if (ii.macho_img_szB < symcmd->stroff + symcmd->strsize
-          || ii.macho_img_szB < symcmd->symoff + symcmd->nsyms
-                                                 * sizeof(struct NLIST)) {
+      if (msli.szB < symcmd.stroff + symcmd.strsize
+          || msli.szB < symcmd.symoff + symcmd.nsyms
+                                        * sizeof(struct NLIST)) {
          ML_(symerr)(di, False, "Invalid Mach-O file (5 too small).");
          goto fail;
       }   
-      if (dysymcmd->ilocalsym + dysymcmd->nlocalsym > symcmd->nsyms
-          || dysymcmd->iextdefsym + dysymcmd->nextdefsym > symcmd->nsyms) {
+      if (dysymcmd.ilocalsym + dysymcmd.nlocalsym > symcmd.nsyms
+          || dysymcmd.iextdefsym + dysymcmd.nextdefsym > symcmd.nsyms) {
          ML_(symerr)(di, False, "Invalid Mach-O file (bad symbol table).");
          goto fail;
       }
-      
-      syms = (struct NLIST *)(ii.macho_img + symcmd->symoff);
-      strs = (UChar *)(ii.macho_img + symcmd->stroff);
+
+      syms = ML_(cur_plus)(ML_(cur_from_sli)(msli), symcmd.symoff);
+      strs = ML_(cur_plus)(ML_(cur_from_sli)(msli), symcmd.stroff);
       
       if (VG_(clo_verbosity) > 1)
          VG_(message)(Vg_DebugMsg,
             "   reading syms   from primary file (%d %d)\n",
-            dysymcmd->nextdefsym, dysymcmd->nlocalsym );
+            dysymcmd.nextdefsym, dysymcmd.nlocalsym );
 
       /* Read candidate symbols into 'candSyms', so we can truncate
          overlapping ends and generally tidy up, before presenting
@@ -878,14 +930,16 @@
 
       // extern symbols
       read_symtab(candSyms,
-                  di, 
-                  syms + dysymcmd->iextdefsym, dysymcmd->nextdefsym, 
-                  strs, symcmd->strsize);
+                  di,
+                  ML_(cur_plus)(syms,
+                                dysymcmd.iextdefsym * sizeof(struct NLIST)),
+                  dysymcmd.nextdefsym, strs, symcmd.strsize);
       // static and private_extern symbols
       read_symtab(candSyms,
-                  di, 
-                  syms + dysymcmd->ilocalsym, dysymcmd->nlocalsym, 
-                  strs, symcmd->strsize);
+                  di,
+                  ML_(cur_plus)(syms,
+                                dysymcmd.ilocalsym * sizeof(struct NLIST)),
+                  dysymcmd.nlocalsym, strs, symcmd.strsize);
 
       /* tidy up the cand syms -- trim overlapping ends.  May resize
          candSyms. */
@@ -918,7 +972,7 @@
       goto success;
 
    /* mmap the dSYM file to look for DWARF debug info.  If successful,
-      use the .macho_img and .macho_img_szB in iid. */
+      use the .macho_img and .macho_img_szB in dsli. */
 
    dsymfilename = find_separate_debug_file( di->fsm.filename );
 
@@ -929,14 +983,16 @@
       if (VG_(clo_verbosity) > 1)
          VG_(message)(Vg_DebugMsg, "   dSYM= %s\n", dsymfilename);
 
-      ok = map_image_aboard( di, &iid, dsymfilename );
-      if (!ok) goto fail;
+      dsli = map_image_aboard( di, dsymfilename );
+      if (!ML_(sli_is_valid)(dsli)) {
+         ML_(symerr)(di, False, "Connect to debuginfo image failed "
+                                "(first attempt).");
+         goto fail;
+      }
 
       /* check it has the right uuid. */
       vg_assert(have_uuid);
-      valid = iid.macho_img && iid.macho_img_szB > 0 
-              && check_uuid_matches( (Addr)iid.macho_img,
-                                     iid.macho_img_szB, uuid );
+      valid = dsli.img && dsli.szB > 0 && check_uuid_matches( dsli, uuid );
       if (valid)
          goto read_the_dwarf;
 
@@ -997,14 +1053,17 @@
       if (VG_(clo_verbosity) > 1)
          VG_(message)(Vg_DebugMsg, "   dsyms= %s\n", dsymfilename);
 
-      ok = map_image_aboard( di, &iid, dsymfilename );
-      if (!ok) goto fail;
+      dsli = map_image_aboard( di, dsymfilename );
+      if (!ML_(sli_is_valid)(dsli)) {
+         ML_(symerr)(di, False, "Connect to debuginfo image failed "
+                                "(second attempt).");
+         goto fail;
+      }
 
       /* check it has the right uuid. */
       vg_assert(have_uuid);
-      valid = iid.macho_img && iid.macho_img_szB > 0 
-              && check_uuid_matches( (Addr)iid.macho_img,
-                                     iid.macho_img_szB, uuid );
+      vg_assert(have_uuid);
+      valid = dsli.img && dsli.szB > 0 && check_uuid_matches( dsli, uuid );
       if (!valid) {
          if (VG_(clo_verbosity) > 0) {
             VG_(message)(Vg_DebugMsg,
@@ -1019,9 +1078,9 @@
             VG_(message)(Vg_DebugMsg,
                          "WARNING: for %s\n", di->fsm.filename);
          }
-         unmap_image( &iid );
-         /* unmap_image zeroes the fields, so the following test makes
-            sense. */
+         unmap_image( &dsli );
+         /* unmap_image zeroes out dsli, so it's safe for "fail:" to
+            re-try unmap_image. */
          goto fail;
       }
    }
@@ -1030,65 +1089,43 @@
       on to reading stuff out of it. */
 
   read_the_dwarf:
-   if (iid.macho_img && iid.macho_img_szB > 0) {
-      UChar* debug_info_img = NULL;
-      Word   debug_info_sz;
-      UChar* debug_abbv_img;
-      Word   debug_abbv_sz;
-      UChar* debug_line_img;
-      Word   debug_line_sz;
-      UChar* debug_str_img;
-      Word   debug_str_sz;
-      UChar* debug_ranges_img;
-      Word   debug_ranges_sz;
-      UChar* debug_loc_img;
-      Word   debug_loc_sz;
-      UChar* debug_name_img;
-      Word   debug_name_sz;
-
-      debug_info_img = 
-          getsectdata(iid.macho_img, iid.macho_img_szB, 
-                      "__DWARF", "__debug_info", &debug_info_sz);
-      debug_abbv_img = 
-          getsectdata(iid.macho_img, iid.macho_img_szB, 
-                      "__DWARF", "__debug_abbrev", &debug_abbv_sz);
-      debug_line_img = 
-          getsectdata(iid.macho_img, iid.macho_img_szB, 
-                      "__DWARF", "__debug_line", &debug_line_sz);
-      debug_str_img = 
-          getsectdata(iid.macho_img, iid.macho_img_szB, 
-                      "__DWARF", "__debug_str", &debug_str_sz);
-      debug_ranges_img = 
-          getsectdata(iid.macho_img, iid.macho_img_szB, 
-                      "__DWARF", "__debug_ranges", &debug_ranges_sz);
-      debug_loc_img = 
-          getsectdata(iid.macho_img, iid.macho_img_szB, 
-                      "__DWARF", "__debug_loc", &debug_loc_sz);
-      debug_name_img = 
-          getsectdata(iid.macho_img, iid.macho_img_szB, 
-                      "__DWARF", "__debug_pubnames", &debug_name_sz);
+   if (ML_(sli_is_valid)(msli) && msli.szB > 0) {
+      // "_mscn" is "mach-o section"
+      DiSlice debug_info_mscn
+         = getsectdata(dsli, "__DWARF", "__debug_info");
+      DiSlice debug_abbv_mscn
+         = getsectdata(dsli, "__DWARF", "__debug_abbrev");
+      DiSlice debug_line_mscn
+         = getsectdata(dsli, "__DWARF", "__debug_line");
+      DiSlice debug_str_mscn
+         = getsectdata(dsli, "__DWARF", "__debug_str");
+      DiSlice debug_ranges_mscn
+         = getsectdata(dsli, "__DWARF", "__debug_ranges");
+      DiSlice debug_loc_mscn
+         = getsectdata(dsli, "__DWARF", "__debug_loc");
    
-      if (debug_info_img) {
+      if (ML_(sli_is_valid)(debug_info_mscn)) {
          if (VG_(clo_verbosity) > 1) {
             if (0)
             VG_(message)(Vg_DebugMsg,
                          "Reading dwarf3 for %s (%#lx) from %s"
-                         " (%ld %ld %ld %ld %ld %ld)\n",
+                         " (%lld %lld %lld %lld %lld %lld)\n",
                          di->fsm.filename, di->text_avma, dsymfilename,
-                         debug_info_sz, debug_abbv_sz, debug_line_sz, 
-                         debug_str_sz, debug_ranges_sz, debug_loc_sz
+                         debug_info_mscn.szB, debug_abbv_mscn.szB,
+                         debug_line_mscn.szB, debug_str_mscn.szB,
+                         debug_ranges_mscn.szB, debug_loc_mscn.szB
                          );
             VG_(message)(Vg_DebugMsg,
                "   reading dwarf3 from dsyms file\n");
          }
          /* The old reader: line numbers and unwind info only */
          ML_(read_debuginfo_dwarf3) ( di,
-                                      debug_info_img, debug_info_sz,
-				      NULL,           0,
-                                      debug_abbv_img, debug_abbv_sz,
-                                      debug_line_img, debug_line_sz,
-                                      debug_str_img,  debug_str_sz,
-                                      NULL, 0 /* ALT .debug_str */ );
+                                      debug_info_mscn,
+				      DiSlice_INVALID, /* .debug_types */
+                                      debug_abbv_mscn,
+                                      debug_line_mscn,
+                                      debug_str_mscn,
+                                      DiSlice_INVALID /* ALT .debug_str */ );
 
          /* The new reader: read the DIEs in .debug_info to acquire
             information on variable types and locations.  But only if
@@ -1097,17 +1134,17 @@
          if (VG_(needs).var_info /* the tool requires it */
              || VG_(clo_read_var_info) /* the user asked for it */) {
             ML_(new_dwarf3_reader)(
-               di, debug_info_img,   debug_info_sz,
-	           NULL,             0,
-                   debug_abbv_img,   debug_abbv_sz,
-                   debug_line_img,   debug_line_sz,
-                   debug_str_img,    debug_str_sz,
-                   debug_ranges_img, debug_ranges_sz,
-                   debug_loc_img,    debug_loc_sz,
-                   NULL, 0, /* ALT .debug_info */
-                   NULL, 0, /* ALT .debug_abbv */
-                   NULL, 0, /* ALT .debug_line */
-                   NULL, 0  /* ALT .debug_str */
+               di, debug_info_mscn,
+                   DiSlice_INVALID, /* .debug_types */
+                   debug_abbv_mscn,
+                   debug_line_mscn,
+                   debug_str_mscn,
+                   debug_ranges_mscn,
+                   debug_loc_mscn,
+                   DiSlice_INVALID, /* ALT .debug_info */
+                   DiSlice_INVALID, /* ALT .debug_abbv */
+                   DiSlice_INVALID, /* ALT .debug_line */
+                   DiSlice_INVALID  /* ALT .debug_str */
             );
          }
       }
@@ -1116,20 +1153,16 @@
    if (dsymfilename) ML_(dinfo_free)(dsymfilename);
 
   success:
-   if (ii.img)
-      unmap_image(&ii);
-   if (iid.img)
-      unmap_image(&iid);
+   unmap_image(&msli);
+   unmap_image(&dsli);
    return True;
 
    /* NOTREACHED */
 
   fail:
    ML_(symerr)(di, True, "Error reading Mach-O object.");
-   if (ii.img)
-      unmap_image(&ii);
-   if (iid.img)
-      unmap_image(&iid);
+   unmap_image(&msli);
+   unmap_image(&dsli);
    return False;
 }
 
diff --git a/coregrind/m_debuginfo/readpdb.c b/coregrind/m_debuginfo/readpdb.c
index f78baa6..1994a1c 100644
--- a/coregrind/m_debuginfo/readpdb.c
+++ b/coregrind/m_debuginfo/readpdb.c
@@ -50,6 +50,7 @@
 #include "pub_core_redir.h"
 
 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
+#include "priv_image.h"
 #include "priv_d3basics.h"
 #include "priv_storage.h"
 #include "priv_readpdb.h"          // self
diff --git a/coregrind/m_debuginfo/readstabs.c b/coregrind/m_debuginfo/readstabs.c
index 82e9882..9955627 100644
--- a/coregrind/m_debuginfo/readstabs.c
+++ b/coregrind/m_debuginfo/readstabs.c
@@ -46,6 +46,7 @@
 #include "pub_core_libcprint.h"
 #include "pub_core_xarray.h"
 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
+#include "priv_image.h"
 #include "priv_tytypes.h"
 #include "priv_d3basics.h"
 #include "priv_storage.h"
diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
index 43e4a8f..ef70913 100644
--- a/coregrind/m_debuginfo/storage.c
+++ b/coregrind/m_debuginfo/storage.c
@@ -47,6 +47,7 @@
 #include "pub_core_oset.h"
 
 #include "priv_misc.h"         /* dinfo_zalloc/free/strdup */
+#include "priv_image.h"
 #include "priv_d3basics.h"     /* ML_(pp_GX) */
 #include "priv_tytypes.h"
 #include "priv_storage.h"      /* self */
@@ -249,6 +250,21 @@
 }
 
 
+/* Add a string to the string table of a DebugInfo, by copying the
+   string from the given DiCursor.  Measures the length of the string
+   itself. */
+HChar* ML_(addStrFromCursor)( struct _DebugInfo* di, DiCursor c )
+{
+   /* This is a less-than-stellar implementation, but it should
+      work. */
+   vg_assert(ML_(cur_is_valid)(c));
+   HChar* str = ML_(cur_read_strdup)(c, "di.addStrFromCursor.1");
+   HChar* res = ML_(addStr)(di, str, -1);
+   ML_(dinfo_free)(str);
+   return res;
+}
+
+
 /* Add a symbol to the symbol table, by copying *sym.  'sym' may only
    have one name, so there's no complexities to do with deep vs
    shallow copying of the sec_name array.  This is checked.
diff --git a/coregrind/m_libcbase.c b/coregrind/m_libcbase.c
index 59396d7..5e3fc80 100644
--- a/coregrind/m_libcbase.c
+++ b/coregrind/m_libcbase.c
@@ -556,8 +556,24 @@
       d = (UChar*)dI;
    }
 
-   while (sz--)
-      *d++ = *s++;
+   /* If we're unlucky, the alignment constraints for the fast case
+      above won't apply, and we'll have to to it all here.  Hence the
+      unrolling. */
+   while (sz >= 4) {
+      d[0] = s[0];
+      d[1] = s[1];
+      d[2] = s[2];
+      d[3] = s[3];
+      d += 4;
+      s += 4;
+      sz -= 4;
+   }
+   while (sz >= 1) {
+      d[0] = s[0];
+      d += 1;
+      s += 1;
+      sz -= 1;
+   }
 
    return dest;
 }
@@ -826,6 +842,168 @@
    return *pSeed;
 }
 
+
+/* The following Adler-32 checksum code is taken from zlib-1.2.3, which
+   has the following copyright notice. */
+/*
+Copyright notice:
+
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind.  The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes. Please
+read the FAQ for more information on the distribution of modified source
+versions.
+*/
+
+/* Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum. An Adler-32 checksum is
+   almost as reliable as a CRC32 but can be computed much faster. */
+UInt VG_(adler32)( UInt adler, const UChar* buf, UInt len )
+{
+#  define BASE 65521UL    /* largest prime smaller than 65536 */
+#  define NMAX 5552
+   /* NMAX is the largest n such that 
+      255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#  define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
+#  define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#  define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#  define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#  define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+   /* The zlib sources recommend this definition of MOD if the
+      processor cannot do integer division in hardware. */
+#  define MOD(a) \
+      do { \
+          if (a >= (BASE << 16)) a -= (BASE << 16); \
+          if (a >= (BASE << 15)) a -= (BASE << 15); \
+          if (a >= (BASE << 14)) a -= (BASE << 14); \
+          if (a >= (BASE << 13)) a -= (BASE << 13); \
+          if (a >= (BASE << 12)) a -= (BASE << 12); \
+          if (a >= (BASE << 11)) a -= (BASE << 11); \
+          if (a >= (BASE << 10)) a -= (BASE << 10); \
+          if (a >= (BASE << 9)) a -= (BASE << 9); \
+          if (a >= (BASE << 8)) a -= (BASE << 8); \
+          if (a >= (BASE << 7)) a -= (BASE << 7); \
+          if (a >= (BASE << 6)) a -= (BASE << 6); \
+          if (a >= (BASE << 5)) a -= (BASE << 5); \
+          if (a >= (BASE << 4)) a -= (BASE << 4); \
+          if (a >= (BASE << 3)) a -= (BASE << 3); \
+          if (a >= (BASE << 2)) a -= (BASE << 2); \
+          if (a >= (BASE << 1)) a -= (BASE << 1); \
+          if (a >= BASE) a -= BASE; \
+      } while (0)
+#  define MOD4(a) \
+      do { \
+          if (a >= (BASE << 4)) a -= (BASE << 4); \
+          if (a >= (BASE << 3)) a -= (BASE << 3); \
+          if (a >= (BASE << 2)) a -= (BASE << 2); \
+          if (a >= (BASE << 1)) a -= (BASE << 1); \
+          if (a >= BASE) a -= BASE; \
+      } while (0)
+
+    UInt sum2;
+    UInt n;
+
+    /* split Adler-32 into component sums */
+    sum2 = (adler >> 16) & 0xffff;
+    adler &= 0xffff;
+
+    /* in case user likes doing a byte at a time, keep it fast */
+    if (len == 1) {
+        adler += buf[0];
+        if (adler >= BASE)
+            adler -= BASE;
+        sum2 += adler;
+        if (sum2 >= BASE)
+            sum2 -= BASE;
+        return adler | (sum2 << 16);
+    }
+
+    /* initial Adler-32 value (deferred check for len == 1 speed) */
+    if (buf == NULL)
+        return 1L;
+
+    /* in case short lengths are provided, keep it somewhat fast */
+    if (len < 16) {
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        if (adler >= BASE)
+            adler -= BASE;
+        MOD4(sum2);             /* only added so many BASE's */
+        return adler | (sum2 << 16);
+    }
+
+    /* do length NMAX blocks -- requires just one modulo operation */
+    while (len >= NMAX) {
+        len -= NMAX;
+        n = NMAX / 16;          /* NMAX is divisible by 16 */
+        do {
+            DO16(buf);          /* 16 sums unrolled */
+            buf += 16;
+        } while (--n);
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* do remaining bytes (less than NMAX, still just one modulo) */
+    if (len) {                  /* avoid modulos if none remaining */
+        while (len >= 16) {
+            len -= 16;
+            DO16(buf);
+            buf += 16;
+        }
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* return recombined sums */
+    return adler | (sum2 << 16);
+
+#  undef MOD4
+#  undef MOD
+#  undef DO16
+#  undef DO8
+#  undef DO4
+#  undef DO2
+#  undef DO1
+#  undef NMAX
+#  undef BASE
+}
+
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
index 5ba7b3a..ebf9594 100644
--- a/coregrind/m_libcfile.c
+++ b/coregrind/m_libcfile.c
@@ -1069,6 +1069,42 @@
 }
 
 
+Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
+                      Int optlen)
+{
+#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
+      || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
+   SysRes res;
+   UWord  args[5];
+   args[0] = sd;
+   args[1] = level;
+   args[2] = optname;
+   args[3] = (UWord)optval;
+   args[4] = (UWord)optlen;
+   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
+   return sr_isError(res) ? -1 : sr_Res(res);
+
+#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
+   SysRes res;
+   res = VG_(do_syscall5)( __NR_setsockopt,
+                           (UWord)sd, (UWord)level, (UWord)optname, 
+                           (UWord)optval, (UWord)optlen );
+   return sr_isError(res) ? -1 : sr_Res(res);
+
+#  elif defined(VGO_darwin)
+   SysRes res;
+   res = VG_(do_syscall5)( __NR_setsockopt,
+                           (UWord)sd, (UWord)level, (UWord)optname, 
+                           (UWord)optval, (UWord)optlen );
+   return sr_isError(res) ? -1 : sr_Res(res);
+
+#  else
+#    error "Unknown platform"
+#  endif
+}
+
+
 const HChar *VG_(basename)(const HChar *path)
 {
    static HChar buf[VKI_PATH_MAX];
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index 89c8eda..8953af1 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -176,6 +176,11 @@
 "    --extra-debuginfo-path=path    absolute path to search for additional\n"
 "                              debug symbols, in addition to existing default\n"
 "                              well known search paths.\n"
+"    --debuginfo-server=ipaddr:port    also query this server\n"
+"                              (valgrind-di-server) for debug symbols\n"
+"    --allow-mismatched-debuginfo=no|yes  [no]\n"
+"                              for the above two flags only, accept debuginfo\n"
+"                              objects that don't \"match\" the main object\n"
 "    --smc-check=none|stack|all|all-non-file [stack]\n"
 "                              checks for self-modifying code: none, only for\n"
 "                              code found in stacks, for all code, or for all\n"
@@ -257,7 +262,7 @@
 "       0000 0010   show after reg-alloc\n"
 "       0000 0001   show final assembly\n"
 "       0000 0000   show summary profile only\n"
-"      (Nb: you need --trace-notbelow and/or --trace-notabove "
+"      (Nb: you need --trace-notbelow and/or --trace-notabove\n"
 "           with --trace-flags for full details)\n"
 "\n"
 "  debugging options for Valgrind tools that report errors\n"
@@ -676,6 +681,12 @@
          xml_to = VgLogTo_Socket;
       }
 
+      else if VG_STR_CLO(arg, "--debuginfo-server",
+                              VG_(clo_debuginfo_server)) {}
+
+      else if VG_BOOL_CLO(arg, "--allow-mismatched-debuginfo",
+                               VG_(clo_allow_mismatched_debuginfo)) {}
+
       else if VG_STR_CLO(arg, "--xml-user-comment",
                               VG_(clo_xml_user_comment)) {}
 
diff --git a/coregrind/m_options.c b/coregrind/m_options.c
index dbdb124..b8e3cac 100644
--- a/coregrind/m_options.c
+++ b/coregrind/m_options.c
@@ -80,6 +80,8 @@
 Int    VG_(clo_n_fullpath_after) = 0;
 const HChar* VG_(clo_fullpath_after)[VG_CLO_MAX_FULLPATH_AFTER];
 const HChar* VG_(clo_extra_debuginfo_path) = NULL;
+const HChar* VG_(clo_debuginfo_server) = NULL;
+Bool   VG_(clo_allow_mismatched_debuginfo) = False;
 UChar  VG_(clo_trace_flags)    = 0; // 00000000b
 Bool   VG_(clo_profyle_sbs)    = False;
 UChar  VG_(clo_profyle_flags)  = 0; // 00000000b
diff --git a/coregrind/pub_core_libcfile.h b/coregrind/pub_core_libcfile.h
index a30ff3d..430b537 100644
--- a/coregrind/pub_core_libcfile.h
+++ b/coregrind/pub_core_libcfile.h
@@ -70,6 +70,8 @@
 extern Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen );
 extern Int VG_(getsockopt)  ( Int sd, Int level, Int optname, 
                               void *optval, Int *optlen );
+extern Int VG_(setsockopt)  ( Int sd, Int level, Int optname,
+                              void *optval, Int optlen );
 
 extern Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr,
                                             Bool ixusr );
diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h
index f1dd80a..58e19dd 100644
--- a/coregrind/pub_core_options.h
+++ b/coregrind/pub_core_options.h
@@ -129,6 +129,18 @@
 /* Full path to additional path to search for debug symbols */
 extern const HChar* VG_(clo_extra_debuginfo_path);
 
+/* Address of a debuginfo server to use.  Either an IPv4 address of
+   the form "d.d.d.d" or that plus a port spec, hence of the form
+   "d.d.d.d:d", where d is one or more digits. */
+extern const HChar* VG_(clo_debuginfo_server);
+
+/* Do we allow reading debuginfo from debuginfo objects that don't
+   match (in some sense) the main object?  This is dangerous, so the
+   default is NO (False).  In any case it applies only to objects
+   found either in _extra_debuginfo_path or via the
+   _debuginfo_server. */
+extern Bool VG_(clo_allow_mismatched_debuginfo);
+
 /* DEBUG: print generated code?  default: 00000000 ( == NO ) */
 extern UChar VG_(clo_trace_flags);