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/auxprogs/Makefile.am b/auxprogs/Makefile.am
index 074d8f6..a9f4b03 100644
--- a/auxprogs/Makefile.am
+++ b/auxprogs/Makefile.am
@@ -21,10 +21,11 @@
primes.c
#----------------------------------------------------------------------------
-# valgrind_listener (built for the primary target only)
+# valgrind_listener (built for the primary target only)
+# valgrind-di-server (ditto)
#----------------------------------------------------------------------------
-bin_PROGRAMS = valgrind-listener
+bin_PROGRAMS = valgrind-listener valgrind-di-server
valgrind_listener_SOURCES = valgrind-listener.c
valgrind_listener_CPPFLAGS = $(AM_CPPFLAGS_PRI) -I$(top_srcdir)/coregrind
@@ -37,3 +38,15 @@
if VGCONF_PLATFORMS_INCLUDE_X86_DARWIN
valgrind_listener_LDFLAGS += -Wl,-read_only_relocs -Wl,suppress
endif
+
+valgrind_di_server_SOURCES = valgrind-di-server.c
+valgrind_di_server_CPPFLAGS = $(AM_CPPFLAGS_PRI) -I$(top_srcdir)/coregrind
+valgrind_di_server_CFLAGS = $(AM_CFLAGS_PRI)
+valgrind_di_server_CCASFLAGS = $(AM_CCASFLAGS_PRI)
+valgrind_di_server_LDFLAGS = $(AM_CFLAGS_PRI)
+if VGCONF_PLATVARIANT_IS_ANDROID
+valgrind_di_server_CFLAGS += -static
+endif
+if VGCONF_PLATFORMS_INCLUDE_X86_DARWIN
+valgrind_di_server_LDFLAGS += -Wl,-read_only_relocs -Wl,suppress
+endif
diff --git a/auxprogs/valgrind-di-server.c b/auxprogs/valgrind-di-server.c
new file mode 100644
index 0000000..06dfdf8
--- /dev/null
+++ b/auxprogs/valgrind-di-server.c
@@ -0,0 +1,1224 @@
+
+/*--------------------------------------------------------------------*/
+/*--- A simple debuginfo server for Valgrind. ---*/
+/*--- valgrind-di-server.c ---*/
+/*--------------------------------------------------------------------*/
+
+/* To build for an x86_64-linux host:
+ gcc -g -Wall -O -o valgrind-di-server \
+ auxprogs/valgrind-di-server.c -Icoregrind -Iinclude \
+ -IVEX/pub -DVGO_linux -DVGA_amd64
+
+ To build for an x86 (32-bit) host
+ The same, except change -DVGA_amd64 to -DVGA_x86
+*/
+
+/*
+ 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> */
+
+/* This code works (just), but it's a mess. Cleanups (also for
+ coregrind/m_debuginfo/image.c):
+
+ * Build this file for the host arch, not the target. But how?
+ Even Tromey had difficulty figuring out how to do that.
+
+ * Change the use of pread w/ fd to FILE*, for the file we're
+ serving. Or, at least, put a loop around the pread uses
+ so that it works correctly in the case where pread reads more
+ than zero but less than we asked for.
+
+ * CRC3 request/response: pass session-IDs back and forth and
+ check them
+
+ * Check that all error cases result in a FAIL frame being returned.
+
+ * image.c: don't assert in cases where a FAIL frame is returned;
+ instead cause the debuginfo reading to fail gracefully. (Not
+ sure how to do this)
+
+ * Improve diagnostic printing
+
+ * image.c: do we need to do VG_(write_socket) ? Will it work
+ just to use ordinary VG_(write) ?
+
+ * Both files: document the reason for setting TCP_NODELAY
+
+ * Add a command line argument saying where the served-from
+ directory is -- changes clo_serverpath.
+
+ * Fix up (common up) massive code duplication between client and
+ server.
+
+ * Tidy up the LZO source files; integrate properly in the build
+ system.
+*/
+
+/*---------------------------------------------------------------*/
+
+/* Include valgrind headers before system headers to avoid problems
+ with the system headers #defining things which are used as names
+ of structure members in vki headers. */
+
+#include "pub_core_basics.h"
+#include "pub_core_libcassert.h" // For VG_BUGS_TO
+#include "pub_core_vki.h" // Avoids warnings from
+ // pub_core_libcfile.h
+#include "pub_core_libcfile.h" // For VG_CLO_DEFAULT_LOGPORT
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+#include <netinet/tcp.h>
+
+#include "../coregrind/m_debuginfo/minilzo.h"
+
+/*---------------------------------------------------------------*/
+
+/* The maximum allowable number concurrent connections. */
+#define M_CONNECTIONS 50
+
+static const char* clo_serverpath = ".";
+
+
+/*---------------------------------------------------------------*/
+
+__attribute__ ((noreturn))
+static void panic ( const char* str )
+{
+ fprintf(stderr,
+ "\nvalgrind-di-server: the "
+ "'impossible' happened:\n %s\n", str);
+ fprintf(stderr,
+ "Please report this bug at: %s\n\n", VG_BUGS_TO);
+ exit(1);
+}
+
+__attribute__ ((noreturn))
+static void my_assert_fail ( const char* expr, const char* file, int line, const char* fn )
+{
+ fprintf(stderr,
+ "\nvalgrind-di-server: %s:%d (%s): Assertion '%s' failed.\n",
+ file, line, fn, expr );
+ fprintf(stderr,
+ "Please report this bug at: %s\n\n", VG_BUGS_TO);
+ exit(1);
+}
+
+#undef assert
+
+#define assert(expr) \
+ ((void) ((expr) ? 0 : \
+ (my_assert_fail (VG_STRINGIFY(expr), \
+ __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__), 0)))
+
+
+/*---------------------------------------------------------------*/
+
+/* Holds the state that we need to track, for each connection. */
+typedef
+ struct {
+ // is this entry in use?
+ Bool in_use;
+ // socket descriptor to communicate with client. Initialised as
+ // soon as this entry is created.
+ int conn_sd;
+ // fd for the file that we are connected to. Zero if not
+ // currently connected to any file.
+ int file_fd;
+ ULong file_size;
+ // Session ID
+ ULong session_id;
+ // How many bytes and chunks sent?
+ ULong stats_n_rdok_frames;
+ ULong stats_n_read_unz_bytes; // bytes via READ (uncompressed)
+ ULong stats_n_read_z_bytes; // bytes via READ (compressed)
+ }
+ ConnState;
+
+/* The state itself. */
+static int conn_count = 0;
+static ConnState conn_state[M_CONNECTIONS];
+
+/* Issues unique session ID values. */
+static ULong next_session_id = 1;
+
+
+/*---------------------------------------------------------------*/
+
+// Code that is duplicated with the client :-(
+
+/* 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. */
+static
+UInt 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
+}
+
+
+/* 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;
+}
+
+static Frame* mk_Frame_asciiz ( const char* tag, const char* str )
+{
+ assert(strlen(tag) == 4);
+ Frame* f = calloc(sizeof(Frame), 1);
+ size_t n_str = strlen(str);
+ f->n_data = 4 + n_str + 1;
+ f->data = calloc(f->n_data, 1);
+ memcpy(&f->data[0], tag, 4);
+ memcpy(&f->data[4], str, n_str);
+ assert(f->data[4 + n_str] == 0);
+ return f;
+}
+
+static Bool parse_Frame_noargs ( Frame* fr, const HChar* tag )
+{
+ assert(strlen(tag) == 4);
+ if (!fr || !fr->data) return False;
+ if (fr->n_data < 4) return False;
+ if (memcmp(&fr->data[0], tag, 4) != 0) return False;
+ if (fr->n_data != 4) return False;
+ return True;
+}
+
+static Bool parse_Frame_asciiz ( Frame* fr, const HChar* tag,
+ /*OUT*/UChar** str )
+{
+ assert(strlen(tag) == 4);
+ if (!fr || !fr->data) return False;
+ if (fr->n_data < 4) return False;
+ if (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++;
+ }
+ 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 Frame* mk_Frame_le64 ( const HChar* tag, ULong n1 )
+{
+ assert(strlen(tag) == 4);
+ Frame* f = calloc(sizeof(Frame), 1);
+ f->n_data = 4 + 1*8;
+ f->data = calloc(f->n_data, 1);
+ memcpy(&f->data[0], tag, 4);
+ write_ULong_le(&f->data[4 + 0*8], n1);
+ return f;
+}
+
+static Frame* mk_Frame_le64_le64 ( const HChar* tag, ULong n1, ULong n2 )
+{
+ assert(strlen(tag) == 4);
+ Frame* f = calloc(sizeof(Frame), 1);
+ f->n_data = 4 + 2*8;
+ f->data = calloc(f->n_data, 1);
+ memcpy(&f->data[0], tag, 4);
+ write_ULong_le(&f->data[4 + 0*8], n1);
+ write_ULong_le(&f->data[4 + 1*8], n2);
+ return f;
+}
+
+static Bool parse_Frame_le64_le64_le64 ( Frame* fr, const HChar* tag,
+ /*OUT*/ULong* n1, /*OUT*/ULong* n2,
+ /*OUT*/ULong* n3 )
+{
+ assert(strlen(tag) == 4);
+ if (!fr || !fr->data) return False;
+ if (fr->n_data < 4) return False;
+ if (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]);
+ return True;
+}
+
+static Frame* mk_Frame_le64_le64_le64_bytes (
+ const HChar* tag,
+ ULong n1, ULong n2, ULong n3, ULong n_data,
+ /*OUT*/UChar** data )
+{
+ assert(strlen(tag) == 4);
+ Frame* f = calloc(sizeof(Frame), 1);
+ f->n_data = 4 + 3*8 + n_data;
+ f->data = calloc(f->n_data, 1);
+ 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);
+ *data = &f->data[4 + 3*8];
+ return f;
+}
+
+static void free_Frame ( Frame* fr )
+{
+ assert(fr && fr->data);
+ free(fr->data);
+ free(fr);
+}
+
+
+static void set_blocking ( int sd )
+{
+ int res;
+ res = fcntl(sd, F_GETFL);
+ res = fcntl(sd, F_SETFL, res & ~O_NONBLOCK);
+ if (res != 0) {
+ perror("fcntl failed");
+ panic("set_blocking");
+ }
+}
+
+
+#if 0
+static void set_nonblocking ( int sd )
+{
+ int res;
+ res = fcntl(sd, F_GETFL);
+ res = fcntl(sd, F_SETFL, res | O_NONBLOCK);
+ if (res != 0) {
+ perror("fcntl failed");
+ panic("set_nonblocking");
+ }
+}
+#endif
+
+
+/* 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 SizeT my_read ( Int fd, UChar* buf, SizeT len )
+{
+ //set_blocking(fd);
+ SizeT nRead = 0;
+ while (1) {
+ if (nRead == len) return nRead;
+ assert(nRead < len);
+ SizeT nNeeded = len - nRead;
+ assert(nNeeded > 0);
+ SSizeT n = 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 SizeT my_write ( Int fd, UChar* buf, SizeT len )
+{
+ //set_nonblocking(fd);
+ SizeT nWritten = 0;
+ while (1) {
+ if (nWritten == len) return nWritten;
+ assert(nWritten < len);
+ SizeT nStillToDo = len - nWritten;
+ assert(nStillToDo > 0);
+ SSizeT n = write(fd, &buf[nWritten], nStillToDo);
+ if (n < 0) return nWritten; /* error or EOF */
+ nWritten += n;
+ }
+}
+
+
+static UInt calc_gnu_debuglink_crc32(/*OUT*/Bool* ok, int fd, ULong size)
+{
+ 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
+ };
+
+ /* Work through the image in 1 KB chunks. */
+ UInt crc = 0xFFFFFFFF;
+ ULong img_szB = size;
+ ULong curr_off = 0;
+ while (1) {
+ assert(curr_off >= 0 && curr_off <= img_szB);
+ if (curr_off == img_szB) break;
+ ULong avail = img_szB - curr_off;
+ assert(avail > 0 && avail <= img_szB);
+ if (avail > 65536) avail = 65536;
+ UChar buf[65536];
+ Int nRead = pread(fd, buf, avail, curr_off);
+ if (nRead <= 0) { /* EOF or error on the file; neither should happen */
+ *ok = False;
+ return 0;
+ }
+ /* this is a kludge .. we should loop around pread and deal
+ with short reads, for whatever reason */
+ assert(nRead == avail);
+ UInt i;
+ for (i = 0; i < (UInt)nRead; i++)
+ crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
+ curr_off += nRead;
+ }
+ *ok = True;
+ return ~crc & 0xFFFFFFFF;
+ }
+
+
+/*---------------------------------------------------------------*/
+
+/* Handle a transaction for conn_state[conn_no]. There is incoming
+ data available; read it and send back an appropriate response.
+ Returns a boolean indicating whether the connection has been
+ closed; in which case this function does all necessary cleanup and
+ leaves conn_state[conn_no] in a not-in-use state. */
+
+static Bool handle_transaction ( int conn_no )
+{
+ Frame* req = NULL; /* the request frame that we receive */
+ Frame* res = NULL; /* the response frame that we send back */
+
+ assert(conn_no >= 0 && conn_no < M_CONNECTIONS);
+ assert(conn_state[conn_no].in_use);
+
+ //printf("SERVER: handle_transaction(%d)\n", conn_no); fflush(stdout);
+
+ Int sd = conn_state[conn_no].conn_sd;
+
+ /* Get a frame out of the channel. */
+ UChar rd_first8[8]; // adler32; length32
+ { Int r = my_read(sd, &rd_first8[0], 8);
+ if (r == 0) goto client_closed_conn;
+ if (r != 8) goto fail;
+ }
+ 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*1024*1024) goto fail;
+ assert(req == NULL);
+ req = calloc(sizeof(Frame), 1);
+ req->n_data = rd_len;
+ req->data = calloc(rd_len, 1);
+ if (rd_len > 0) {
+ Int r = my_read(sd, req->data, req->n_data);
+ if (r != rd_len) goto fail;
+ }
+//printf("SERVER: recv %c%c%c%c\n", req->data[0], req->data[1], req->data[2], req->data[3]); fflush(stdout);
+
+ /* Compute the checksum for the received data, and check it. */
+ UInt adler = adler32(0, NULL, 0); // initial value
+ adler = adler32(adler, &rd_first8[4], 4);
+ if (req->n_data > 0)
+ adler = adler32(adler, req->data, req->n_data);
+
+ if (adler/*computed*/ != rd_adler/*expected*/) goto fail;
+
+ /* Now we have a request frame. Cook up a response. */
+ assert(res == NULL);
+
+ UChar* filename = NULL;
+ ULong req_session_id = 0, req_offset = 0, req_len = 0;
+
+ if (parse_Frame_noargs(req, "VERS")) {
+ res = mk_Frame_asciiz("VEOK", "Valgrind Debuginfo Server, Version 1");
+ }
+ else
+ if (parse_Frame_noargs(req, "CRC3")) {
+ /* FIXME: add a session ID to this request, and check it */
+ if (conn_state[conn_no].file_fd == 0) {
+ res = mk_Frame_asciiz("CRC3", "FAIL: not connected to file");
+ } else {
+ Bool ok = False;
+ UInt crc32 = calc_gnu_debuglink_crc32(&ok,
+ conn_state[conn_no].file_fd,
+ conn_state[conn_no].file_size);
+ if (ok) {
+ res = mk_Frame_le64("CROK", (ULong)crc32);
+ } else {
+ res = mk_Frame_asciiz("FAIL", "CRC3: I/O error reading file");
+ }
+ }
+ }
+ else
+ if (parse_Frame_asciiz(req, "OPEN", &filename)) {
+ Bool ok = True;
+ int fd = 0;
+ if (conn_state[conn_no].file_fd != 0) {
+ res = mk_Frame_asciiz("FAIL", "OPEN: already connected to file");
+ ok = False;
+ }
+ if (ok) {
+ assert(clo_serverpath);
+ fd = open((char*)filename, O_RDONLY);
+ if (fd == -1) {
+ res = mk_Frame_asciiz("FAIL", "OPEN: cannot open file");
+ ok = False;
+ } else {
+ assert(fd > 2);
+ }
+ }
+ if (ok) {
+ struct stat stat_buf;
+ int r = fstat(fd, &stat_buf);
+ if (r != 0) {
+ res = mk_Frame_asciiz("FAIL", "OPEN: cannot stat file");
+ ok = False;
+ }
+ if (ok && stat_buf.st_size == 0) {
+ res = mk_Frame_asciiz("FAIL", "OPEN: file has zero size");
+ ok = False;
+ }
+ if (ok) {
+ conn_state[conn_no].file_fd = fd;
+ conn_state[conn_no].file_size = stat_buf.st_size;
+ assert(res == NULL);
+ res = mk_Frame_le64_le64("OPOK", conn_state[conn_no].session_id,
+ conn_state[conn_no].file_size);
+ printf("(%d) SessionID %llu: open successful for \"%s\"\n",
+ conn_count, conn_state[conn_no].session_id, filename );
+ fflush(stdout);
+ }
+ }
+ }
+ else
+ if (parse_Frame_le64_le64_le64(req, "READ", &req_session_id,
+ &req_offset, &req_len)) {
+ /* Because each new connection is associated with its own socket
+ descriptor and hence with a particular conn_no, the requested
+ session-ID is redundant -- it must be the one associated with
+ this slot. But check anyway. */
+ Bool ok = True;
+ if (req_session_id != conn_state[conn_no].session_id) {
+ req = mk_Frame_asciiz("FAIL", "READ: invalid session ID");
+ ok = False;
+ }
+ /* Check we're connected to a file, and if so range-check the
+ request. */
+ if (ok && conn_state[conn_no].file_fd == 0) {
+ res = mk_Frame_asciiz("FAIL", "READ: no associated file");
+ ok = False;
+ }
+ if (ok && (req_len == 0 || req_len > 4*1024*1024)) {
+ res = mk_Frame_asciiz("FAIL", "READ: invalid request size");
+ ok = False;
+ }
+ if (ok && req_len + req_offset > conn_state[conn_no].file_size) {
+ res = mk_Frame_asciiz("FAIL", "READ: request exceeds file size");
+ ok = False;
+ }
+ /* Try to read the file. */
+ if (ok) {
+ /* First, allocate a temp buf and read from the file into it. */
+ /* FIXME: what if pread reads short and we have to redo it? */
+ UChar* unzBuf = malloc(req_len);
+ size_t nRead = pread(conn_state[conn_no].file_fd,
+ unzBuf, req_len, req_offset);
+ if (nRead != req_len) {
+ free_Frame(res);
+ res = mk_Frame_asciiz("FAIL", "READ: I/O error reading file");
+ ok = False;
+ } UInt zLen = 0;
+ if (ok) {
+ // Now compress it with LZO. LZO appears to recommend
+ // the worst-case output size as (in_len + in_len / 16 + 67).
+ // Be more conservative here.
+# define STACK_ALLOC(var,size) \
+ lzo_align_t __LZO_MMODEL \
+ var [ ((size) \
+ + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
+ STACK_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS);
+# undef STACK_ALLOC
+ UInt zLenMax = req_len + req_len / 4 + 1024;
+ UChar* zBuf = malloc(zLenMax);
+ zLen = zLenMax;
+ Int lzo_rc = lzo1x_1_compress(unzBuf, req_len,
+ zBuf, (lzo_uint*)&zLen, wrkmem);
+ if (lzo_rc == LZO_E_OK) {
+ //printf("XXXXX req_len %u zLen %u\n", (UInt)req_len, (UInt)zLen);
+ assert(zLen <= zLenMax);
+ /* Make a frame to put the results in. Bytes 24 and
+ onwards need to be filled from the compressed data,
+ and 'buf' is set to point to the right bit. */
+ UChar* buf = NULL;
+ res = mk_Frame_le64_le64_le64_bytes
+ ("RDOK", req_session_id, req_offset, req_len, zLen, &buf);
+ assert(res);
+ assert(buf);
+ memcpy(buf, zBuf, zLen);
+ // Update stats
+ conn_state[conn_no].stats_n_rdok_frames++;
+ conn_state[conn_no].stats_n_read_unz_bytes += req_len;
+ conn_state[conn_no].stats_n_read_z_bytes += zLen;
+ } else {
+ ok = False;
+ free_Frame(res);
+ res = mk_Frame_asciiz("FAIL", "READ: LZO failed");
+ }
+ free(zBuf);
+ }
+ free(unzBuf);
+ }
+ }
+ else {
+ res = mk_Frame_asciiz("FAIL", "Invalid request frame type");
+ }
+
+ /* All paths through the above should result in an assignment to |res|. */
+ assert(res != NULL);
+
+ /* And send the response frame back to the client. */
+ /* 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 */
+ adler = adler32(0, NULL, 0);
+
+ /* Fold in the length field, encoded as le32. */
+ UChar wr_first8[8];
+ write_UInt_le(&wr_first8[4], res->n_data);
+ adler = adler32(adler, &wr_first8[4], 4);
+ /* Fold in the data values */
+ adler = adler32(adler, res->data, res->n_data);
+ write_UInt_le(&wr_first8[0], adler);
+
+ Int r = my_write(sd, &wr_first8[0], 8);
+ if (r != 8) goto fail;
+ assert(res->n_data >= 4); // else ill formed -- no KIND field
+ r = my_write(sd, res->data, res->n_data);
+ if (r != res->n_data) goto fail;
+
+//printf("SERVER: send %c%c%c%c\n", res->data[0], res->data[1], res->data[2], res->data[3]); fflush(stdout);
+
+ /* So, success. */
+ if (req) free_Frame(req);
+ if (res) free_Frame(res);
+ return False; /* "connection still in use" */
+
+ // Is there any difference between these?
+ client_closed_conn:
+ fail:
+ if (conn_state[conn_no].conn_sd > 0)
+ close(conn_state[conn_no].conn_sd);
+ if (conn_state[conn_no].file_fd > 0)
+ close(conn_state[conn_no].file_fd);
+
+ if (conn_state[conn_no].stats_n_rdok_frames > 0) {
+ printf("(%d) SessionID %llu: sent %llu frames, "
+ "%llu MB (unz), %llu MB (z), ratio %4.2f:1\n",
+ conn_count, conn_state[conn_no].session_id,
+ conn_state[conn_no].stats_n_rdok_frames,
+ conn_state[conn_no].stats_n_read_unz_bytes / 1000000,
+ conn_state[conn_no].stats_n_read_z_bytes / 1000000,
+ (double)conn_state[conn_no].stats_n_read_unz_bytes
+ / (double)conn_state[conn_no].stats_n_read_z_bytes);
+ printf("(%d) SessionID %llu: closed\n",
+ conn_count, conn_state[conn_no].session_id);
+
+ fflush(stdout);
+ }
+
+ memset(&conn_state[conn_no], 0, sizeof(conn_state[conn_no]));
+ if (req) free_Frame(req);
+ if (res) free_Frame(res);
+ return True; /* "connection has been closed" */
+}
+
+
+/*---------------------------------------------------------------*/
+
+
+
+#if 0
+static void copyout ( char* buf, int nbuf )
+{
+ int i;
+ for (i = 0; i < nbuf; i++) {
+ if (buf[i] == '\n') {
+ fprintf(stdout, "\n(%d) ", conn_count);
+ } else {
+ __attribute__((unused)) size_t ignored
+ = fwrite(&buf[i], 1, 1, stdout);
+ }
+ }
+ fflush(stdout);
+}
+
+static int read_from_sd ( int sd )
+{
+ char buf[100];
+ int n;
+
+ set_blocking(sd);
+ n = read(sd, buf, 99);
+ if (n <= 0) return 0; /* closed */
+ copyout(buf, n);
+
+ set_nonblocking(sd);
+ while (1) {
+ n = read(sd, buf, 100);
+ if (n <= 0) return 1; /* not closed */
+ copyout(buf, n);
+ }
+}
+#endif
+
+static void snooze ( void )
+{
+ struct timespec req;
+ req.tv_sec = 0;
+ req.tv_nsec = 200 * 1000 * 1000;
+ nanosleep(&req,NULL);
+}
+
+
+/* returns 0 if invalid, else port # */
+static int atoi_portno ( const char* str )
+{
+ int n = 0;
+ while (1) {
+ if (*str == 0)
+ break;
+ if (*str < '0' || *str > '9')
+ return 0;
+ n = 10*n + (int)(*str - '0');
+ str++;
+ if (n >= 65536)
+ return 0;
+ }
+ if (n < 1024)
+ return 0;
+ return n;
+}
+
+
+static void usage ( void )
+{
+ fprintf(stderr,
+ "\n"
+ "usage is:\n"
+ "\n"
+ " valgrind-di-server [--exit-at-zero|-e] [port-number]\n"
+ "\n"
+ " where --exit-at-zero or -e causes the listener to exit\n"
+ " when the number of connections falls back to zero\n"
+ " (the default is to keep listening forever)\n"
+ "\n"
+ " port-number is the default port on which to listen for\n"
+ " connections. It must be between 1024 and 65535.\n"
+ " Current default is %d.\n"
+ "\n"
+ ,
+ VG_CLO_DEFAULT_LOGPORT
+ );
+ exit(1);
+}
+
+
+static void banner ( const char* str )
+{
+ time_t t;
+ t = time(NULL);
+ printf("valgrind-di-server %s at %s", str, ctime(&t));
+ fflush(stdout);
+}
+
+
+static void exit_routine ( void )
+{
+ banner("exited");
+ exit(0);
+}
+
+
+static void sigint_handler ( int signo )
+{
+ exit_routine();
+}
+
+
+int main (int argc, char** argv)
+{
+ int i, j, res, one;
+ int main_sd, new_sd;
+ socklen_t client_len;
+ struct sockaddr_in client_addr, server_addr;
+
+ char /*bool*/ exit_when_zero = 0;
+ int port = VG_CLO_DEFAULT_LOGPORT;
+
+ for (i = 1; i < argc; i++) {
+ if (0==strcmp(argv[i], "--exit-at-zero")
+ || 0==strcmp(argv[i], "-e")) {
+ exit_when_zero = 1;
+ }
+ else
+ if (atoi_portno(argv[i]) > 0) {
+ port = atoi_portno(argv[i]);
+ }
+ else
+ usage();
+ }
+
+ banner("started");
+ signal(SIGINT, sigint_handler);
+
+ conn_count = 0;
+ memset(&conn_state, 0, sizeof(conn_state));
+
+ /* create socket */
+ main_sd = socket(AF_INET, SOCK_STREAM, 0);
+ if (main_sd < 0) {
+ perror("cannot open socket ");
+ panic("main -- create socket");
+ }
+
+ /* allow address reuse to avoid "address already in use" errors */
+
+ one = 1;
+ if (setsockopt(main_sd, SOL_SOCKET, SO_REUSEADDR,
+ &one, sizeof(one)) < 0) {
+ perror("cannot enable address reuse ");
+ panic("main -- enable address reuse");
+ }
+
+ /* bind server port */
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ server_addr.sin_port = htons(port);
+
+ if (bind(main_sd, (struct sockaddr *) &server_addr,
+ sizeof(server_addr) ) < 0) {
+ perror("cannot bind port ");
+ panic("main -- bind port");
+ }
+
+ res = listen(main_sd, M_CONNECTIONS);
+ if (res != 0) {
+ perror("listen failed ");
+ panic("main -- listen");
+ }
+
+ Bool do_snooze = False;
+ while (1) {
+
+ if (0 && do_snooze)
+ snooze();
+
+ /* Snooze after this iteration, unless something happened. */
+ do_snooze = True;
+
+ /* enquire, using poll, whether there is any activity available on
+ the main socket descriptor. If so, someone is trying to
+ connect; get the fd and add it to our table thereof. */
+ { struct pollfd ufd;
+ while (1) {
+ ufd.fd = main_sd;
+ ufd.events = POLLIN;
+ ufd.revents = 0;
+ res = poll(&ufd, 1, 0/*ms*/ /* 0=return immediately. */);
+ if (res == 0) break;
+
+ /* ok, we have someone waiting to connect. Get the sd. */
+ client_len = sizeof(client_addr);
+ new_sd = accept(main_sd, (struct sockaddr *)&client_addr,
+ &client_len);
+ if (new_sd < 0) {
+ perror("cannot accept connection ");
+ panic("main -- accept connection");
+ }
+
+ /* find a place to put it. */
+ assert(new_sd > 0);
+ for (i = 0; i < M_CONNECTIONS; i++)
+ if (!conn_state[i].in_use)
+ break;
+
+ if (i >= M_CONNECTIONS) {
+ fprintf(stderr, "Too many concurrent connections. "
+ "Increase M_CONNECTIONS and recompile.\n");
+ panic("main -- too many concurrent connections");
+ }
+
+assert(one == 1);
+int ret = setsockopt( new_sd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
+assert(ret != -1);
+
+ memset(&conn_state[i], 0, sizeof(conn_state[i]));
+ conn_state[i].in_use = True;
+ conn_state[i].conn_sd = new_sd;
+ conn_state[i].file_fd = 0; /* not known yet */
+ conn_state[i].session_id = next_session_id++;
+ set_blocking(new_sd);
+ conn_count++;
+ do_snooze = False;
+ } /* while (1) */
+ }
+
+ /* We've processed all new connect requests. Listen for changes
+ to the current set of fds. This requires gathering up all
+ the known conn_sd values and doing poll() on them. */
+ struct pollfd tmp_pollfd[M_CONNECTIONS];
+ /* And a parallel array which maps entries in tmp_pollfd back to
+ entries in conn_state. */
+ int tmp_pollfd_to_conn_state[M_CONNECTIONS];
+ j = 0;
+ for (i = 0; i < M_CONNECTIONS; i++) {
+ if (!conn_state[i].in_use)
+ continue;
+ assert(conn_state[i].conn_sd > 2);
+ tmp_pollfd[j].fd = conn_state[i].conn_sd;
+ tmp_pollfd[j].events = POLLIN /* | POLLHUP | POLLNVAL */;
+ tmp_pollfd[j].revents = 0;
+ tmp_pollfd_to_conn_state[j] = i;
+ j++;
+ }
+
+ res = poll(tmp_pollfd, j, 20/*ms*/ /* 0=return immediately. */ );
+ if (res < 0) {
+ perror("poll(main) failed");
+ panic("poll(main) failed");
+ }
+
+ /* nothing happened. go round again. */
+ if (res == 0) {
+ continue;
+ }
+
+ /* inspect the fds. */
+ for (i = 0; i < j; i++) {
+
+ if (tmp_pollfd[i].revents & POLLIN) {
+ /* We have some activity on tmp_pollfd[i]. We need to
+ figure out which conn_state[] entry that corresponds
+ to, which is what tmp_pollfd_to_conn_state is for. */
+ Int conn_no = tmp_pollfd_to_conn_state[i];
+ Bool finished = handle_transaction(conn_no);
+ if (finished) {
+ /* this connection has been closed or otherwise gone
+ bad; forget about it. */
+ conn_count--;
+ fflush(stdout);
+ if (conn_count == 0 && exit_when_zero) {
+ if (0) printf("\n");
+ fflush(stdout);
+ exit_routine();
+ }
+ } else {
+ // maybe show stats
+ if (conn_state[i].stats_n_rdok_frames > 0
+ && (conn_state[i].stats_n_rdok_frames % 1000) == 0) {
+ printf("(%d) SessionID %llu: sent %llu frames, "
+ "%llu MB (unz), %llu MB (z)\n",
+ conn_count, conn_state[conn_no].session_id,
+ conn_state[conn_no].stats_n_rdok_frames,
+ conn_state[conn_no].stats_n_read_unz_bytes / 1000000,
+ conn_state[conn_no].stats_n_read_z_bytes / 1000000);
+ fflush(stdout);
+ }
+ }
+ }
+
+ } /* for (i = 0; i < j; i++) */
+
+ do_snooze = False;
+
+ } /* while (1) */
+
+ /* NOTREACHED */
+}
+
+////////////////////////////////////////////////////
+#include "../coregrind/m_debuginfo/minilzo-inl.c"
+
+/*--------------------------------------------------------------------*/
+/*--- end valgrind-di-server.c ---*/
+/*--------------------------------------------------------------------*/
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)(¬e, 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)(¬e, 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)(§, §s_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);
diff --git a/include/pub_tool_libcbase.h b/include/pub_tool_libcbase.h
index ba1dd0c..05d6bfd 100644
--- a/include/pub_tool_libcbase.h
+++ b/include/pub_tool_libcbase.h
@@ -194,6 +194,12 @@
extern UInt VG_(random) ( /*MOD*/UInt* pSeed );
#define VG_RAND_MAX (1ULL << 32)
+/* 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. */
+extern UInt VG_(adler32)( UInt adler, const UChar* buf, UInt len);
+
#endif // __PUB_TOOL_LIBCBASE_H
/*--------------------------------------------------------------------*/
diff --git a/include/vki/vki-darwin.h b/include/vki/vki-darwin.h
index d87a72a..6c4b559 100644
--- a/include/vki/vki-darwin.h
+++ b/include/vki/vki-darwin.h
@@ -1041,6 +1041,16 @@
#define vki_aiocb aiocb
+#include <netinet/tcp.h>
+
+#define VKI_TCP_NODELAY TCP_NODELAY
+
+
+#include <netinet/in.h>
+
+#define VKI_IPPROTO_TCP IPPROTO_TCP
+
+
// XXX: for some reason when I #include <sys/kernel_types.h> I get a syntax
// error. Hmm. So just define things ourselves.
//#include <sys/kernel_types.h>
diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h
index 08ab138..c9aa047 100644
--- a/include/vki/vki-linux.h
+++ b/include/vki/vki-linux.h
@@ -702,6 +702,8 @@
sizeof(unsigned short int) - sizeof(struct vki_in_addr)];
};
+#define VKI_IPPROTO_TCP 6 /* Transmission Control Protocol */
+
//----------------------------------------------------------------------
// From linux-2.6.8.1/include/linux/in6.h
//----------------------------------------------------------------------
@@ -728,6 +730,13 @@
};
//----------------------------------------------------------------------
+// From linux-2.6.8.1/include/linux/tcp.h
+//----------------------------------------------------------------------
+
+#define VKI_TCP_NODELAY 1 /* Turn off Nagle's algorithm. */
+
+
+//----------------------------------------------------------------------
// From linux-2.6.8.1/include/linux/un.h
//----------------------------------------------------------------------