* google-perftools: version 0.93 release
	* PORTING: everything compiles on Solaris, OS X, FreeBSD (see INSTALL)
	* PORTING: cpu-profiler works on most platforms (much better GetPC())
	* PORTING: heap-profiler works on most platforms
	* PORTING: improved windows support, including release builds
	* No longer build or run ptmalloc tests by default
	* Add support for using memfs filesystem to allocate memory in linux
	* WINDOWS: give debug library and release library different names
	
Tue Jul 17 22:26:27 2007  Google Inc. <opensource@google.com>


git-svn-id: http://gperftools.googlecode.com/svn/trunk@38 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
diff --git a/ChangeLog b/ChangeLog
index 9075474..0127ff1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,105 +1,33 @@
-Tue Feb 8 09:57:17 2005  Google Inc. <opensource@google.com>
+Fri Aug 17 12:32:56 2007  Google Inc. <opensource@google.com>
 
-	* google-perftools: initial release:
-	  The google-perftools package contains some utilities to improve
-	  and analyze the performance of C++ programs.  This includes an
-	  optimized thread-caching malloc() and cpu and heap profiling
-	  utilities.
+	* google-perftools: version 0.93 release
+	* PORTING: everything compiles on Solaris, OS X, FreeBSD (see INSTALL)
+	* PORTING: cpu-profiler works on most platforms (much better GetPC())
+	* PORTING: heap-profiler works on most platforms
+	* PORTING: improved windows support, including release builds
+	* No longer build or run ptmalloc tests by default
+	* Add support for using memfs filesystem to allocate memory in linux
+	* WINDOWS: give debug library and release library different names
+	
+Tue Jul 17 22:26:27 2007  Google Inc. <opensource@google.com>
 
-Tue May 31 08:14:38 2005  Google Inc. <opensource@google.com>
+	* google-perftools: version 0.92 release
+	* PERFORMANCE: use a packed cache to speed up tcmalloc
+	* PORTING: preliminary windows support! (see README.windows)
+	* PORTING: better support for solaris, OS X, FreeBSD (see INSTALL)
+	* Envvar support for running the heap-checker under gdb
+	* Add weak declarations to maybe_threads to fix no-pthreads compile bugs
+	* Some 64bit fixes, especially with pprof
+	* Better heap-checker support for some low-level allocations
+	* Fix bug where heap-profiles would sometimes get truncated
+	* New documentation about how to handle common heap leak situations
+	* Use computed includes for hash_map/set: easier config
+	* Added all used .m4 templates to the distribution
 
-	* google-perftools: version 0.2 release
-	* Use mmap2() instead of mmap(), to map more memory (menage)
-	* Do correct pthread-local checking in heap-checker! (maxim)
-	* Avoid overflow on 64-bit machines in pprof (sanjay)
-	* Add a few more GetPC() functions, including for AMD (csilvers)
-	* Better method for overriding pthread functions (menage)
-	* (Hacky) fix to avoid overwriting profile files after fork() (csilvers)
-	* Crashing bugfix involving dumping heaps on small-stack threads (tudor)
-	* Allow library versions with letters at the end (csilvers)
-	* Config fixes for systems that don't define PATH_MAX (csilvers)
-	* Confix fixes so we no longer need config.h after install (csilvers)
-	* Fix to pprof to correctly read very big cpu profiles (csilvers)
-	* Fix to pprof to deal with new commandline flags in modern gv's
-	* Better error reporting when we can't access /proc/maps (etune)
-	* Get rid of the libc-preallocate code (which could crash on some
-	  systems); no longer needed with local-threads fix (csilvers)
+Wed Apr 18 16:43:55 2007  Google Inc. <opensource@google.com>
 
-Fri Jun 24 18:02:26 2005  Google Inc. <opensource@google.com>
-
-	* google-perftools: version 0.3 release
-	* Add missing errno include for one of the unittests (csilvers)
-	* Reduce tcmalloc startup memory from 5M to 256K (sanjay)
-	* Add support for mallopt() and mallinfo (sanjay)
-	* Improve stacktrace's performance on some 64-bit systems (etune)
-	* Improve the stacktrace unittest (etune)
-
-Wed Oct 26 15:19:16 2005  Google Inc. <opensource@google.com>
-
-	* google-perftools: version 0.4 release
-	* Decrease fragmentation in tcmalloc (lefevere)
-	* Support for ARM in some of the thread-specific code (markus)
-	* Turn off heap-checker for statically-linked binaries, which
-	  cause error leak reports now (etune)
-	* Many pprof improvements, including a command-line interface (jeff)
-	* CPU profiling now automatically affects all threads in linux 2.6.
-	  (Kernel bugs break CPU profiling and threads in linux 2.4 a bit.)
-	  ProfilerEnable() and ProfilerDisable() are deprecated.  (sanjay)
-	* tcmalloc now correctly intercepts memalign (m3b, maxim)
-	* Syntax fix: added missing va_end()s.  Helps non-gcc compiling (etune)
-	* Fixed a few coredumper bugs: race condition after PTRACE_DETACH,
-	  ignore non-aligned stackframe pointers (markus, menage)
-	* 64-bit cleanup, especially for spinlock code (etune) and mmap (sanjay)
-	* Better support for finding threads in linux (markus)
-	* tcmalloc now tracks those stack traces that allocate memory (sanjay)
-	* Work around a weird setspecific problem (sanjay)
-	* Fix tcmalloc overflow problems when an alloc is close to 2G/4G (sanjay)
-
-Mon Nov 14 17:28:59 2005  Google Inc. <opensource@google.com>
-
-	* google-perftools: version 0.5 release
-	* Add va_start/va_end calls around vsnprintf() (csilvers)
-	* Write our own __syscall_return(), since it's not defined
-	  consistently on all 64-bit linux distros (markus)
-
-Fri Jan 27 14:04:27 2006  Google Inc. <opensource@google.com>
-
-	* google-perftools: version 0.6 release
-	* More sophisticated stacktrace usage, possibly using libunwind (aruns)
-	* Update pprof to handle 64-bit profiles (dehnert)
-	* Fix GetStackTrace to correctly return top stackframe (sanjay)
-	* Add ANSI compliance for new and new[], including new_handler (jkearney)
-	* More accuracy by reading ELF files directly rather than objdump (mec)
-	* Add readline support for pprof (addi)
-	* Add #includes for PPC (csilvers)
-	* New PC-detection routine for ibook powerpc (asbestoshead)
-	* Vastly improved tcmalloc unittest (csilvers)
-	* Move documentation from /usr/doc to /usr/share/doc
-
-Thu Apr 13 20:59:09 2006  Google Inc. <opensource@google.com>
-
-	* google-perftools: version 0.7 release
-	* Major rewrite of thread introspection for new kernels (markus)
-	* Major rewrite of heap-checker to use new thread tools (maxim)
-	* Add proper support for following data in thread registers (maxim)
-	* Syscall support for older kernels, including _syscall6 (markus)
-	* Support PIC mode (markus, mbland, iant)
-	* Better support for running in non-threaded contexts (csilvers)
-
-Wed Jun 14 15:11:14 2006  Google Inc. <opensource@google.com>
-
-	* google-perftools: version 0.8 release
-	* Experimental support for remote profiling added to pprof (many)
-	* Fixed race condition in ProfileData::FlushTable (etune)
-	* Better support for weird /proc maps (maxim, mec)
-	* Fix heap-checker interaction with gdb (markus)
-	* Better 64-bit support in pprof (aruns)
-	* Reduce scavenging cost in tcmalloc by capping NumMoveSize (sanjay)
-	* Cast syscall(SYS_mmap); works on more 64-bit systems now (menage)
-	* Document the text output of pprof! (csilvers)
-	* Better compiler support for no-THREADS and for old compilers (csilvers)
-	* Make libunwind the default stack unwinder for x86-64 (aruns)
-	* Somehow the COPYING file got erased.  Regenerate it (csilvers)
+	* google-perftools: version 0.91 release
+	* Brown-paper-bag bugfix: compilation error on some x86-64 machines
 
 Fri Apr 13 14:50:51 2007  Google Inc. <opensource@google.com>
 
@@ -127,22 +55,105 @@
 	* CPU-profiling may crash on x86_64 (64-bit) systems.  See the README
 	* Profiling/heap-checking may deadlock on x86_64 systems.  See README
 
-Wed Apr 18 16:43:55 2007  Google Inc. <opensource@google.com>
+Wed Jun 14 15:11:14 2006  Google Inc. <opensource@google.com>
 
-	* google-perftools: version 0.91 release
-	* Brown-paper-bag bugfix: compilation error on some x86-64 machines
+	* google-perftools: version 0.8 release
+	* Experimental support for remote profiling added to pprof (many)
+	* Fixed race condition in ProfileData::FlushTable (etune)
+	* Better support for weird /proc maps (maxim, mec)
+	* Fix heap-checker interaction with gdb (markus)
+	* Better 64-bit support in pprof (aruns)
+	* Reduce scavenging cost in tcmalloc by capping NumMoveSize (sanjay)
+	* Cast syscall(SYS_mmap); works on more 64-bit systems now (menage)
+	* Document the text output of pprof! (csilvers)
+	* Better compiler support for no-THREADS and for old compilers (csilvers)
+	* Make libunwind the default stack unwinder for x86-64 (aruns)
+	* Somehow the COPYING file got erased.  Regenerate it (csilvers)
 
-Tue Jul 17 22:26:27 2007  Google Inc. <opensource@google.com>
+Thu Apr 13 20:59:09 2006  Google Inc. <opensource@google.com>
 
-	* google-perftools: version 0.92 release
-	* PERFORMANCE: use a packed cache to speed up tcmalloc
-	* PORTING: preliminary windows support! (see README.windows)
-	* PORTING: better support for solaris, OS X, FreeBSD (see INSTALL)
-	* Envvar support for running the heap-checker under gdb
-	* Add weak declarations to maybe_threads to fix no-pthreads compile bugs
-	* Some 64bit fixes, especially with pprof
-	* Better heap-checker support for some low-level allocations
-	* Fix bug where heap-profiles would sometimes get truncated
-	* New documentation about how to handle common heap leak situations
-	* Use computed includes for hash_map/set: easier config
-	* Added all used .m4 templates to the distribution
+	* google-perftools: version 0.7 release
+	* Major rewrite of thread introspection for new kernels (markus)
+	* Major rewrite of heap-checker to use new thread tools (maxim)
+	* Add proper support for following data in thread registers (maxim)
+	* Syscall support for older kernels, including _syscall6 (markus)
+	* Support PIC mode (markus, mbland, iant)
+	* Better support for running in non-threaded contexts (csilvers)
+
+Fri Jan 27 14:04:27 2006  Google Inc. <opensource@google.com>
+
+	* google-perftools: version 0.6 release
+	* More sophisticated stacktrace usage, possibly using libunwind (aruns)
+	* Update pprof to handle 64-bit profiles (dehnert)
+	* Fix GetStackTrace to correctly return top stackframe (sanjay)
+	* Add ANSI compliance for new and new[], including new_handler (jkearney)
+	* More accuracy by reading ELF files directly rather than objdump (mec)
+	* Add readline support for pprof (addi)
+	* Add #includes for PPC (csilvers)
+	* New PC-detection routine for ibook powerpc (asbestoshead)
+	* Vastly improved tcmalloc unittest (csilvers)
+	* Move documentation from /usr/doc to /usr/share/doc
+
+Mon Nov 14 17:28:59 2005  Google Inc. <opensource@google.com>
+
+	* google-perftools: version 0.5 release
+	* Add va_start/va_end calls around vsnprintf() (csilvers)
+	* Write our own __syscall_return(), since it's not defined
+	  consistently on all 64-bit linux distros (markus)
+
+Wed Oct 26 15:19:16 2005  Google Inc. <opensource@google.com>
+
+	* google-perftools: version 0.4 release
+	* Decrease fragmentation in tcmalloc (lefevere)
+	* Support for ARM in some of the thread-specific code (markus)
+	* Turn off heap-checker for statically-linked binaries, which
+	  cause error leak reports now (etune)
+	* Many pprof improvements, including a command-line interface (jeff)
+	* CPU profiling now automatically affects all threads in linux 2.6.
+	  (Kernel bugs break CPU profiling and threads in linux 2.4 a bit.)
+	  ProfilerEnable() and ProfilerDisable() are deprecated.  (sanjay)
+	* tcmalloc now correctly intercepts memalign (m3b, maxim)
+	* Syntax fix: added missing va_end()s.  Helps non-gcc compiling (etune)
+	* Fixed a few coredumper bugs: race condition after PTRACE_DETACH,
+	  ignore non-aligned stackframe pointers (markus, menage)
+	* 64-bit cleanup, especially for spinlock code (etune) and mmap (sanjay)
+	* Better support for finding threads in linux (markus)
+	* tcmalloc now tracks those stack traces that allocate memory (sanjay)
+	* Work around a weird setspecific problem (sanjay)
+	* Fix tcmalloc overflow problems when an alloc is close to 2G/4G (sanjay)
+
+Fri Jun 24 18:02:26 2005  Google Inc. <opensource@google.com>
+
+	* google-perftools: version 0.3 release
+	* Add missing errno include for one of the unittests (csilvers)
+	* Reduce tcmalloc startup memory from 5M to 256K (sanjay)
+	* Add support for mallopt() and mallinfo (sanjay)
+	* Improve stacktrace's performance on some 64-bit systems (etune)
+	* Improve the stacktrace unittest (etune)
+
+Tue May 31 08:14:38 2005  Google Inc. <opensource@google.com>
+
+	* google-perftools: version 0.2 release
+	* Use mmap2() instead of mmap(), to map more memory (menage)
+	* Do correct pthread-local checking in heap-checker! (maxim)
+	* Avoid overflow on 64-bit machines in pprof (sanjay)
+	* Add a few more GetPC() functions, including for AMD (csilvers)
+	* Better method for overriding pthread functions (menage)
+	* (Hacky) fix to avoid overwriting profile files after fork() (csilvers)
+	* Crashing bugfix involving dumping heaps on small-stack threads (tudor)
+	* Allow library versions with letters at the end (csilvers)
+	* Config fixes for systems that don't define PATH_MAX (csilvers)
+	* Confix fixes so we no longer need config.h after install (csilvers)
+	* Fix to pprof to correctly read very big cpu profiles (csilvers)
+	* Fix to pprof to deal with new commandline flags in modern gv's
+	* Better error reporting when we can't access /proc/maps (etune)
+	* Get rid of the libc-preallocate code (which could crash on some
+	  systems); no longer needed with local-threads fix (csilvers)
+
+Tue Feb 8 09:57:17 2005  Google Inc. <opensource@google.com>
+
+	* google-perftools: initial release:
+	  The google-perftools package contains some utilities to improve
+	  and analyze the performance of C++ programs.  This includes an
+	  optimized thread-caching malloc() and cpu and heap profiling
+	  utilities.
diff --git a/INSTALL b/INSTALL
index 0e2ad31..9d765c6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,10 @@
-Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
+Installation Instructions
+*************************
 
-   This file is free documentation; the Free Software Foundation gives
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
 
 
@@ -12,7 +15,7 @@
 
 The glibc built-in stack-unwinder on 64-bit systems has some problems
 with the perftools libraries.  (In particular, the cpu/heap profiler
-may be in the middle of malloc, holding some malloc-related locks when
+may be in the middle of malloc, holding some malloc-related locks, when
 they invoke the stack unwinder.  The built-in stack unwinder may call
 malloc recursively, which may require the thread to acquire a lock it
 already holds: deadlock.)
@@ -28,7 +31,7 @@
 
 CAUTION: if you install libunwind from the url above, be aware that
 you may have trouble if you try to statically link your binary with
-pertools: that is, if you link with 'gcc -static -lgcc_eh ...'.  This
+perftools: that is, if you link with 'gcc -static -lgcc_eh ...'.  This
 is because both libunwind and libgcc implement the same C++ exception
 handling APIs, but they implement them differently on some platforms.
 This is not likely to be a problem on ia64, but may be on x86-64.
@@ -61,69 +64,104 @@
    Linux Fedora Core 5 (x86)
    Linux Fedora Core 6 (x86)
    Linux Ubuntu 6.06.1 (x86)
-   Linux Ubuntu 6.06.1 (ia64)
+   Linux Ubuntu 6.06.1 (x86_64)
    Linux RedHat 9 (x86)
    Mac OS X 10.3.9 (Panther) (PowerPC)
+   Mac OS X 10.4.8 (Tiger) (PowerPC)
    Mac OS X 10.4.8 (Tiger) (x86)
    Solaris 10 (x86)
    Windows XP, Visual Studio 2003 (VC++ 7) (x86)
    Windows XP, Visual Studio 2005 (VC++ 8) (x86)
 
 It works in its full generality on all the Linux systems tested, both
-x86 and ia64 (though see 64-bit notes above).  Portions of perftools
-work on the other systems.  The basic memory-allocation library,
-tcmalloc_minimal, works on all systems.  The advanced tools, such as
-the cpu-profiler, heap-profiler, and heap-checker, are not yet as
-widely supported.
+x86 and x86_64 (though see 64-bit notes above).  There's also
+preliminary support for ia64 architectures, though more remains to be
+done there.
 
-Note that tcmalloc_minimal is perfectly usable as a malloc/new
-replacement, so it is possible to use tcmalloc on all the systems
-above, by linking in libtcmalloc_minimal.
+On other unix-based systems, most of perftools works.  The basic
+memory-allocation library, tcmalloc_minimal, works on all systems.
+The cpu-profiler also works widely.  The heap-profiler works on many
+systems, but ONLY FOR SINGLE-THREADED PROGRAMS.  It also does not
+profile mmap calls, which the linux version of the code does.  In both
+cases, this is because the necessary system munging -- to find all
+threads, to override the relevant syscalls -- has only been written
+for Linux.
+
+The last provided tool, the heap-checker, works only on Linux.  This
+is again because the necessary system munging -- in this case, to find
+all the memory-mapped regions owned by a process -- has only been
+written for Linux.  You can still safely try to use the heap-checker,
+it will just turn itself off and not do any leak-detection.
+
+In all cases -- including for Windows -- the basic code that replaces
+new/malloc works and is usable, by linking in either libtcmalloc or
+libtcmalloc_minimal.
 
 ** FreeBSD:
 
-   The following binaries build and run successfully (creating
-   libtcmalloc_minimal.so in the process):
+   Everything should build successfully (creating
+   libtcmalloc_minimal.so, libtcmalloc.so, and libprofile.so in the
+   process):
       % ./configure
-      % make tcmalloc_minimal_unittest tcmalloc_minimal_large_unittest \
-             addressmap_unittest atomicops_unittest frag_unittest \
-             low_level_alloc_unittest markidle_unittest memalign_unittest \
-             packed_cache_test stacktrace_unittest system_alloc_unittest \
-             thread_dealloc_unittest
-      % ./tcmalloc_minimal_unittest    # to run this test
-      % [etc]                          # to run other tests
+      % make
+      % make check    # to run the tests
+      % make install  # to install the libraries
 
-   (The only possible exception is frag_unittest, which tries to
-   allocate 400M of memory; if you have less virtual memory on your
-   system, the test may fail with a bad_alloc exception.)
+   Most of the unittests should pass.  A few may fail:
 
-   In addition, you can build and run these tests (creating libprofile.so
-   in the process), but they don't pass.  Feel free to look into why!
-   Maybe you can fix them up.  (Perhaps GetPC is wrong?)
-      % make profiler_unittest.sh
-      % ./profiler_unittest.sh         # to run the test
+   1) frag_unittest tries to allocate 400M of memory, and if you have
+      less virtual memory on your system, the test may fail with a
+      bad_alloc exception.
 
-   libtcmalloc.so does not successfully build, so neither do these
-   unittests that depend on it:
-      % make -k heap-profiler_unittest.sh heap-checker_unittest.sh \
-                heap-checker-death_unittest.sh maybe_threads_unittest.sh \
-                tcmalloc_unittest tcmalloc_both_unittest \
-                tcmalloc_large_unittest
+   2) profiler_unittest.sh sometimes fails in the "fork" test.  This
+      is because stray SIGPROF signals from the parent process are
+      making their way into the child process.  (This may be a kernel
+      bug that only exists in older kernels.)  The profiling code
+      itself is working fine.  This only affects programs that call
+      fork(); for most programs, as long as the unittest makes it to
+      the "fork" test, it indicates the cpu profiler is safe to use.
+
+   3) heap-checker-death_unittest.sh will fail because the
+      heap-checker does not successfully run on FreeBSD.  The
+      leak-checker notices it cannot run and turns itself off; as a
+      result, it does not die in the way the unittest is expecting,
+      leading to test failure.  (Likewise, while
+      heap-checker_unittest.sh succeeds, it doesn't actually test
+      anything, since heap-checking is never actually enabled during
+      those tests.)
+
+   As a result, you can safely link any or all of libtcmalloc_minimal,
+   libtcmalloc, or libprofiler into your application.  The following
+   functionality is available:
+
+   1) malloc/new replacement: by linking in libtcmalloc or
+      libtcmalloc_minimal.
+   2) heap-profiler: by linking in libtcmalloc and setting HEAPPROFILE.
+   3) cpu-profiler: by linking in libprofile and setting CPUPROFILE.
+
+   The following functionality is not available; if you try to enable
+   it, it will turn itself off:
+
+   1) heap-checker (automatic leak-detection): by linking in
+      libtcmalloc and setting HEAPCHECK.
+
+   See the README and documentation in the doc/ directory for more
+   information on how to use these features.
 
    I have not tested other *BSD systems, but they are probably similar.
 
 ** Mac OS X:
 
-   I've only tested on Intel (x86) systems.  PowerPC may work as well
-   -- I've implemented a stacktrace_ppc-inl.h that *ought* to work --
-   but hasn't been tested.  (For PowerPC, it probably will only work
-   for OS X 10.4 [Tiger] and later, since the ppc code uses
-   OSAtomic.h, which is new in 10.4.)  If you try it, let us know what
-   you find!
+   I've tested OS X 10.4 [Tiger] and OS X 10.3 [Panther] on both intel
+   (x86) and PowerPC systems.  For Panther/ppc systems, perftools does
+   not work at all: it depends on a header file, OSAtomic.h, which is
+   new in 10.4.
 
-   On Mac OS X/x86 systems, the binaries and libraries that
-   successfully build are exactly the same as for FreeBSD.  See that
-   section for a list of binaries, and instructions on building them.
+   For the other three systems, all binaries and libraries build, and
+   the set of unittests that pass are exactly the same as for FreeBSD.
+   In particular, you can use the basic malloc/new replacements (by
+   linking in libtcmalloc or libtcmalloc_minimal), the heap-profiler
+   (by linking in libtcmalloc and setting HEAPPROFILE), 
 
 ** Solaris 10 x86:
 
@@ -133,14 +171,24 @@
    src/solaris/libstdc++.la for more info), which we work around by
    adding a custom LDFLAGS argument:
 
-   % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin ./configure LDFLAGS="-Lsrc/solaris -lrt"
-   % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin make [...]
+   % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin ./configure LDFLAGS="-Lsrc/solaris -lrt -lnsl"
+   % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin make
 
-   Again, the binaries and libraries that successfully build are
-   exactly the same as for FreeBSD.  (The profiler code is farther
-   from working, though -- c++filt doesn't seem to be installed by
-   default on Solaris.)  See that section for a list of binaries, and
-   instructions on building them.
+   Again, all binaries and libraries successfully build.  However,
+   while libprofiler.so can be used to generate CPU profiles, pprof is
+   not very successful at reading them -- necessary helper programs
+   like nm don't seem to be installed by default on Solaris, or
+   perhaps are only installed as part of the Sun C++ compiler package.
+   Even more trouble exists trying to generate heap-profiles, because
+   the Sun linker does not support __attribute__((section)).  I've
+   been unable to test this, but it might work correctly if you can
+   get gcc to use the gnu linker (/usr/sfw/bin/gld) instead of sun's
+   ld.
+
+   The perftools code uses a lot of gcc-specific functionality,
+   including attributes like section-naming and weak-linking, so it
+   may be difficult to fully port this code to the Sun C++ compiler.
+   The basic tcmalloc_minimal library may port well, however.
 
 ** Windows:
 
@@ -154,10 +202,23 @@
    instructions on how to install on Windows.
 
 
+*** FURTHER OPTIONAL TESTING
+
+  In addition to all the tests that tcmalloc performs with "make
+  check", for your convenience we've included part a test suite that
+  comes with ptmalloc, another malloc implementation.  It is not
+  enabled by default, because the tests do not compile on all systems.
+  If you want to run these tests, you can try the following:
+
+      % make ptmalloc_unittest1 ptmalloc_unittest2
+      % ./ptmalloc_unittest1    # to run the test
+      % ./ptmalloc_unittest2    # to run the test
+
+
 Basic Installation
 ==================
 
-   These are generic installation instructions.
+These are generic installation instructions.
 
    The `configure' shell script attempts to guess correct values for
 various system-dependent variables used during compilation.  It uses
@@ -217,9 +278,9 @@
 Compilers and Options
 =====================
 
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
 
    You can give `configure' initial values for configuration parameters
 by setting variables in the command line or in the environment.  Here
@@ -232,7 +293,7 @@
 Compiling For Multiple Architectures
 ====================================
 
-   You can compile the package for more than one kind of computer at the
+You can compile the package for more than one kind of computer at the
 same time, by placing the object files for each architecture in their
 own directory.  To do this, you must use a version of `make' that
 supports the `VPATH' variable, such as GNU `make'.  `cd' to the
@@ -249,19 +310,19 @@
 Installation Names
 ==================
 
-   By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
 
    You can specify separate installation prefixes for
 architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
 
    In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
+options like `--bindir=DIR' to specify different values for particular
 kinds of files.  Run `configure --help' for a list of the directories
 you can set and what kinds of files go in them.
 
@@ -272,7 +333,7 @@
 Optional Features
 =================
 
-   Some packages pay attention to `--enable-FEATURE' options to
+Some packages pay attention to `--enable-FEATURE' options to
 `configure', where FEATURE indicates an optional part of the package.
 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
 is something like `gnu-as' or `x' (for the X Window System).  The
@@ -287,11 +348,11 @@
 Specifying the System Type
 ==========================
 
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
 `--build=TYPE' option.  TYPE can either be a short name for the system
 type, such as `sun4', or a canonical name which has the form:
 
@@ -306,7 +367,7 @@
 need to know the machine type.
 
    If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
+use the option `--target=TYPE' to select the type of system they will
 produce code for.
 
    If you want to _use_ a cross compiler, that generates code for a
@@ -317,9 +378,9 @@
 Sharing Defaults
 ================
 
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
 `configure' looks for `PREFIX/share/config.site' if it exists, then
 `PREFIX/etc/config.site' if it exists.  Or, you can set the
 `CONFIG_SITE' environment variable to the location of the site script.
@@ -328,7 +389,7 @@
 Defining Variables
 ==================
 
-   Variables not defined in a site shell script can be set in the
+Variables not defined in a site shell script can be set in the
 environment passed to `configure'.  However, some packages may run
 configure again during the build, and the customized values of these
 variables may be lost.  In order to avoid this problem, you should set
@@ -336,14 +397,18 @@
 
      ./configure CC=/usr/local2/bin/gcc
 
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).  Here is a another example:
+
+     /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
 
 `configure' Invocation
 ======================
 
-   `configure' recognizes the following options to control how it
-operates.
+`configure' recognizes the following options to control how it operates.
 
 `--help'
 `-h'
diff --git a/Makefile.am b/Makefile.am
index 6bb9724..d351602 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,8 +9,25 @@
 
 # This is so we can #include <google/foo>
 AM_CPPFLAGS = -I$(top_srcdir)/src
-# This is initialized in configure.ac (though we might add to it later)
-AM_CXXFLAGS = $(EXTRA_CXXFLAGS)
+
+# This is mostly based on configure options
+AM_CXXFLAGS =
+
+# These are good warnings to turn on by default,
+if GCC
+AM_CXXFLAGS += -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
+endif
+
+# These are x86-specific, having to do with frame-pointers
+if X86_64
+if ENABLE_FRAME_POINTER
+AM_CXXFLAGS += -fno-omit-frame-pointer
+else
+  # TODO(csilvers): check if -fomit-frame-pointer might be in $(CXXFLAGS),
+  #                 before setting this.
+AM_CXXFLAGS += -DNO_FRAME_POINTER
+endif
+endif
 
 googleincludedir = $(includedir)/google
 # The .h files you want to install (that is, .h files that people
@@ -181,16 +198,29 @@
 WINDOWS_PROJECTS += vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
 libtcmalloc_minimal_la_SOURCES = src/internal_logging.cc \
                                  src/system-alloc.cc \
+                                 src/memfs_malloc.cc \
                                  src/tcmalloc.cc \
                                  src/malloc_hook.cc \
                                  src/malloc_extension.cc \
                                  src/maybe_threads.cc \
                                  $(TCMALLOC_MINIMAL_INCLUDES)
-libtcmalloc_minimal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
+libtcmalloc_minimal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
 libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS)
 libtcmalloc_minimal_la_LIBADD = $(PTHREAD_LIBS) \
                                 libstacktrace.la libspinlock.la liblogging.la
 
+# Whenever we link in tcmalloc_minimal, we also need to link in
+# libstacktrace.so (we also need libspinlock and liblogging, but those
+# are created as .a's, not .so's).  libtool should do this for us, via
+# the LIBADD above.  But on some systems, -rpath doesn't work
+# properly, and whatever libtool does fails.  So we just manually link
+# in -lstacktrace whenever linking in -ltcmalloc_minimal.
+# (Note this isn't a problem for an *installed* tcmalloc, because then
+# everything lives in /usr/lib or /usr/local/lib, which is on the
+# linker search path, so the value of -rpath doesn't matter.)
+# Remember tcmalloc should always be linked in last!
+LIBTCMALLOC_MINIMAL = libstacktrace.la libtcmalloc_minimal.la
+
 ### Unittests
 
 # Commented out for the moment because malloc(very_big_num) is broken in
@@ -205,7 +235,7 @@
 ##                           src/malloc_extension.cc \
 ##                           src/maybe_threads.cc \
 ##                           $(MALLOC_UNITTEST_INCLUDES)
-## malloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+## malloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 ## malloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
 ## malloc_unittest_LDADD = $(PTHREAD_LIBS)
 
@@ -216,18 +246,19 @@
                             src/tcmalloc.h \
                             src/tests/testutil.h src/tests/testutil.cc \
                             $(TCMALLOC_UNITTEST_INCLUDES)
-tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_unittest_LDADD = libtcmalloc.la liblogging.la $(PTHREAD_LIBS)
+tcmalloc_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS)
 
 TESTS += tcmalloc_minimal_unittest
 WINDOWS_PROJECTS += vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
+WINDOWS_PROJECTS += vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj
 tcmalloc_minimal_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
                                     src/tests/testutil.h src/tests/testutil.cc \
                                     $(TCMALLOC_UNITTEST_INCLUDES)
-tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_minimal_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_minimal_unittest_LDADD = libtcmalloc_minimal.la \
+tcmalloc_minimal_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) \
                                   liblogging.la $(PTHREAD_LIBS)
 
 # This makes sure it's safe to link in both tcmalloc and tcmalloc_minimal.
@@ -236,23 +267,23 @@
 tcmalloc_both_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
                                  src/tests/testutil.h src/tests/testutil.cc \
                                  $(TCMALLOC_UNITTEST_INCLUDES)
-tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_both_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_both_unittest_LDADD = libtcmalloc.la libtcmalloc_minimal.la \
+tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \
                                liblogging.la $(PTHREAD_LIBS)
 
 TESTS += tcmalloc_large_unittest
 tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc
-tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_large_unittest_LDADD = libtcmalloc.la $(PTHREAD_LIBS)
+tcmalloc_large_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS)
 
 TESTS += tcmalloc_minimal_large_unittest
 WINDOWS_PROJECTS += vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
 tcmalloc_minimal_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc
-tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_minimal_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_minimal_large_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+tcmalloc_minimal_large_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 
 # This tests it works to LD_PRELOAD libtcmalloc (tests maybe_threads.cc)
 TESTS += maybe_threads_unittest.sh
@@ -260,7 +291,7 @@
 noinst_SCRIPTS += $(maybe_threads_unittest_sh_SOURCES)
 # This script preloads libtcmalloc, and calls two other binaries as well
 maybe_threads_unittest.sh$(EXEEXT): $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) \
-                           libtcmalloc.la \
+                           $(LIBTCMALLOC) \
                            low_level_alloc_unittest profiler1_unittest
 	rm -f $@
 	cp -p $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) $@
@@ -269,9 +300,9 @@
 WINDOWS_PROJECTS += vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj
 system_alloc_unittest_SOURCES = src/config_for_unittests.h \
                                 src/tests/system-alloc_unittest.cc
-system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 system_alloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-system_alloc_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+system_alloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 
 TESTS += packed_cache_test
 WINDOWS_PROJECTS += vsprojects/packed-cache_test/packed-cache_test.vcproj
@@ -280,7 +311,12 @@
                             src/base/logging.h
 
 # performance/unittests originally from ptmalloc2
-TESTS += ptmalloc_unittest1 ptmalloc_unittest2
+# Commented out for now because they don't compile on all systems.
+# However, you can still make/run by hand like so:
+#    make ptmalloc_unittest1 ptmalloc_unittest2
+#    ./ptmalloc_unittest1; ./ptmalloc_unittest2
+##TESTS += ptmalloc_unittest1 ptmalloc_unittest2
+EXTRA_PROGRAMS = ptmalloc_unittest1 ptmalloc_unittest2
 PTMALLOC_UNITTEST_INCLUDES = src/tests/ptmalloc/t-test.h \
                              src/tests/ptmalloc/thread-m.h \
                              src/tests/ptmalloc/lran2.h \
@@ -300,36 +336,36 @@
 TESTS += frag_unittest
 WINDOWS_PROJECTS += vsprojects/frag_unittest/frag_unittest.vcproj
 frag_unittest_SOURCES = src/tests/frag_unittest.cc src/config_for_unittests.h
-frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 frag_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-frag_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+frag_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 
 TESTS += markidle_unittest
 WINDOWS_PROJECTS += vsprojects/markidle_unittest/markidle_unittest.vcproj
 markidle_unittest_SOURCES = src/tests/markidle_unittest.cc \
                             src/config_for_unittests.h \
                             src/tests/testutil.h src/tests/testutil.cc
-markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 markidle_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-markidle_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+markidle_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 
 TESTS += memalign_unittest
 WINDOWS_PROJECTS += vsprojects/memalign_unittest/memalign_unittest.vcproj
 memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \
                             src/config_for_unittests.h \
                             src/tcmalloc.h
-memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-memalign_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 
 TESTS += thread_dealloc_unittest
 WINDOWS_PROJECTS += vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
 thread_dealloc_unittest_SOURCES = src/tests/thread_dealloc_unittest.cc \
                                   src/config_for_unittests.h \
                                   src/tests/testutil.h src/tests/testutil.cc
-thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 thread_dealloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-thread_dealloc_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 
 ### Documentation
 dist_doc_DATA += doc/tcmalloc.html \
@@ -403,6 +439,7 @@
 # Note: heap-checker-bcad is last, in hopes its global ctor will run first
 libtcmalloc_la_SOURCES = src/internal_logging.cc \
                          src/system-alloc.cc \
+                         src/memfs_malloc.cc \
                          src/tcmalloc.cc \
                          src/malloc_hook.cc \
                          src/malloc_extension.cc \
@@ -417,11 +454,17 @@
                          src/base/low_level_alloc.cc \
                          $(TCMALLOC_INCLUDES) \
                          src/heap-checker-bcad.cc
-libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
+libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
 libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS)
 libtcmalloc_la_LIBADD = $(PTHREAD_LIBS) \
                         libstacktrace.la libspinlock.la liblogging.la
 
+# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
+# Basically it's to work around systems where --rpath doesn't work right.
+# Remember tcmalloc should always be linked in last!
+LIBTCMALLOC = libstacktrace.la libtcmalloc.la
+
+
 ### Unittests
 
 # These unittests often need to run binaries.  They're in the current dir
@@ -434,7 +477,7 @@
                                $(LOGGING_INCLUDES)
 addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc \
                               $(ADDRESSMAP_UNITTEST_INCLUDES)
-addressmap_unittest_CXXFLAGS = -g
+addressmap_unittest_CXXFLAGS = -g $(AM_CXXFLAGS)
 addressmap_unittest_LDADD = liblogging.la
 
 TESTS += heap-profiler_unittest.sh
@@ -451,9 +494,9 @@
                                   src/google/heap-profiler.h
 heap_profiler_unittest_SOURCES = src/tests/heap-profiler_unittest.cc \
                                  $(HEAP_PROFILER_UNITTEST_INCLUDES)
-heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 heap_profiler_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS)
-heap_profiler_unittest_LDADD = libtcmalloc.la $(PTHREAD_LIBS)
+heap_profiler_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS)
 
 TESTS += heap-checker_unittest.sh
 heap_checker_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh
@@ -481,10 +524,10 @@
                                  $(LOGGING_INCLUDES)
 heap_checker_unittest_SOURCES = src/tests/heap-checker_unittest.cc \
                                 $(HEAP_CHECKER_UNITTEST_INCLUDES)
-heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 heap_checker_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS)
 # tcmalloc has to be specified last!
-heap_checker_unittest_LDADD =  $(PTHREAD_LIBS) liblogging.la -ltcmalloc
+heap_checker_unittest_LDADD = $(PTHREAD_LIBS) liblogging.la $(LIBTCMALLOC)
 
 ### Documentation (above and beyond tcmalloc_minimal documentation)
 dist_doc_DATA += doc/heapprofile.html \
@@ -495,10 +538,13 @@
 ### ------- CPU profiler
 
 ### The header files we use.  We divide into categories based on directory
-S_CPU_PROFILER_INCLUDES = src/base/commandlineflags.h \
+S_CPU_PROFILER_INCLUDES = src/getpc.h \
+                          src/base/basictypes.h \
+                          src/base/commandlineflags.h \
                           src/base/googleinit.h \
                           src/base/logging.h \
                           src/base/mutex.h \
+                          src/base/sysinfo.h \
                           $(SPINLOCK_INCLUDES) \
                           $(LOGGING_INCLUDES)
 SG_CPU_PROFILER_INCLUDES = src/google/profiler.h \
@@ -509,12 +555,21 @@
 ### Making the library
 lib_LTLIBRARIES += libprofiler.la
 libprofiler_la_SOURCES = src/profiler.cc \
+                         src/base/sysinfo.cc \
                          $(CPU_PROFILER_INCLUDES)
 libprofiler_la_LIBADD = libspinlock.la liblogging.la libstacktrace.la
 CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStop|ProfilerEnable|ProfilerDisable|ProfilerFlush|ProfilerRegisterThread|ProfilerThreadState)'
 libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS)
 
+# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
+# Basically it's to work around systems where --rpath doesn't work right.
+LIBPROFILER = libstacktrace.la libprofiler.la
+
 ### Unittests
+TESTS += getpc_test
+#WINDOWS_PROJECTS += vsprojects/getpc_test/getpc_test.vcproj
+getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h
+
 TESTS += profiler_unittest.sh
 profiler_unittest_sh_SOURCES = src/tests/profiler_unittest.sh
 noinst_SCRIPTS += $(profiler_unittest_sh_SOURCES)
@@ -533,23 +588,23 @@
                          src/tests/testutil.h src/tests/testutil.cc \
                          $(PROFILER_UNITTEST_INCLUDES)
 profiler1_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler1_unittest_CXXFLAGS = -g -DNO_THREADS
-profiler1_unittest_LDADD = libprofiler.la
+profiler1_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
+profiler1_unittest_LDADD = $(LIBPROFILER)
 profiler2_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler2_unittest_CXXFLAGS = -g -DNO_THREADS
-profiler2_unittest_LDADD = -lprofiler
+profiler2_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
+profiler2_unittest_LDADD = -lstacktrace -lprofiler
 # We depend on -lprofiler but haven't yet said how to build it.  Do so now.
-profiler2_unittest_DEPENDENCIES = libprofiler.la
+profiler2_unittest_DEPENDENCIES = $(LIBPROFILER)
 profiler3_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 profiler3_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-profiler3_unittest_LDADD = libprofiler.la $(PTHREAD_LIBS)
+profiler3_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS)
 profiler4_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 profiler4_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-profiler4_unittest_LDADD = -lprofiler $(PTHREAD_LIBS)
+profiler4_unittest_LDADD = -lstacktrace -lprofiler $(PTHREAD_LIBS)
 # We depend on -lprofiler but haven't yet said how to build it.  Do so now.
-profiler4_unittest_DEPENDENCIES = libprofiler.la
+profiler4_unittest_DEPENDENCIES = $(LIBPROFILER)
 
 
 ### Documentation
@@ -576,6 +631,11 @@
 libtool: $(LIBTOOL_DEPS)
 	$(SHELL) ./config.status --recheck
 
+# Windows wants write permission to .vcproj files and maybe even sln files.
+dist-hook:
+	test -e "$(distdir)/vsprojects" \
+	   && chmod -R u+w $(distdir)/*.sln $(distdir)/vsprojects/
+
 EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
              $(SCRIPTS) libtool \
              src/windows $(WINDOWS_PROJECTS) src/solaris/libstdc++.la
diff --git a/Makefile.in b/Makefile.in
index 7476cda..2c44355 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -44,10 +44,19 @@
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
+
+# These are good warnings to turn on by default,
+@GCC_TRUE@am__append_1 = -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
+
+# These are x86-specific, having to do with frame-pointers
+@ENABLE_FRAME_POINTER_TRUE@@X86_64_TRUE@am__append_2 = -fno-omit-frame-pointer
+@ENABLE_FRAME_POINTER_FALSE@@X86_64_TRUE@am__append_3 = -DNO_FRAME_POINTER
 noinst_PROGRAMS = heap-profiler_unittest$(EXEEXT) \
 	heap-checker_unittest$(EXEEXT) profiler1_unittest$(EXEEXT) \
 	profiler2_unittest$(EXEEXT) profiler3_unittest$(EXEEXT) \
 	profiler4_unittest$(EXEEXT) $(am__EXEEXT_1)
+EXTRA_PROGRAMS = ptmalloc_unittest1$(EXEEXT) \
+	ptmalloc_unittest2$(EXEEXT)
 DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \
 	$(dist_man_MANS) $(googleinclude_HEADERS) \
 	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -90,7 +99,7 @@
 	libstacktrace.la
 am__objects_2 = $(am__objects_1) $(am__objects_1)
 am__objects_3 = $(am__objects_2) $(am__objects_1)
-am_libprofiler_la_OBJECTS = profiler.lo $(am__objects_3)
+am_libprofiler_la_OBJECTS = profiler.lo sysinfo.lo $(am__objects_3)
 libprofiler_la_OBJECTS = $(am_libprofiler_la_OBJECTS)
 libspinlock_la_LIBADD =
 am_libspinlock_la_OBJECTS = spinlock.lo atomicops-internals-x86.lo \
@@ -103,8 +112,8 @@
 libtcmalloc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) libstacktrace.la \
 	libspinlock.la liblogging.la
 am_libtcmalloc_la_OBJECTS = libtcmalloc_la-internal_logging.lo \
-	libtcmalloc_la-system-alloc.lo libtcmalloc_la-tcmalloc.lo \
-	libtcmalloc_la-malloc_hook.lo \
+	libtcmalloc_la-system-alloc.lo libtcmalloc_la-memfs_malloc.lo \
+	libtcmalloc_la-tcmalloc.lo libtcmalloc_la-malloc_hook.lo \
 	libtcmalloc_la-malloc_extension.lo \
 	libtcmalloc_la-maybe_threads.lo \
 	libtcmalloc_la-memory_region_map.lo \
@@ -122,6 +131,7 @@
 am_libtcmalloc_minimal_la_OBJECTS =  \
 	libtcmalloc_minimal_la-internal_logging.lo \
 	libtcmalloc_minimal_la-system-alloc.lo \
+	libtcmalloc_minimal_la-memfs_malloc.lo \
 	libtcmalloc_minimal_la-tcmalloc.lo \
 	libtcmalloc_minimal_la-malloc_hook.lo \
 	libtcmalloc_minimal_la-malloc_extension.lo \
@@ -135,13 +145,12 @@
 	tcmalloc_minimal_large_unittest$(EXEEXT) \
 	maybe_threads_unittest.sh$(EXEEXT) \
 	system_alloc_unittest$(EXEEXT) packed_cache_test$(EXEEXT) \
-	ptmalloc_unittest1$(EXEEXT) ptmalloc_unittest2$(EXEEXT) \
 	frag_unittest$(EXEEXT) markidle_unittest$(EXEEXT) \
 	memalign_unittest$(EXEEXT) thread_dealloc_unittest$(EXEEXT) \
 	addressmap_unittest$(EXEEXT) \
 	heap-profiler_unittest.sh$(EXEEXT) \
 	heap-checker_unittest.sh$(EXEEXT) \
-	heap-checker-death_unittest.sh$(EXEEXT) \
+	heap-checker-death_unittest.sh$(EXEEXT) getpc_test$(EXEEXT) \
 	profiler_unittest.sh$(EXEEXT)
 PROGRAMS = $(noinst_PROGRAMS)
 am_addressmap_unittest_OBJECTS =  \
@@ -155,8 +164,12 @@
 atomicops_unittest_DEPENDENCIES = libspinlock.la liblogging.la
 am_frag_unittest_OBJECTS = frag_unittest-frag_unittest.$(OBJEXT)
 frag_unittest_OBJECTS = $(am_frag_unittest_OBJECTS)
-frag_unittest_DEPENDENCIES = libtcmalloc_minimal.la \
+am__DEPENDENCIES_2 = libstacktrace.la libtcmalloc_minimal.la
+frag_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 	$(am__DEPENDENCIES_1)
+am_getpc_test_OBJECTS = getpc_test.$(OBJEXT)
+getpc_test_OBJECTS = $(am_getpc_test_OBJECTS)
+getpc_test_LDADD = $(LDADD)
 am_heap_checker_death_unittest_sh_OBJECTS =
 heap_checker_death_unittest_sh_OBJECTS =  \
 	$(am_heap_checker_death_unittest_sh_OBJECTS)
@@ -165,8 +178,9 @@
 	heap_checker_unittest-heap-checker_unittest.$(OBJEXT) \
 	$(am__objects_4)
 heap_checker_unittest_OBJECTS = $(am_heap_checker_unittest_OBJECTS)
+am__DEPENDENCIES_3 = libstacktrace.la libtcmalloc.la
 heap_checker_unittest_DEPENDENCIES = $(am__DEPENDENCIES_1) \
-	liblogging.la
+	liblogging.la $(am__DEPENDENCIES_3)
 am_heap_checker_unittest_sh_OBJECTS =
 heap_checker_unittest_sh_OBJECTS =  \
 	$(am_heap_checker_unittest_sh_OBJECTS)
@@ -175,7 +189,7 @@
 	heap_profiler_unittest-heap-profiler_unittest.$(OBJEXT) \
 	$(am__objects_1)
 heap_profiler_unittest_OBJECTS = $(am_heap_profiler_unittest_OBJECTS)
-heap_profiler_unittest_DEPENDENCIES = libtcmalloc.la \
+heap_profiler_unittest_DEPENDENCIES = $(am__DEPENDENCIES_3) \
 	$(am__DEPENDENCIES_1)
 am_heap_profiler_unittest_sh_OBJECTS =
 heap_profiler_unittest_sh_OBJECTS =  \
@@ -192,7 +206,7 @@
 	markidle_unittest-markidle_unittest.$(OBJEXT) \
 	markidle_unittest-testutil.$(OBJEXT)
 markidle_unittest_OBJECTS = $(am_markidle_unittest_OBJECTS)
-markidle_unittest_DEPENDENCIES = libtcmalloc_minimal.la \
+markidle_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 	$(am__DEPENDENCIES_1)
 am_maybe_threads_unittest_sh_OBJECTS =
 maybe_threads_unittest_sh_OBJECTS =  \
@@ -201,7 +215,7 @@
 am_memalign_unittest_OBJECTS =  \
 	memalign_unittest-memalign_unittest.$(OBJEXT)
 memalign_unittest_OBJECTS = $(am_memalign_unittest_OBJECTS)
-memalign_unittest_DEPENDENCIES = libtcmalloc_minimal.la \
+memalign_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 	$(am__DEPENDENCIES_1)
 am_packed_cache_test_OBJECTS = packed-cache_test.$(OBJEXT)
 packed_cache_test_OBJECTS = $(am_packed_cache_test_OBJECTS)
@@ -210,7 +224,8 @@
 	profiler1_unittest-testutil.$(OBJEXT) $(am__objects_1)
 am_profiler1_unittest_OBJECTS = $(am__objects_6)
 profiler1_unittest_OBJECTS = $(am_profiler1_unittest_OBJECTS)
-profiler1_unittest_DEPENDENCIES = libprofiler.la
+am__DEPENDENCIES_4 = libstacktrace.la libprofiler.la
+profiler1_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4)
 am__objects_7 = profiler2_unittest-profiler_unittest.$(OBJEXT) \
 	profiler2_unittest-testutil.$(OBJEXT) $(am__objects_1)
 am_profiler2_unittest_OBJECTS = $(am__objects_7)
@@ -219,7 +234,8 @@
 	profiler3_unittest-testutil.$(OBJEXT) $(am__objects_1)
 am_profiler3_unittest_OBJECTS = $(am__objects_8)
 profiler3_unittest_OBJECTS = $(am_profiler3_unittest_OBJECTS)
-profiler3_unittest_DEPENDENCIES = libprofiler.la $(am__DEPENDENCIES_1)
+profiler3_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+	$(am__DEPENDENCIES_1)
 am__objects_9 = profiler4_unittest-profiler_unittest.$(OBJEXT) \
 	profiler4_unittest-testutil.$(OBJEXT) $(am__objects_1)
 am_profiler4_unittest_OBJECTS = $(am__objects_9)
@@ -242,44 +258,44 @@
 am_system_alloc_unittest_OBJECTS =  \
 	system_alloc_unittest-system-alloc_unittest.$(OBJEXT)
 system_alloc_unittest_OBJECTS = $(am_system_alloc_unittest_OBJECTS)
-system_alloc_unittest_DEPENDENCIES = libtcmalloc_minimal.la \
+system_alloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 	$(am__DEPENDENCIES_1)
 am_tcmalloc_both_unittest_OBJECTS =  \
 	tcmalloc_both_unittest-tcmalloc_unittest.$(OBJEXT) \
 	tcmalloc_both_unittest-testutil.$(OBJEXT) $(am__objects_1)
 tcmalloc_both_unittest_OBJECTS = $(am_tcmalloc_both_unittest_OBJECTS)
-tcmalloc_both_unittest_DEPENDENCIES = libtcmalloc.la \
-	libtcmalloc_minimal.la liblogging.la $(am__DEPENDENCIES_1)
+tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_3) \
+	$(am__DEPENDENCIES_2) liblogging.la $(am__DEPENDENCIES_1)
 am_tcmalloc_large_unittest_OBJECTS =  \
 	tcmalloc_large_unittest-tcmalloc_large_unittest.$(OBJEXT)
 tcmalloc_large_unittest_OBJECTS =  \
 	$(am_tcmalloc_large_unittest_OBJECTS)
-tcmalloc_large_unittest_DEPENDENCIES = libtcmalloc.la \
+tcmalloc_large_unittest_DEPENDENCIES = $(am__DEPENDENCIES_3) \
 	$(am__DEPENDENCIES_1)
 am_tcmalloc_minimal_large_unittest_OBJECTS = tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.$(OBJEXT)
 tcmalloc_minimal_large_unittest_OBJECTS =  \
 	$(am_tcmalloc_minimal_large_unittest_OBJECTS)
-tcmalloc_minimal_large_unittest_DEPENDENCIES = libtcmalloc_minimal.la \
+tcmalloc_minimal_large_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 	$(am__DEPENDENCIES_1)
 am_tcmalloc_minimal_unittest_OBJECTS =  \
 	tcmalloc_minimal_unittest-tcmalloc_unittest.$(OBJEXT) \
 	tcmalloc_minimal_unittest-testutil.$(OBJEXT) $(am__objects_1)
 tcmalloc_minimal_unittest_OBJECTS =  \
 	$(am_tcmalloc_minimal_unittest_OBJECTS)
-tcmalloc_minimal_unittest_DEPENDENCIES = libtcmalloc_minimal.la \
+tcmalloc_minimal_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 	liblogging.la $(am__DEPENDENCIES_1)
 am_tcmalloc_unittest_OBJECTS =  \
 	tcmalloc_unittest-tcmalloc_unittest.$(OBJEXT) \
 	tcmalloc_unittest-testutil.$(OBJEXT) $(am__objects_1)
 tcmalloc_unittest_OBJECTS = $(am_tcmalloc_unittest_OBJECTS)
-tcmalloc_unittest_DEPENDENCIES = libtcmalloc.la liblogging.la \
+tcmalloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_3) liblogging.la \
 	$(am__DEPENDENCIES_1)
 am_thread_dealloc_unittest_OBJECTS =  \
 	thread_dealloc_unittest-thread_dealloc_unittest.$(OBJEXT) \
 	thread_dealloc_unittest-testutil.$(OBJEXT)
 thread_dealloc_unittest_OBJECTS =  \
 	$(am_thread_dealloc_unittest_OBJECTS)
-thread_dealloc_unittest_DEPENDENCIES = libtcmalloc_minimal.la \
+thread_dealloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 	$(am__DEPENDENCIES_1)
 binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
 SCRIPTS = $(bin_SCRIPTS) $(noinst_SCRIPTS)
@@ -306,7 +322,7 @@
 	$(libspinlock_la_SOURCES) $(libstacktrace_la_SOURCES) \
 	$(libtcmalloc_la_SOURCES) $(libtcmalloc_minimal_la_SOURCES) \
 	$(addressmap_unittest_SOURCES) $(atomicops_unittest_SOURCES) \
-	$(frag_unittest_SOURCES) \
+	$(frag_unittest_SOURCES) $(getpc_test_SOURCES) \
 	$(heap_checker_death_unittest_sh_SOURCES) \
 	$(heap_checker_unittest_SOURCES) \
 	$(heap_checker_unittest_sh_SOURCES) \
@@ -331,7 +347,7 @@
 	$(libspinlock_la_SOURCES) $(libstacktrace_la_SOURCES) \
 	$(libtcmalloc_la_SOURCES) $(libtcmalloc_minimal_la_SOURCES) \
 	$(addressmap_unittest_SOURCES) $(atomicops_unittest_SOURCES) \
-	$(frag_unittest_SOURCES) \
+	$(frag_unittest_SOURCES) $(getpc_test_SOURCES) \
 	$(heap_checker_death_unittest_sh_SOURCES) \
 	$(heap_checker_unittest_SOURCES) \
 	$(heap_checker_unittest_sh_SOURCES) \
@@ -398,10 +414,13 @@
 ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
+ENABLE_FRAME_POINTER_FALSE = @ENABLE_FRAME_POINTER_FALSE@
+ENABLE_FRAME_POINTER_TRUE = @ENABLE_FRAME_POINTER_TRUE@
 EXEEXT = @EXEEXT@
-EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@
 F77 = @F77@
 FFLAGS = @FFLAGS@
+GCC_FALSE = @GCC_FALSE@
+GCC_TRUE = @GCC_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -431,6 +450,8 @@
 STRIP = @STRIP@
 UNWIND_LIBS = @UNWIND_LIBS@
 VERSION = @VERSION@
+X86_64_FALSE = @X86_64_FALSE@
+X86_64_TRUE = @X86_64_TRUE@
 ac_ct_AR = @ac_ct_AR@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
@@ -481,8 +502,9 @@
 
 # This is so we can #include <google/foo>
 AM_CPPFLAGS = -I$(top_srcdir)/src
-# This is initialized in configure.ac (though we might add to it later)
-AM_CXXFLAGS = $(EXTRA_CXXFLAGS)
+
+# This is mostly based on configure options
+AM_CXXFLAGS = $(am__append_1) $(am__append_2) $(am__append_3)
 googleincludedir = $(includedir)/google
 # The .h files you want to install (that is, .h files that people
 # who install this package can include in their own applications.)
@@ -560,6 +582,7 @@
 	vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj \
 	vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj \
 	vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj \
+	vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj \
 	vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj \
 	vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj \
 	vsprojects/packed-cache_test/packed-cache_test.vcproj \
@@ -592,19 +615,16 @@
 
 # This tests it works to LD_PRELOAD libtcmalloc (tests maybe_threads.cc)
 
-# performance/unittests originally from ptmalloc2
-
 ### Unittests
 TESTS = low_level_alloc_unittest atomicops_unittest \
 	stacktrace_unittest tcmalloc_unittest \
 	tcmalloc_minimal_unittest tcmalloc_both_unittest \
 	tcmalloc_large_unittest tcmalloc_minimal_large_unittest \
 	maybe_threads_unittest.sh system_alloc_unittest \
-	packed_cache_test ptmalloc_unittest1 ptmalloc_unittest2 \
-	frag_unittest markidle_unittest memalign_unittest \
-	thread_dealloc_unittest addressmap_unittest \
+	packed_cache_test frag_unittest markidle_unittest \
+	memalign_unittest thread_dealloc_unittest addressmap_unittest \
 	heap-profiler_unittest.sh heap-checker_unittest.sh \
-	heap-checker-death_unittest.sh profiler_unittest.sh
+	heap-checker-death_unittest.sh getpc_test profiler_unittest.sh
 # TESTS_ENVIRONMENT sets environment variables for when you run unittest.
 # We always get "srcdir" set for free.
 # We'll add to this later, on a library-by-library basis.
@@ -722,17 +742,30 @@
 TCMALLOC_MINIMAL_INCLUDES = $(S_TCMALLOC_MINIMAL_INCLUDES) $(SG_TCMALLOC_MINIMAL_INCLUDES)
 libtcmalloc_minimal_la_SOURCES = src/internal_logging.cc \
                                  src/system-alloc.cc \
+                                 src/memfs_malloc.cc \
                                  src/tcmalloc.cc \
                                  src/malloc_hook.cc \
                                  src/malloc_extension.cc \
                                  src/maybe_threads.cc \
                                  $(TCMALLOC_MINIMAL_INCLUDES)
 
-libtcmalloc_minimal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
+libtcmalloc_minimal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
 libtcmalloc_minimal_la_LDFLAGS = $(PTHREAD_CFLAGS)
 libtcmalloc_minimal_la_LIBADD = $(PTHREAD_LIBS) \
                                 libstacktrace.la libspinlock.la liblogging.la
 
+
+# Whenever we link in tcmalloc_minimal, we also need to link in
+# libstacktrace.so (we also need libspinlock and liblogging, but those
+# are created as .a's, not .so's).  libtool should do this for us, via
+# the LIBADD above.  But on some systems, -rpath doesn't work
+# properly, and whatever libtool does fails.  So we just manually link
+# in -lstacktrace whenever linking in -ltcmalloc_minimal.
+# (Note this isn't a problem for an *installed* tcmalloc, because then
+# everything lives in /usr/lib or /usr/local/lib, which is on the
+# linker search path, so the value of -rpath doesn't matter.)
+# Remember tcmalloc should always be linked in last!
+LIBTCMALLOC_MINIMAL = libstacktrace.la libtcmalloc_minimal.la
 TCMALLOC_UNITTEST_INCLUDES = src/config_for_unittests.h \
                              src/google/malloc_extension.h
 
@@ -741,42 +774,42 @@
                             src/tests/testutil.h src/tests/testutil.cc \
                             $(TCMALLOC_UNITTEST_INCLUDES)
 
-tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_unittest_LDADD = libtcmalloc.la liblogging.la $(PTHREAD_LIBS)
+tcmalloc_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS)
 tcmalloc_minimal_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
                                     src/tests/testutil.h src/tests/testutil.cc \
                                     $(TCMALLOC_UNITTEST_INCLUDES)
 
-tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_minimal_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_minimal_unittest_LDADD = libtcmalloc_minimal.la \
+tcmalloc_minimal_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) \
                                   liblogging.la $(PTHREAD_LIBS)
 
 tcmalloc_both_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
                                  src/tests/testutil.h src/tests/testutil.cc \
                                  $(TCMALLOC_UNITTEST_INCLUDES)
 
-tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_both_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_both_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_both_unittest_LDADD = libtcmalloc.la libtcmalloc_minimal.la \
+tcmalloc_both_unittest_LDADD = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \
                                liblogging.la $(PTHREAD_LIBS)
 
 tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc
-tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_large_unittest_LDADD = libtcmalloc.la $(PTHREAD_LIBS)
+tcmalloc_large_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS)
 tcmalloc_minimal_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc
-tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 tcmalloc_minimal_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-tcmalloc_minimal_large_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+tcmalloc_minimal_large_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 maybe_threads_unittest_sh_SOURCES = src/tests/maybe_threads_unittest.sh
 system_alloc_unittest_SOURCES = src/config_for_unittests.h \
                                 src/tests/system-alloc_unittest.cc
 
-system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 system_alloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-system_alloc_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+system_alloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 packed_cache_test_SOURCES = src/tests/packed-cache_test.cc \
                             src/packed-cache-inl.h \
                             src/base/logging.h
@@ -800,30 +833,30 @@
 ptmalloc_unittest2_LDFLAGS = $(PTHREAD_CFLAGS)
 ptmalloc_unittest2_LDADD = $(PTHREAD_LIBS)
 frag_unittest_SOURCES = src/tests/frag_unittest.cc src/config_for_unittests.h
-frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 frag_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-frag_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+frag_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 markidle_unittest_SOURCES = src/tests/markidle_unittest.cc \
                             src/config_for_unittests.h \
                             src/tests/testutil.h src/tests/testutil.cc
 
-markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 markidle_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-markidle_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+markidle_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \
                             src/config_for_unittests.h \
                             src/tcmalloc.h
 
-memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-memalign_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 thread_dealloc_unittest_SOURCES = src/tests/thread_dealloc_unittest.cc \
                                   src/config_for_unittests.h \
                                   src/tests/testutil.h src/tests/testutil.cc
 
-thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
+thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 thread_dealloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-thread_dealloc_unittest_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS)
+thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
 
 ### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker)
 
@@ -857,6 +890,7 @@
 # Note: heap-checker-bcad is last, in hopes its global ctor will run first
 libtcmalloc_la_SOURCES = src/internal_logging.cc \
                          src/system-alloc.cc \
+                         src/memfs_malloc.cc \
                          src/tcmalloc.cc \
                          src/malloc_hook.cc \
                          src/malloc_extension.cc \
@@ -872,11 +906,16 @@
                          $(TCMALLOC_INCLUDES) \
                          src/heap-checker-bcad.cc
 
-libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG
+libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
 libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS)
 libtcmalloc_la_LIBADD = $(PTHREAD_LIBS) \
                         libstacktrace.la libspinlock.la liblogging.la
 
+
+# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
+# Basically it's to work around systems where --rpath doesn't work right.
+# Remember tcmalloc should always be linked in last!
+LIBTCMALLOC = libstacktrace.la libtcmalloc.la
 ADDRESSMAP_UNITTEST_INCLUDES = src/addressmap-inl.h \
                                src/base/commandlineflags.h \
                                $(LOGGING_INCLUDES)
@@ -884,7 +923,7 @@
 addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc \
                               $(ADDRESSMAP_UNITTEST_INCLUDES)
 
-addressmap_unittest_CXXFLAGS = -g
+addressmap_unittest_CXXFLAGS = -g $(AM_CXXFLAGS)
 addressmap_unittest_LDADD = liblogging.la
 heap_profiler_unittest_sh_SOURCES = src/tests/heap-profiler_unittest.sh
 HEAP_PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \
@@ -893,9 +932,9 @@
 heap_profiler_unittest_SOURCES = src/tests/heap-profiler_unittest.cc \
                                  $(HEAP_PROFILER_UNITTEST_INCLUDES)
 
-heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 heap_profiler_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS)
-heap_profiler_unittest_LDADD = libtcmalloc.la $(PTHREAD_LIBS)
+heap_profiler_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS)
 heap_checker_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh
 heap_checker_death_unittest_sh_SOURCES = src/tests/heap-checker-death_unittest.sh
 HEAP_CHECKER_UNITTEST_INCLUDES = src/config_for_unittests.h \
@@ -908,18 +947,21 @@
 heap_checker_unittest_SOURCES = src/tests/heap-checker_unittest.cc \
                                 $(HEAP_CHECKER_UNITTEST_INCLUDES)
 
-heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 heap_checker_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS)
 # tcmalloc has to be specified last!
-heap_checker_unittest_LDADD = $(PTHREAD_LIBS) liblogging.la -ltcmalloc
+heap_checker_unittest_LDADD = $(PTHREAD_LIBS) liblogging.la $(LIBTCMALLOC)
 
 ### ------- CPU profiler
 
 ### The header files we use.  We divide into categories based on directory
-S_CPU_PROFILER_INCLUDES = src/base/commandlineflags.h \
+S_CPU_PROFILER_INCLUDES = src/getpc.h \
+                          src/base/basictypes.h \
+                          src/base/commandlineflags.h \
                           src/base/googleinit.h \
                           src/base/logging.h \
                           src/base/mutex.h \
+                          src/base/sysinfo.h \
                           $(SPINLOCK_INCLUDES) \
                           $(LOGGING_INCLUDES)
 
@@ -928,11 +970,18 @@
 
 CPU_PROFILER_INCLUDES = $(S_CPU_PROFILER_INCLUDES) $(SG_CPU_PROFILER_INCLUDES)
 libprofiler_la_SOURCES = src/profiler.cc \
+                         src/base/sysinfo.cc \
                          $(CPU_PROFILER_INCLUDES)
 
 libprofiler_la_LIBADD = libspinlock.la liblogging.la libstacktrace.la
 CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStop|ProfilerEnable|ProfilerDisable|ProfilerFlush|ProfilerRegisterThread|ProfilerThreadState)'
 libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS)
+
+# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
+# Basically it's to work around systems where --rpath doesn't work right.
+LIBPROFILER = libstacktrace.la libprofiler.la
+#WINDOWS_PROJECTS += vsprojects/getpc_test/getpc_test.vcproj
+getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h
 profiler_unittest_sh_SOURCES = src/tests/profiler_unittest.sh
 PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \
                              src/google/profiler.h
@@ -942,23 +991,23 @@
                          $(PROFILER_UNITTEST_INCLUDES)
 
 profiler1_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler1_unittest_CXXFLAGS = -g -DNO_THREADS
-profiler1_unittest_LDADD = libprofiler.la
+profiler1_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
+profiler1_unittest_LDADD = $(LIBPROFILER)
 profiler2_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler2_unittest_CXXFLAGS = -g -DNO_THREADS
-profiler2_unittest_LDADD = -lprofiler
+profiler2_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS)
+profiler2_unittest_LDADD = -lstacktrace -lprofiler
 # We depend on -lprofiler but haven't yet said how to build it.  Do so now.
-profiler2_unittest_DEPENDENCIES = libprofiler.la
+profiler2_unittest_DEPENDENCIES = $(LIBPROFILER)
 profiler3_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 profiler3_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-profiler3_unittest_LDADD = libprofiler.la $(PTHREAD_LIBS)
+profiler3_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS)
 profiler4_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS)
-profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS)
+profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
 profiler4_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
-profiler4_unittest_LDADD = -lprofiler $(PTHREAD_LIBS)
+profiler4_unittest_LDADD = -lstacktrace -lprofiler $(PTHREAD_LIBS)
 # We depend on -lprofiler but haven't yet said how to build it.  Do so now.
-profiler4_unittest_DEPENDENCIES = libprofiler.la
+profiler4_unittest_DEPENDENCIES = $(LIBPROFILER)
 EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
              $(SCRIPTS) libtool \
              src/windows $(WINDOWS_PROJECTS) src/solaris/libstdc++.la
@@ -1081,6 +1130,9 @@
 frag_unittest$(EXEEXT): $(frag_unittest_OBJECTS) $(frag_unittest_DEPENDENCIES) 
 	@rm -f frag_unittest$(EXEEXT)
 	$(CXXLINK) $(frag_unittest_LDFLAGS) $(frag_unittest_OBJECTS) $(frag_unittest_LDADD) $(LIBS)
+getpc_test$(EXEEXT): $(getpc_test_OBJECTS) $(getpc_test_DEPENDENCIES) 
+	@rm -f getpc_test$(EXEEXT)
+	$(CXXLINK) $(getpc_test_LDFLAGS) $(getpc_test_OBJECTS) $(getpc_test_LDADD) $(LIBS)
 heap-checker_unittest$(EXEEXT): $(heap_checker_unittest_OBJECTS) $(heap_checker_unittest_DEPENDENCIES) 
 	@rm -f heap-checker_unittest$(EXEEXT)
 	$(CXXLINK) $(heap_checker_unittest_LDFLAGS) $(heap_checker_unittest_OBJECTS) $(heap_checker_unittest_LDADD) $(LIBS)
@@ -1171,6 +1223,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomicops-internals-x86.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomicops_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frag_unittest-frag_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getpc_test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo@am__quote@
@@ -1182,6 +1235,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-malloc_extension.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-malloc_hook.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-maybe_threads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-memfs_malloc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-memory_region_map.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-sysinfo.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-system-alloc.Plo@am__quote@
@@ -1190,6 +1244,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-malloc_extension.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-malloc_hook.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-maybe_threads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-memfs_malloc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-system-alloc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linuxthreads.Plo@am__quote@
@@ -1215,6 +1270,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spinlock.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysinfo.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_both_unittest-testutil.Po@am__quote@
@@ -1326,6 +1382,13 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o profiler.lo `test -f 'src/profiler.cc' || echo '$(srcdir)/'`src/profiler.cc
 
+sysinfo.lo: src/base/sysinfo.cc
+@am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sysinfo.lo -MD -MP -MF "$(DEPDIR)/sysinfo.Tpo" -c -o sysinfo.lo `test -f 'src/base/sysinfo.cc' || echo '$(srcdir)/'`src/base/sysinfo.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/sysinfo.Tpo" "$(DEPDIR)/sysinfo.Plo"; else rm -f "$(DEPDIR)/sysinfo.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/base/sysinfo.cc' object='sysinfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sysinfo.lo `test -f 'src/base/sysinfo.cc' || echo '$(srcdir)/'`src/base/sysinfo.cc
+
 spinlock.lo: src/base/spinlock.cc
 @am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT spinlock.lo -MD -MP -MF "$(DEPDIR)/spinlock.Tpo" -c -o spinlock.lo `test -f 'src/base/spinlock.cc' || echo '$(srcdir)/'`src/base/spinlock.cc; \
 @am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/spinlock.Tpo" "$(DEPDIR)/spinlock.Plo"; else rm -f "$(DEPDIR)/spinlock.Tpo"; exit 1; fi
@@ -1361,6 +1424,13 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc
 
+libtcmalloc_la-memfs_malloc.lo: src/memfs_malloc.cc
+@am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_la-memfs_malloc.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_la-memfs_malloc.Tpo" -c -o libtcmalloc_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libtcmalloc_la-memfs_malloc.Tpo" "$(DEPDIR)/libtcmalloc_la-memfs_malloc.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_la-memfs_malloc.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/memfs_malloc.cc' object='libtcmalloc_la-memfs_malloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc
+
 libtcmalloc_la-tcmalloc.lo: src/tcmalloc.cc
 @am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_la-tcmalloc.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_la-tcmalloc.Tpo" -c -o libtcmalloc_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc; \
 @am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libtcmalloc_la-tcmalloc.Tpo" "$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_la-tcmalloc.Tpo"; exit 1; fi
@@ -1452,6 +1522,13 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc
 
+libtcmalloc_minimal_la-memfs_malloc.lo: src/memfs_malloc.cc
+@am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_la-memfs_malloc.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_minimal_la-memfs_malloc.Tpo" -c -o libtcmalloc_minimal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libtcmalloc_minimal_la-memfs_malloc.Tpo" "$(DEPDIR)/libtcmalloc_minimal_la-memfs_malloc.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_minimal_la-memfs_malloc.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/memfs_malloc.cc' object='libtcmalloc_minimal_la-memfs_malloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc
+
 libtcmalloc_minimal_la-tcmalloc.lo: src/tcmalloc.cc
 @am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_la-tcmalloc.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Tpo" -c -o libtcmalloc_minimal_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc; \
 @am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Tpo" "$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Tpo"; exit 1; fi
@@ -1522,6 +1599,20 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -c -o frag_unittest-frag_unittest.obj `if test -f 'src/tests/frag_unittest.cc'; then $(CYGPATH_W) 'src/tests/frag_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/frag_unittest.cc'; fi`
 
+getpc_test.o: src/tests/getpc_test.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT getpc_test.o -MD -MP -MF "$(DEPDIR)/getpc_test.Tpo" -c -o getpc_test.o `test -f 'src/tests/getpc_test.cc' || echo '$(srcdir)/'`src/tests/getpc_test.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/getpc_test.Tpo" "$(DEPDIR)/getpc_test.Po"; else rm -f "$(DEPDIR)/getpc_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/tests/getpc_test.cc' object='getpc_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o getpc_test.o `test -f 'src/tests/getpc_test.cc' || echo '$(srcdir)/'`src/tests/getpc_test.cc
+
+getpc_test.obj: src/tests/getpc_test.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT getpc_test.obj -MD -MP -MF "$(DEPDIR)/getpc_test.Tpo" -c -o getpc_test.obj `if test -f 'src/tests/getpc_test.cc'; then $(CYGPATH_W) 'src/tests/getpc_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/getpc_test.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/getpc_test.Tpo" "$(DEPDIR)/getpc_test.Po"; else rm -f "$(DEPDIR)/getpc_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/tests/getpc_test.cc' object='getpc_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o getpc_test.obj `if test -f 'src/tests/getpc_test.cc'; then $(CYGPATH_W) 'src/tests/getpc_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/getpc_test.cc'; fi`
+
 heap_checker_unittest-heap-checker_unittest.o: src/tests/heap-checker_unittest.cc
 @am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_unittest-heap-checker_unittest.o -MD -MP -MF "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo" -c -o heap_checker_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc; \
 @am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo" "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po"; else rm -f "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo"; exit 1; fi
@@ -2141,7 +2232,7 @@
 distdir: $(DISTFILES)
 	$(am__remove_distdir)
 	mkdir $(distdir)
-	$(mkdir_p) $(distdir)/$(top_srcdir) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/src $(distdir)/src/google $(distdir)/src/solaris $(distdir)/src/tests $(distdir)/vsprojects/addressmap_unittest $(distdir)/vsprojects/frag_unittest $(distdir)/vsprojects/libtcmalloc_minimal $(distdir)/vsprojects/low_level_alloc_unittest $(distdir)/vsprojects/markidle_unittest $(distdir)/vsprojects/memalign_unittest $(distdir)/vsprojects/packed-cache_test $(distdir)/vsprojects/system_alloc_unittest $(distdir)/vsprojects/tcmalloc_minimal_large $(distdir)/vsprojects/tcmalloc_minimal_unittest $(distdir)/vsprojects/thread_dealloc_unittest
+	$(mkdir_p) $(distdir)/$(top_srcdir) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/src $(distdir)/src/google $(distdir)/src/solaris $(distdir)/src/tests $(distdir)/vsprojects/addressmap_unittest $(distdir)/vsprojects/frag_unittest $(distdir)/vsprojects/libtcmalloc_minimal $(distdir)/vsprojects/low_level_alloc_unittest $(distdir)/vsprojects/markidle_unittest $(distdir)/vsprojects/memalign_unittest $(distdir)/vsprojects/packed-cache_test $(distdir)/vsprojects/system_alloc_unittest $(distdir)/vsprojects/tcmalloc_minimal_large $(distdir)/vsprojects/tcmalloc_minimal_unittest $(distdir)/vsprojects/tcmalloc_minimal_unittest-static $(distdir)/vsprojects/thread_dealloc_unittest
 	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
 	list='$(DISTFILES)'; for file in $$list; do \
@@ -2168,6 +2259,9 @@
 	    || exit 1; \
 	  fi; \
 	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
+	  dist-hook
 	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
 	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
 	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
@@ -2362,27 +2456,30 @@
 .PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \
 	clean clean-generic clean-libLTLIBRARIES clean-libtool \
 	clean-noinstLTLIBRARIES clean-noinstPROGRAMS ctags dist \
-	dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip \
-	distcheck distclean distclean-compile distclean-generic \
-	distclean-hdr distclean-libtool distclean-tags distcleancheck \
-	distdir distuninstallcheck dvi dvi-am html html-am info \
-	info-am install install-am install-binSCRIPTS install-data \
-	install-data-am install-dist_docDATA install-exec \
-	install-exec-am install-googleincludeHEADERS install-info \
-	install-info-am install-libLTLIBRARIES install-man \
-	install-man1 install-strip installcheck installcheck-am \
-	installdirs maintainer-clean maintainer-clean-generic \
-	mostlyclean mostlyclean-compile mostlyclean-generic \
-	mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
-	uninstall-am uninstall-binSCRIPTS uninstall-dist_docDATA \
-	uninstall-googleincludeHEADERS uninstall-info-am \
-	uninstall-libLTLIBRARIES uninstall-man uninstall-man1
+	dist-all dist-bzip2 dist-gzip dist-hook dist-shar dist-tarZ \
+	dist-zip distcheck distclean distclean-compile \
+	distclean-generic distclean-hdr distclean-libtool \
+	distclean-tags distcleancheck distdir distuninstallcheck dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-binSCRIPTS install-data install-data-am \
+	install-dist_docDATA install-exec install-exec-am \
+	install-googleincludeHEADERS install-info install-info-am \
+	install-libLTLIBRARIES install-man install-man1 install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-binSCRIPTS \
+	uninstall-dist_docDATA uninstall-googleincludeHEADERS \
+	uninstall-info-am uninstall-libLTLIBRARIES uninstall-man \
+	uninstall-man1
 
+@ENABLE_FRAME_POINTER_FALSE@@X86_64_TRUE@  # TODO(csilvers): check if -fomit-frame-pointer might be in $(CXXFLAGS),
+@ENABLE_FRAME_POINTER_FALSE@@X86_64_TRUE@  #                 before setting this.
 pprof_unittest: $(top_srcdir)/src/pprof
 	$(top_srcdir)/src/pprof -test
 # This script preloads libtcmalloc, and calls two other binaries as well
 maybe_threads_unittest.sh$(EXEEXT): $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) \
-                           libtcmalloc.la \
+                           $(LIBTCMALLOC) \
                            low_level_alloc_unittest profiler1_unittest
 	rm -f $@
 	cp -p $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) $@
@@ -2412,6 +2509,11 @@
 
 libtool: $(LIBTOOL_DEPS)
 	$(SHELL) ./config.status --recheck
+
+# Windows wants write permission to .vcproj files and maybe even sln files.
+dist-hook:
+	test -e "$(distdir)/vsprojects" \
+	   && chmod -R u+w $(distdir)/*.sln $(distdir)/vsprojects/
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/README b/README
index d746e55..e171d8f 100644
--- a/README
+++ b/README
@@ -21,11 +21,19 @@
 There are other environment variables, besides CPUPROFILE, you can set
 to adjust the cpu-profiler behavior; cf "ENVIRONMENT VARIABLES" below.
 
+The CPU profiler is available on all unix-based systems we've tested;
+see INSTALL for more details.  It is not currently available on Windows.
+
 
 TCMALLOC
 --------
-Just link in -ltcmalloc to get the advantages of tcmalloc.  See below
-for some environment variables you can use with tcmalloc, as well.
+Just link in -ltcmalloc or -ltcmalloc_minimal to get the advantages of
+tcmalloc -- a replacement for malloc and new.  See below for some
+environment variables you can use with tcmalloc, as well.
+
+tcmalloc functionality is available on all systems we've tested; see
+INSTALL for more details.  See README.windows for instructions on
+using tcmalloc on Windows.
 
 
 HEAP PROFILER
@@ -46,9 +54,12 @@
 didn't compile.
 
 There are other environment variables, besides HEAPPROFILE, you can
-set to adjust the heap-profiler behavior; cf "ENVIRONMENT VARIABLES"
+set to adjust the heap-profiler behavior; c.f. "ENVIRONMENT VARIABLES"
 below.
 
+The heap profiler is available on all unix-based systems we've tested;
+see INSTALL for more details.  It is not currently available on Windows.
+
 
 HEAP CHECKER
 ------------
@@ -74,6 +85,9 @@
 You can also use LD_PRELOAD to heap-check an executable that you
 didn't compile.
 
+The heap checker is only available on Linux at this time; see INSTALL
+for more details.
+
 
 ENVIRONMENT VARIABLES
 ---------------------
@@ -110,9 +124,10 @@
 
 Perftools was developed and tested on x86 Linux systems, and it works
 in its full generality only on those systems.  However, we've
-successfully built and tested the core tcmalloc library
-(tcmalloc_minimal) on FreeBSD, Solaris x86, Darwin (Mac OS X) x86, and
-Windows.  See INSTALL for details.
+successfully ported much of the tcmalloc library to FreeBSD, Solaris
+x86, and Darwin (Mac OS X) x86 and ppc; and we've ported the basic
+functionality in tcmalloc_minimal to Windows.  See INSTALL for details.
+See README.windows for details on the Windows port.
 
 
 PERFORMANCE
@@ -142,7 +157,7 @@
 deadlock with the cpu-profiler, heap-profiler, and heap-checker.
 Its likeliness increases the more dlopen() commands an executable has.
 Most executables don't have any, though several library routines like
-getgrgid() call dlopen() behind the scnees.
+getgrgid() call dlopen() behind the scenes.
 
 2) On x86-64 64-bit systems, while tcmalloc itself works fine, the
 cpu-profiler tool is unreliable: it will sometimes work, but sometimes
@@ -187,4 +202,4 @@
 pthread_mutex_lock!
 
 ---
-12 April 2007
+8 August 2007
diff --git a/README.windows b/README.windows
index 71423d0..fd80d20 100644
--- a/README.windows
+++ b/README.windows
@@ -17,8 +17,20 @@
 
 To use tcmalloc_minimal in your own projects, you should only need to
 build the dll and install it someplace, so you can link it into
-further binaries.  No .h files are needed for the basic use case.
-However, this code should still be considered EXPERIMENTAL.
+further binaries.  Note that the tcmalloc DLL is compiled with
+the "Multithreaded DLL" CRT library -- this is required so we can
+override malloc in user applications.  This means, to use the tcmalloc
+DLL, your applcation must link in the "Multithreaded DLL" CRT library
+as well.  (It is a TODO to try to remove this restriction in the
+future.)
+
+You can also link tcmalloc code in statically -- see the example
+project tcmalloc_minimal_unittest-static, which does this.  For this
+to work, you'll need to add "/D PERFTOOLS_DLL_DECL=" to the compile
+line of every perftools .cc file.  For reasons I don't fully
+understand yet, you still need to use the "DLL" CRT library even when
+statically linking.  Again, you can look at the
+tcmalloc_minimal_unittest-static project, which does this.
 
 I have little experience with Windows programming, so there may be
 better ways to set this up than I've done!  If you run across any
diff --git a/autogen.sh b/autogen.sh
index 5af30c6..9659115 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 # Before using, you should figure out all the .m4 macros that your
-# configure.m4 script needs and make sure they exist in the autoconf/
+# configure.m4 script needs and make sure they exist in the m4/
 # directory.
 #
 # These are the files that this script might edit:
diff --git a/configure b/configure
index 03ab33a..b8e2b13 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for google-perftools 0.92.
+# Generated by GNU Autoconf 2.59 for google-perftools 0.93.
 #
 # Report bugs to <opensource@google.com>.
 #
@@ -423,8 +423,8 @@
 # Identity of this package.
 PACKAGE_NAME='google-perftools'
 PACKAGE_TARNAME='google-perftools'
-PACKAGE_VERSION='0.92'
-PACKAGE_STRING='google-perftools 0.92'
+PACKAGE_VERSION='0.93'
+PACKAGE_STRING='google-perftools 0.93'
 PACKAGE_BUGREPORT='opensource@google.com'
 
 ac_unique_file="README"
@@ -465,7 +465,7 @@
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS UNWIND_LIBS EXTRA_CXXFLAGS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE GCC_TRUE GCC_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBTOOL_DEPS UNWIND_LIBS ENABLE_FRAME_POINTER_TRUE ENABLE_FRAME_POINTER_FALSE X86_64_TRUE X86_64_FALSE acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -954,7 +954,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures google-perftools 0.92 to adapt to many kinds of systems.
+\`configure' configures google-perftools 0.93 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1020,7 +1020,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of google-perftools 0.92:";;
+     short | recursive ) echo "Configuration of google-perftools 0.93:";;
    esac
   cat <<\_ACEOF
 
@@ -1161,7 +1161,7 @@
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-google-perftools configure 0.92
+google-perftools configure 0.93
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1175,7 +1175,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by google-perftools $as_me 0.92, which was
+It was created by google-perftools $as_me 0.93, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1821,7 +1821,7 @@
 
 # Define the identity of the package.
  PACKAGE='google-perftools'
- VERSION='0.92'
+ VERSION='0.93'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3748,6 +3748,16 @@
 
 
 
+
+if test "$GCC" = yes; then
+  GCC_TRUE=
+  GCC_FALSE='#'
+else
+  GCC_TRUE='#'
+  GCC_FALSE=
+fi
+   # let the Makefile know if we're gcc
+
 # Check whether --enable-shared or --disable-shared was given.
 if test "${enable_shared+set}" = set; then
   enableval="$enable_shared"
@@ -4368,7 +4378,7 @@
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 4371 "configure"' > conftest.$ac_ext
+  echo '#line 4381 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -5265,7 +5275,7 @@
 
 
 # Provide some information about the compiler.
-echo "$as_me:5268:" \
+echo "$as_me:5278:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -6326,11 +6336,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6329: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6339: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6333: \$? = $ac_status" >&5
+   echo "$as_me:6343: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -6594,11 +6604,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6597: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6607: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6601: \$? = $ac_status" >&5
+   echo "$as_me:6611: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -6698,11 +6708,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6701: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6711: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:6705: \$? = $ac_status" >&5
+   echo "$as_me:6715: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -9056,7 +9066,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 9059 "configure"
+#line 9069 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -9156,7 +9166,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 9159 "configure"
+#line 9169 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11494,11 +11504,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11497: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11507: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:11501: \$? = $ac_status" >&5
+   echo "$as_me:11511: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -11598,11 +11608,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11601: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11611: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:11605: \$? = $ac_status" >&5
+   echo "$as_me:11615: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -13186,11 +13196,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13189: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13199: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13193: \$? = $ac_status" >&5
+   echo "$as_me:13203: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13290,11 +13300,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13293: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13303: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13297: \$? = $ac_status" >&5
+   echo "$as_me:13307: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -15513,11 +15523,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15516: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15526: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15520: \$? = $ac_status" >&5
+   echo "$as_me:15530: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -15781,11 +15791,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15784: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15794: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15788: \$? = $ac_status" >&5
+   echo "$as_me:15798: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -15885,11 +15895,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15888: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15898: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15892: \$? = $ac_status" >&5
+   echo "$as_me:15902: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -20381,6 +20391,155 @@
 done
       # for stacktrace
 
+for ac_header in ucontext.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to opensource@google.com ##
+## ------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+    # for profiler.cc (cpu profiler)
+
 for ac_header in conflict-signal.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -20530,6 +20689,155 @@
 done
       # defined on some windows platforms
 
+for ac_header in sys/prctl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to opensource@google.com ##
+## ------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+   # for thread_lister (needed by leak-checker)
+
 for ac_header in linux/ptrace.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -20677,9 +20985,9 @@
 fi
 
 done
+# also needed by leak-checker
 
-
-for ac_header in syscall.h
+for ac_header in sys/syscall.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -20828,6 +21136,155 @@
 done
 
 
+for ac_header in fcntl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to opensource@google.com ##
+## ------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+       # for tcmalloc_unittest
+
 for ac_header in grp.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -21125,895 +21582,6 @@
 
 done
          # for heapchecker_unittest
-echo "$as_me:$LINENO: checking for struct sigcontext.sc_eip" >&5
-echo $ECHO_N "checking for struct sigcontext.sc_eip... $ECHO_C" >&6
-if test "${ac_cv_member_struct_sigcontext_sc_eip+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (ac_aggr.sc_eip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_sc_eip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (sizeof ac_aggr.sc_eip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_sc_eip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_sigcontext_sc_eip=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_sigcontext_sc_eip" >&5
-echo "${ECHO_T}$ac_cv_member_struct_sigcontext_sc_eip" >&6
-if test $ac_cv_member_struct_sigcontext_sc_eip = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SIGCONTEXT_SC_EIP 1
-_ACEOF
-
-
-fi
-echo "$as_me:$LINENO: checking for struct ucontext.uc_mcontext" >&5
-echo $ECHO_N "checking for struct ucontext.uc_mcontext... $ECHO_C" >&6
-if test "${ac_cv_member_struct_ucontext_uc_mcontext+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct ucontext ac_aggr;
-if (ac_aggr.uc_mcontext)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_ucontext_uc_mcontext=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct ucontext ac_aggr;
-if (sizeof ac_aggr.uc_mcontext)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_ucontext_uc_mcontext=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_ucontext_uc_mcontext=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_ucontext_uc_mcontext" >&5
-echo "${ECHO_T}$ac_cv_member_struct_ucontext_uc_mcontext" >&6
-if test $ac_cv_member_struct_ucontext_uc_mcontext = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_UCONTEXT_UC_MCONTEXT 1
-_ACEOF
-
-
-fi
-echo "$as_me:$LINENO: checking for struct sigcontext.eip" >&5
-echo $ECHO_N "checking for struct sigcontext.eip... $ECHO_C" >&6
-if test "${ac_cv_member_struct_sigcontext_eip+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (ac_aggr.eip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_eip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (sizeof ac_aggr.eip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_eip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_sigcontext_eip=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_sigcontext_eip" >&5
-echo "${ECHO_T}$ac_cv_member_struct_sigcontext_eip" >&6
-if test $ac_cv_member_struct_sigcontext_eip = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SIGCONTEXT_EIP 1
-_ACEOF
-
-
-fi
-echo "$as_me:$LINENO: checking for struct sigcontext.rip" >&5
-echo $ECHO_N "checking for struct sigcontext.rip... $ECHO_C" >&6
-if test "${ac_cv_member_struct_sigcontext_rip+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (ac_aggr.rip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_rip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (sizeof ac_aggr.rip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_rip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_sigcontext_rip=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_sigcontext_rip" >&5
-echo "${ECHO_T}$ac_cv_member_struct_sigcontext_rip" >&6
-if test $ac_cv_member_struct_sigcontext_rip = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SIGCONTEXT_RIP 1
-_ACEOF
-
-
-fi
-echo "$as_me:$LINENO: checking for struct sigcontext.sc_ip" >&5
-echo $ECHO_N "checking for struct sigcontext.sc_ip... $ECHO_C" >&6
-if test "${ac_cv_member_struct_sigcontext_sc_ip+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (ac_aggr.sc_ip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_sc_ip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (sizeof ac_aggr.sc_ip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_sc_ip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_sigcontext_sc_ip=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_sigcontext_sc_ip" >&5
-echo "${ECHO_T}$ac_cv_member_struct_sigcontext_sc_ip" >&6
-if test $ac_cv_member_struct_sigcontext_sc_ip = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SIGCONTEXT_SC_IP 1
-_ACEOF
-
-
-fi
-echo "$as_me:$LINENO: checking for struct sigcontext.sc_ir" >&5
-echo $ECHO_N "checking for struct sigcontext.sc_ir... $ECHO_C" >&6
-if test "${ac_cv_member_struct_sigcontext_sc_ir+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (ac_aggr.sc_ir)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_sc_ir=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (sizeof ac_aggr.sc_ir)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_sc_ir=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_sigcontext_sc_ir=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_sigcontext_sc_ir" >&5
-echo "${ECHO_T}$ac_cv_member_struct_sigcontext_sc_ir" >&6
-if test $ac_cv_member_struct_sigcontext_sc_ir = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SIGCONTEXT_SC_IR 1
-_ACEOF
-
-
-fi
-echo "$as_me:$LINENO: checking for struct siginfo.si_faddr" >&5
-echo $ECHO_N "checking for struct siginfo.si_faddr... $ECHO_C" >&6
-if test "${ac_cv_member_struct_siginfo_si_faddr+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct siginfo ac_aggr;
-if (ac_aggr.si_faddr)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_siginfo_si_faddr=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct siginfo ac_aggr;
-if (sizeof ac_aggr.si_faddr)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_siginfo_si_faddr=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_siginfo_si_faddr=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_siginfo_si_faddr" >&5
-echo "${ECHO_T}$ac_cv_member_struct_siginfo_si_faddr" >&6
-if test $ac_cv_member_struct_siginfo_si_faddr = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SIGINFO_SI_FADDR 1
-_ACEOF
-
-
-fi
-echo "$as_me:$LINENO: checking for struct sigcontext.regs->nip" >&5
-echo $ECHO_N "checking for struct sigcontext.regs->nip... $ECHO_C" >&6
-if test "${ac_cv_member_struct_sigcontext_regs__nip+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (ac_aggr.regs->nip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_regs__nip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-                  #include <signal.h>
-
-int
-main ()
-{
-static struct sigcontext ac_aggr;
-if (sizeof ac_aggr.regs->nip)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_member_struct_sigcontext_regs__nip=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_member_struct_sigcontext_regs__nip=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_member_struct_sigcontext_regs__nip" >&5
-echo "${ECHO_T}$ac_cv_member_struct_sigcontext_regs__nip" >&6
-if test $ac_cv_member_struct_sigcontext_regs__nip = yes; then
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SIGCONTEXT_REGS__NIP 1
-_ACEOF
-
-
-fi
-
 # We override a lot of memory allocation routines, not all of which are
 # standard.  For those the system doesn't declare, we'll declare ourselves.
 echo "$as_me:$LINENO: checking whether cfree is declared" >&5
@@ -22435,6 +22003,82 @@
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
+# We want to access the "PC" (Program Counter) register from a struct
+# ucontext.  Every system has its own way of doing that.  We try all the
+# possibilities we know about.  Note REG_PC should come first (REG_RIP
+# is also defined on solaris, but does the wrong thing).
+echo "$as_me:$LINENO: checking how to access the program counter from a struct ucontext" >&5
+echo $ECHO_N "checking how to access the program counter from a struct ucontext... $ECHO_C" >&6
+pc_fields="           uc_mcontext.gregs[REG_PC]"  # Solaris x86 (32 + 64 bit)
+pc_fields="$pc_fields uc_mcontext.gregs[REG_EIP]" # Linux (i386)
+pc_fields="$pc_fields uc_mcontext.gregs[REG_RIP]" # Linux (x86_64)
+pc_fields="$pc_fields uc_mcontext.sc_ip"            # Linux (ia64)
+pc_fields="$pc_fields uc_mcontext.mc_eip"           # FreeBSD (i386)
+pc_fields="$pc_fields uc_mcontext.mc_rip"           # FreeBSD (x86_64 [untested])
+pc_fields="$pc_fields uc_mcontext->ss.eip"          # OS X (i386)
+pc_fields="$pc_fields uc_mcontext->ss.rip"          # OS X (x86_64)
+pc_fields="$pc_fields uc_mcontext->ss.srr0"         # OS X (ppc, ppc64 [untested])
+pc_field_found=false
+for pc_field in $pc_fields; do
+  if ! $pc_field_found; then
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _GNU_SOURCE 1
+                    #include <ucontext.h>
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+                   echo "$as_me:$LINENO: result: $pc_field" >&5
+echo "${ECHO_T}$pc_field" >&6
+  		 pc_field_found=true
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  fi
+done
+if ! $pc_field_found; then
+  { echo "$as_me:$LINENO: WARNING: Could not find the PC.  libprofiler will probably not compile!" >&5
+echo "$as_me: WARNING: Could not find the PC.  libprofiler will probably not compile!" >&2;}
+fi
+
 # We want to link in libunwind if it exists
 echo "$as_me:$LINENO: checking for backtrace in -lunwind" >&5
 echo $ECHO_N "checking for backtrace in -lunwind... $ECHO_C" >&6
@@ -22560,13 +22204,24 @@
 is_x86_64=no
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-EXTRA_CXXFLAGS=
-if test "$is_x86_64" = yes -a "$enable_frame_pointer" = "yes"; then
-  EXTRA_CXXFLAGS=-fno-omit-frame-pointer
-elif test "$is_x86_64" = yes -a "$enable_frame_pointer" != "yes"; then
-  # TODO(csilvers): set -DNO_FRAME_POINTER in the Makefile instead, based
-  #                 on the presence of -f[no-]omit-frame-pointer in cxxflags.
-  EXTRA_CXXFLAGS=-DNO_FRAME_POINTER
+
+
+if test "$enable_frame_pointer" = yes; then
+  ENABLE_FRAME_POINTER_TRUE=
+  ENABLE_FRAME_POINTER_FALSE='#'
+else
+  ENABLE_FRAME_POINTER_TRUE='#'
+  ENABLE_FRAME_POINTER_FALSE=
+fi
+
+
+
+if test "$is_x86_64" = yes; then
+  X86_64_TRUE=
+  X86_64_FALSE='#'
+else
+  X86_64_TRUE='#'
+  X86_64_FALSE=
 fi
 
 
@@ -22729,6 +22384,11 @@
 
 
 
+# Also make sure we get standard PRI... definitions, even with glibc.
+# We have to use AH_VERBATIM because we need the #ifdef guard (gcc buglet)
+
+
+
 # Check if __builtin_stack_pointer() is available (for elfcore.h)
 echo "$as_me:$LINENO: checking for __builtin_stack_pointer()" >&5
 echo $ECHO_N "checking for __builtin_stack_pointer()... $ECHO_C" >&6
@@ -23900,7 +23560,7 @@
 int
 main ()
 {
-char c = *program_invocation_name; return 0;
+return *program_invocation_name;
   ;
   return 0;
 }
@@ -24083,6 +23743,27 @@
 Usually this means the macro was only invoked conditionally." >&2;}
    { (exit 1); exit 1; }; }
 fi
+if test -z "${GCC_TRUE}" && test -z "${GCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"GCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"GCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${ENABLE_FRAME_POINTER_TRUE}" && test -z "${ENABLE_FRAME_POINTER_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"ENABLE_FRAME_POINTER\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_FRAME_POINTER\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${X86_64_TRUE}" && test -z "${X86_64_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"X86_64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"X86_64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
 
 : ${CONFIG_STATUS=./config.status}
 ac_clean_files_save=$ac_clean_files
@@ -24354,7 +24035,7 @@
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by google-perftools $as_me 0.92, which was
+This file was extended by google-perftools $as_me 0.93, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -24417,7 +24098,7 @@
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-google-perftools config.status 0.92
+google-perftools config.status 0.93
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -24660,6 +24341,8 @@
 s,@CXXDEPMODE@,$CXXDEPMODE,;t t
 s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t
 s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t
+s,@GCC_TRUE@,$GCC_TRUE,;t t
+s,@GCC_FALSE@,$GCC_FALSE,;t t
 s,@build@,$build,;t t
 s,@build_cpu@,$build_cpu,;t t
 s,@build_vendor@,$build_vendor,;t t
@@ -24682,7 +24365,10 @@
 s,@LIBTOOL@,$LIBTOOL,;t t
 s,@LIBTOOL_DEPS@,$LIBTOOL_DEPS,;t t
 s,@UNWIND_LIBS@,$UNWIND_LIBS,;t t
-s,@EXTRA_CXXFLAGS@,$EXTRA_CXXFLAGS,;t t
+s,@ENABLE_FRAME_POINTER_TRUE@,$ENABLE_FRAME_POINTER_TRUE,;t t
+s,@ENABLE_FRAME_POINTER_FALSE@,$ENABLE_FRAME_POINTER_FALSE,;t t
+s,@X86_64_TRUE@,$X86_64_TRUE,;t t
+s,@X86_64_FALSE@,$X86_64_FALSE,;t t
 s,@acx_pthread_config@,$acx_pthread_config,;t t
 s,@PTHREAD_CC@,$PTHREAD_CC,;t t
 s,@PTHREAD_LIBS@,$PTHREAD_LIBS,;t t
diff --git a/configure.ac b/configure.ac
index 26f6a85..2a9474e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 # make sure we're interpreted by some minimal autoconf
 AC_PREREQ(2.57)
 
-AC_INIT(google-perftools, 0.92, opensource@google.com)
+AC_INIT(google-perftools, 0.93, opensource@google.com)
 # The argument here is just something that should be in the current directory
 # (for sanity checking)
 AC_CONFIG_SRCDIR(README)
@@ -15,6 +15,7 @@
 AC_PROG_CC
 AC_PROG_CPP
 AC_PROG_CXX
+AM_CONDITIONAL(GCC, test "$GCC" = yes)   # let the Makefile know if we're gcc
 
 AC_PROG_LIBTOOL
 AC_SUBST(LIBTOOL_DEPS)
@@ -35,21 +36,14 @@
 AC_CHECK_HEADERS(execinfo.h)    # for stacktrace? and heapchecker_unittest
 AC_CHECK_HEADERS(libunwind.h)   # for stacktrace
 AC_CHECK_HEADERS(unwind.h)      # for stacktrace
+AC_CHECK_HEADERS(ucontext.h)    # for profiler.cc (cpu profiler)
 AC_CHECK_HEADERS(conflict-signal.h)      # defined on some windows platforms
-AC_CHECK_HEADERS(linux/ptrace.h)
-AC_CHECK_HEADERS(syscall.h)
+AC_CHECK_HEADERS(sys/prctl.h)   # for thread_lister (needed by leak-checker)
+AC_CHECK_HEADERS(linux/ptrace.h)# also needed by leak-checker
+AC_CHECK_HEADERS(sys/syscall.h)
+AC_CHECK_HEADERS(fcntl.h)       # for tcmalloc_unittest
 AC_CHECK_HEADERS(grp.h)         # for heapchecker_unittest
 AC_CHECK_HEADERS(pwd.h)         # for heapchecker_unittest
-AC_CHECK_MEMBERS([struct sigcontext.sc_eip,
-                  struct ucontext.uc_mcontext,
-                  struct sigcontext.eip,
-                  struct sigcontext.rip,
-                  struct sigcontext.sc_ip,
-                  struct sigcontext.sc_ir,
-                  struct siginfo.si_faddr,
-		  struct sigcontext.regs->nip],,,
-                 [#define _GNU_SOURCE 1
-                  #include <signal.h>])
 # We override a lot of memory allocation routines, not all of which are
 # standard.  For those the system doesn't declare, we'll declare ourselves.
 AC_CHECK_DECLS([cfree,
@@ -71,6 +65,36 @@
                 AC_MSG_RESULT([yes])],
                [AC_MSG_RESULT([no])])
 
+# We want to access the "PC" (Program Counter) register from a struct
+# ucontext.  Every system has its own way of doing that.  We try all the
+# possibilities we know about.  Note REG_PC should come first (REG_RIP
+# is also defined on solaris, but does the wrong thing).
+AC_MSG_CHECKING([how to access the program counter from a struct ucontext])
+pc_fields="           uc_mcontext.gregs[[REG_PC]]"  # Solaris x86 (32 + 64 bit)
+pc_fields="$pc_fields uc_mcontext.gregs[[REG_EIP]]" # Linux (i386)
+pc_fields="$pc_fields uc_mcontext.gregs[[REG_RIP]]" # Linux (x86_64)
+pc_fields="$pc_fields uc_mcontext.sc_ip"            # Linux (ia64)
+pc_fields="$pc_fields uc_mcontext.mc_eip"           # FreeBSD (i386)
+pc_fields="$pc_fields uc_mcontext.mc_rip"           # FreeBSD (x86_64 [untested])
+pc_fields="$pc_fields uc_mcontext->ss.eip"          # OS X (i386)
+pc_fields="$pc_fields uc_mcontext->ss.rip"          # OS X (x86_64)
+pc_fields="$pc_fields uc_mcontext->ss.srr0"         # OS X (ppc, ppc64 [untested])
+pc_field_found=false
+for pc_field in $pc_fields; do
+  if ! $pc_field_found; then
+    AC_TRY_COMPILE([#define _GNU_SOURCE 1
+                    #include <ucontext.h>],
+                   [ucontext_t u; return u.$pc_field == 0;],
+                   AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
+                                      How to access the PC from a struct ucontext)
+                   AC_MSG_RESULT([$pc_field])
+  		 pc_field_found=true)
+  fi
+done
+if ! $pc_field_found; then
+  AC_MSG_WARN(Could not find the PC.  libprofiler will probably not compile!)
+fi
+
 # We want to link in libunwind if it exists
 AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind, UNWIND_LIBS=)
 AC_SUBST(UNWIND_LIBS)
@@ -83,19 +107,20 @@
 	      , enable_frame_pointer=no)
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __x86_64__ == 1 ? 0 : 1])],
                   [is_x86_64=yes], [is_x86_64=no])
-EXTRA_CXXFLAGS=
-if test "$is_x86_64" = yes -a "$enable_frame_pointer" = "yes"; then
-  EXTRA_CXXFLAGS=-fno-omit-frame-pointer
-elif test "$is_x86_64" = yes -a "$enable_frame_pointer" != "yes"; then
-  # TODO(csilvers): set -DNO_FRAME_POINTER in the Makefile instead, based
-  #                 on the presence of -f[no-]omit-frame-pointer in cxxflags.
-  EXTRA_CXXFLAGS=-DNO_FRAME_POINTER
-fi
-AC_SUBST(EXTRA_CXXFLAGS)
+AM_CONDITIONAL(ENABLE_FRAME_POINTER, test "$enable_frame_pointer" = yes)
+AM_CONDITIONAL(X86_64, test "$is_x86_64" = yes)
 
 # Defines PRIuS
 AC_COMPILER_CHARACTERISTICS
 
+# Also make sure we get standard PRI... definitions, even with glibc.
+# We have to use AH_VERBATIM because we need the #ifdef guard (gcc buglet)
+AH_VERBATIM([__STDC_FORMAT_MACROS],
+            [/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif])
+
 # Check if __builtin_stack_pointer() is available (for elfcore.h)
 AC_MSG_CHECKING([for __builtin_stack_pointer()])
 AC_LINK_IFELSE([AC_LANG_PROGRAM(, [void *sp = __builtin_stack_pointer()])],
diff --git a/google-perftools.sln b/google-perftools.sln
index f3e9759..5b5b495 100755
--- a/google-perftools.sln
+++ b/google-perftools.sln
@@ -50,6 +50,10 @@
 		{55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} = {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}

 	EndProjectSection

 EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcmalloc_minimal_unittest-static", "vsprojects\tcmalloc_minimal_unittest-static\tcmalloc_minimal_unittest-static.vcproj", "{8F708DCB-7EE4-4BA0-81AA-A52A0BA73B74}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

 Global

 	GlobalSection(SolutionConfiguration) = preSolution

 		Debug = Debug

@@ -102,6 +106,10 @@
 		{6CFFBD0F-09E3-4282-A711-0564451FDF74}.Debug.Build.0 = Debug|Win32

 		{6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release.ActiveCfg = Release|Win32

 		{6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release.Build.0 = Release|Win32

+		{8F708DCB-7EE4-4BA0-81AA-A52A0BA73B74}.Debug.ActiveCfg = Debug|Win32

+		{8F708DCB-7EE4-4BA0-81AA-A52A0BA73B74}.Debug.Build.0 = Debug|Win32

+		{8F708DCB-7EE4-4BA0-81AA-A52A0BA73B74}.Release.ActiveCfg = Release|Win32

+		{8F708DCB-7EE4-4BA0-81AA-A52A0BA73B74}.Release.Build.0 = Release|Win32

 	EndGlobalSection

 	GlobalSection(ExtensibilityGlobals) = postSolution

 	EndGlobalSection

diff --git a/m4/program_invocation_name.m4 b/m4/program_invocation_name.m4
index 19833e7..6161f66 100644
--- a/m4/program_invocation_name.m4
+++ b/m4/program_invocation_name.m4
@@ -1,9 +1,13 @@
+# We need to be careful to avoid having the reference to
+# program_invocation_name optimized out.  We do that by
+# returning the value.
+
 AC_DEFUN([AC_PROGRAM_INVOCATION_NAME],
   [AC_CACHE_CHECK(
     for program_invocation_name,
     ac_cv_have_program_invocation_name,
     AC_TRY_LINK([extern char* program_invocation_name;],
-	        [char c = *program_invocation_name; return 0; ],
+	        [return *program_invocation_name;],
 	        [ac_cv_have_program_invocation_name=yes],
 		[ac_cv_have_program_invocation_name=no])
    )
diff --git a/packages/deb/changelog b/packages/deb/changelog
index 950edb0..e26ba9a 100644
--- a/packages/deb/changelog
+++ b/packages/deb/changelog
@@ -1,3 +1,9 @@
+google-perftools (0.93-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Google Inc. <opensource@google.com>  Fri, 17 Aug 2007 12:32:56 -0700
+
 google-perftools (0.92-1) unstable; urgency=low
 
   * New upstream release.
diff --git a/src/addressmap-inl.h b/src/addressmap-inl.h
index 2241b9b..7760710 100644
--- a/src/addressmap-inl.h
+++ b/src/addressmap-inl.h
@@ -96,7 +96,7 @@
  public:
   typedef void* (*Allocator)(size_t);
   typedef void  (*DeAllocator)(void*);
-  typedef void* Key;
+  typedef const void* Key;
 
   // Create an AddressMap that uses the specified allocator/deallocator.
   // The allocator/deallocator should behave like malloc/free.
diff --git a/src/base/basictypes.h b/src/base/basictypes.h
index cbfa2db..d9d2774 100644
--- a/src/base/basictypes.h
+++ b/src/base/basictypes.h
@@ -37,13 +37,12 @@
 //    AC_HEADER_STDC              /* for stdint_h and inttypes_h */
 //    AC_CHECK_TYPES([__int64])   /* defined in some windows platforms */
 
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>           // uint16_t might be here; PRId64 too.
+#endif
 #ifdef HAVE_STDINT_H
 #include <stdint.h>             // to get uint16_t (ISO naming madness)
 #endif
-#ifdef HAVE_INTTYPES_H
-#define __STDC_FORMAT_MACROS    // gets us PRId64, etc.
-#include <inttypes.h>           // uint16_t might be here; PRId64 too.
-#endif
 #include <sys/types.h>          // our last best hope for uint16_t
 
 // Standard typedefs
@@ -179,39 +178,101 @@
 
 #ifdef HAVE___ATTRIBUTE__
 # define ATTRIBUTE_WEAK  __attribute__((weak))
-# ifdef __MACH__   // Mach-O has a slightly different format from coff and elf
-#  define ATTRIBUTE_SECTION(name) __attribute__ ((section ("__DATA, " #name)))
-# else
-#  define ATTRIBUTE_SECTION(name) __attribute__ ((section (#name)))
-# endif
-# ifdef __ELF__   // only gcc/elf seems to define the __start_foo/__stop_foo :(
-#   define DECLARE_ATTRIBUTE_SECTION(name) \
-      extern char __start_##name[] ATTRIBUTE_WEAK; \
-      extern char __stop_##name[] ATTRIBUTE_WEAK;
-    // Return void* pointers to start/end of a section of code with functions
-    // having ATTRIBUTE_SECTION(name), or 0 if no such function exists.
-    // One must DECLARE_ATTRIBUTE_SECTION(name) for this to compile and link.
-#   define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name))
-#   define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
-# endif
-#endif
-
-// Complicated logic above!  Now we simply go with the default for
-// everything that hasn't been set to something special.
-#ifndef ATTRIBUTE_WEAK
+#else
 # define ATTRIBUTE_WEAK
 #endif
-#ifndef ATTRIBUTE_SECTION
+
+// Section attributes are supported for both ELF and Mach-O, but in
+// very different ways.  Here's the API we provide:
+// 1) ATTRIBUTE_SECTION: put this with the declaration of all functions
+//    you want to be in the same linker section
+// 2) DEFINE_ATTRIBUTE_SECTION_VARS: must be called once per unique
+//    name.  You want to make sure this is executed before any
+//    DECLARE_ATTRIBUTE_SECTION_VARS; the easiest way is to put them
+//    in the same .cc file.  Put this call at the global level.
+// 3) INIT_ATTRIBUTE_SECTION_VARS: you can scatter calls to this in
+//    multiple places to help ensure execution before any
+//    DECLARE_ATTRIBUTE_SECTION_VARS.  You must have at least one
+//    DEFINE, but you can have many INITs.  Put each in its own scope.
+// 4) DECLARE_ATTRIBUTE_SECTION_VARS: must be called before using
+//    ATTRIBUTE_SECTION_START or ATTRIBUTE_SECTION_STOP on a name.
+//    Put this call at the global level.
+// 5) ATTRIBUTE_SECTION_START/ATTRIBUTE_SECTION_STOP: call this to say
+//    where in memory a given section is.  All functions declared with
+//    ATTRIBUTE_SECTION are guaranteed to be between START and STOP.
+
+#if defined(HAVE___ATTRIBUTE__) && defined(__ELF__)
+# define ATTRIBUTE_SECTION(name) __attribute__ ((section (#name)))
+
+  // Weak section declaration to be used as a global declaration
+  // for ATTRIBUTE_SECTION_START|STOP(name) to compile and link
+  // even without functions with ATTRIBUTE_SECTION(name).
+# define DECLARE_ATTRIBUTE_SECTION_VARS(name) \
+    extern char __start_##name[] ATTRIBUTE_WEAK; \
+    extern char __stop_##name[] ATTRIBUTE_WEAK
+# define INIT_ATTRIBUTE_SECTION_VARS(name)     // no-op for ELF
+# define DEFINE_ATTRIBUTE_SECTION_VARS(name)   // no-op for ELF
+
+  // Return void* pointers to start/end of a section of code with functions
+  // having ATTRIBUTE_SECTION(name), or 0 if no such function exists.
+  // One must DECLARE_ATTRIBUTE_SECTION(name) for this to compile and link.
+# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
+# define HAVE_ATTRIBUTE_SECTION_START 1
+
+#elif defined(HAVE___ATTRIBUTE__) && defined(__MACH__)
+# define ATTRIBUTE_SECTION(name) __attribute__ ((section ("__DATA, " #name)))
+
+#include <mach-o/getsect.h>
+#include <mach-o/dyld.h>
+class AssignAttributeStartEnd {
+ public:
+  AssignAttributeStartEnd(const char* name, char** pstart, char** pend) {
+    // Find out what dynamic library name is defined in
+    if (_dyld_present()) {
+      for (int i = _dyld_image_count() - 1; i >= 0; --i) {
+        const mach_header* hdr = _dyld_get_image_header(i);
+        uint32_t len;
+        *pstart = getsectdatafromheader(hdr, "__DATA", name, &len);
+        if (*pstart) {   // NULL if not defined in this dynamic library
+          *pstart += _dyld_get_image_vmaddr_slide(i);   // correct for reloc
+          *pend = *pstart + len;
+          return;
+        }
+      }
+    }
+    // If we get here, not defined in a dll at all.  See if defined statically.
+    unsigned long len;    // don't ask me why this type isn't uint32_t too...
+    *pstart = getsectdata("__DATA", name, &len);
+    *pend = *pstart + len;
+  }
+};
+
+#define DECLARE_ATTRIBUTE_SECTION_VARS(name)    \
+  extern char* __start_##name;                  \
+  extern char* __stop_##name
+
+#define INIT_ATTRIBUTE_SECTION_VARS(name)               \
+  DECLARE_ATTRIBUTE_SECTION_VARS(name);                 \
+  static const AssignAttributeStartEnd __assign_##name( \
+    #name, &__start_##name, &__stop_##name)
+
+#define DEFINE_ATTRIBUTE_SECTION_VARS(name)     \
+  char* __start_##name, *__stop_##name;         \
+  INIT_ATTRIBUTE_SECTION_VARS(name)
+
+# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
+# define HAVE_ATTRIBUTE_SECTION_START 1
+
+#else  // not HAVE___ATTRIBUTE__ && __ELF__, nor HAVE___ATTRIBUTE__ && __MACH__
 # define ATTRIBUTE_SECTION(name)
-#endif
-#ifndef DECLARE_ATTRIBUTE_SECTION
-# define DECLARE_ATTRIBUTE_SECTION(name)
-#endif
-#ifndef ATTRIBUTE_SECTION_START
+# define DECLARE_ATTRIBUTE_SECTION_VARS(name)
+# define INIT_ATTRIBUTE_SECTION_VARS(name)
+# define DEFINE_ATTRIBUTE_SECTION_VARS(name)
 # define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(0))
-#endif
-#ifndef ATTRIBUTE_SECTION_STOP
 # define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(0))
-#endif
+
+#endif  // HAVE___ATTRIBUTE__ and __ELF__ or __MACH__
 
 #endif  // _BASICTYPES_H_
diff --git a/src/base/logging.h b/src/base/logging.h
index 673d18a..95035b3 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -47,6 +47,19 @@
 #include <errno.h>     // for errno
 #include "base/commandlineflags.h"
 
+// On some systems (like freebsd), we can't call write() at all in a
+// global constructor, perhaps because errno hasn't been set up.
+// Calling the write syscall is safer (it doesn't set errno), so we
+// prefer that.  Note we don't care about errno for logging: we just
+// do logging on a best-effort basis.
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#define WRITE_TO_STDERR(buf, len) syscall(SYS_write, STDERR_FILENO, buf, len)
+#else
+#define WRITE_TO_STDERR(buf, len) write(STDERR_FILENO, buf, len)
+#endif
+
+
 // We log all messages at this log-level and below.
 // INFO == -1, WARNING == -2, ERROR == -3, FATAL == -4
 DECLARE_int32(verbose);
@@ -57,23 +70,23 @@
 //    CHECK(fp->Write(x) == 4)
 // Note we use write instead of printf/puts to avoid the risk we'll
 // call malloc().
-#define CHECK(condition)                                        \
-  do {                                                          \
-    if (!(condition)) {                                         \
-      write(STDERR_FILENO, "Check failed: " #condition "\n",    \
-            sizeof("Check failed: " #condition "\n")-1);        \
-      exit(1);                                                  \
-    }                                                           \
+#define CHECK(condition)                                                \
+  do {                                                                  \
+    if (!(condition)) {                                                 \
+      WRITE_TO_STDERR("Check failed: " #condition "\n",                 \
+                      sizeof("Check failed: " #condition "\n")-1);      \
+      exit(1);                                                          \
+    }                                                                   \
   } while (0)
 
 // This takes a message to print.  The name is historical.
-#define RAW_CHECK(condition, message)                                      \
-  do {                                                                     \
-    if (!(condition)) {                                                    \
-      write(STDERR_FILENO, "Check failed: " #condition ": " message "\n",  \
-            sizeof("Check failed: " #condition ": " message "\n")-1);      \
-      exit(1);                                                             \
-    }                                                                      \
+#define RAW_CHECK(condition, message)                                          \
+  do {                                                                         \
+    if (!(condition)) {                                                        \
+      WRITE_TO_STDERR("Check failed: " #condition ": " message "\n",           \
+                      sizeof("Check failed: " #condition ": " message "\n")-1);\
+      exit(1);                                                                 \
+    }                                                                          \
   } while (0)
 
 // This is like RAW_CHECK, but only in debug-mode
@@ -91,10 +104,10 @@
   do {                                                                  \
     if (!(condition)) {                                                 \
       const int err_no = errno;                                         \
-      write(STDERR_FILENO, "Check failed: " #condition ": ",            \
-            sizeof("Check failed: " #condition ": ")-1);                \
-      write(STDERR_FILENO, strerror(err_no), strlen(strerror(err_no))); \
-      write(STDERR_FILENO, "\n", sizeof("\n")-1);                       \
+      WRITE_TO_STDERR("Check failed: " #condition ": ",                 \
+                      sizeof("Check failed: " #condition ": ")-1);      \
+      WRITE_TO_STDERR(strerror(err_no), strlen(strerror(err_no)));      \
+      WRITE_TO_STDERR("\n", sizeof("\n")-1);                            \
       exit(1);                                                          \
     }                                                                   \
   } while (0)
@@ -123,6 +136,9 @@
 #define CHECK_GE(val1, val2) CHECK_OP(>=, val1, val2)
 #define CHECK_GT(val1, val2) CHECK_OP(> , val1, val2)
 
+// Used for (libc) functions that return -1 and set errno
+#define CHECK_ERR(invocation)  PCHECK((invocation) != -1)
+
 // A few more checks that only happen in debug mode
 #ifdef NDEBUG
 #define DCHECK_EQ(val1, val2)
@@ -156,7 +172,7 @@
     assert(strlen(buf)+1 < sizeof(buf));
     strcat(buf, "\n");
   }
-  write(STDERR_FILENO, buf, strlen(buf));
+  WRITE_TO_STDERR(buf, strlen(buf));
   if ((severity) == FATAL)
     abort(); // LOG(FATAL) indicates a big problem, so don't run atexit() calls
 }
diff --git a/src/base/sysinfo.cc b/src/base/sysinfo.cc
index 445b65e..4c06782 100644
--- a/src/base/sysinfo.cc
+++ b/src/base/sysinfo.cc
@@ -35,20 +35,39 @@
 #include <stdio.h>    // for snprintf(), sscanf()
 #include <string.h>   // for memmove(), memchr(), etc.
 #include <fcntl.h>    // for open()
+#include <errno.h>    // for errno
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>   // for read()
 #endif
+#if defined __MACH__          // Mac OS X, almost certainly
+#include <mach-o/dyld.h>      // for iterating over dll's in ProcMapsIter
+#include <mach-o/loader.h>    // for iterating over dll's in ProcMapsIter
+#elif defined __sun__         // Solaris
+#include <procfs.h>           // for, e.g., prmap_t
+#endif
 #include "base/sysinfo.h"
 #include "base/commandlineflags.h"
 #include "base/logging.h"
 
-DEFINE_string(procfs_prefix, "", "string to prepend to filenames opened "
-              "via OpenProcFile");
+#if defined(WIN32) && defined(MODULEENTRY32)
+// In a change from the usual W-A pattern, there is no A variant of
+// MODULEENTRY32.  Tlhelp32.h #defines the W variant, but not the A.
+// We want the original A variants, and this #undef is the only
+// way I see to get them.
+#undef MODULEENTRY32
+#undef Module32First
+#undef Module32Next
+#undef PMODULEENTRY32
+#undef LPMODULEENTRY32
+#endif
+
+// Re-run fn until it doesn't cause EINTR.
+#define NO_INTR(fn)  do {} while ((fn) < 0 && errno == EINTR)
 
 // open/read/close can set errno, which may be illegal at this
 // time, so prefer making the syscalls directly if we can.
-#ifdef HAVE_SYSCALL_H
-# include <syscall.h>
+#ifdef HAVE_SYS_SYSCALL_H
+# include <sys/syscall.h>
 # define safeopen(filename, mode)  syscall(SYS_open, filename, mode)
 # define saferead(fd, buffer, size)  syscall(SYS_read, fd, buffer, size)
 # define safeclose(fd)  syscall(SYS_close, fd)
@@ -64,16 +83,12 @@
   static char envbuf[16<<10];
   if (*envbuf == '\0') {    // haven't read the environ yet
     int fd = safeopen("/proc/self/environ", O_RDONLY);
-    if (fd == -1) {         // unable to open the file, fall back onto libc
-      RAW_LOG(WARNING, "Unable to open /proc/self/environ, falling back "
-                       "on getenv(\"%s\"), which may not work", name);
-      return getenv(name);
-    }
-    // The -2 here guarantees the last two bytes of the buffer will be \0\0
-    if (saferead(fd, envbuf, sizeof(envbuf) - 2) < 0) {   // error reading file
-      safeclose(fd);
-      RAW_LOG(WARNING, "Unable to read from /proc/self/environ, falling back "
-                       "on getenv(\"%s\"), which may not work", name);
+    // The -2 below guarantees the last two bytes of the buffer will be \0\0
+    if (fd == -1 ||           // unable to open the file, fall back onto libc
+        saferead(fd, envbuf, sizeof(envbuf) - 2) < 0) { // error reading file
+      RAW_VLOG(1, "Unable to open /proc/self/environ, falling back "
+               "on getenv(\"%s\"), which may not work", name);
+      if (fd != -1) safeclose(fd);
       return getenv(name);
     }
     safeclose(fd);
@@ -92,23 +107,15 @@
   return NULL;                   // env var never found
 }
 
+
+#if defined __linux__ || defined __FreeBSD__ || defined __sun__
 static void ConstructFilename(const char* spec, pid_t pid,
                               char* buf, int buf_size) {
-  // We are duplicating the code here for performance.
-  // The second call requires constructing a new string object
-  // and then destructing it again, which is a waste if
-  // the string ends up being the same as the passed in cstring
-  // anyway.
-  if (FLAGS_procfs_prefix.empty()) {
-    CHECK_LT(snprintf(buf, buf_size,
-                      spec,
-                      pid ? pid : getpid()), buf_size);
-  } else {
-    CHECK_LT(snprintf(buf, buf_size,
-                      (FLAGS_procfs_prefix + spec).c_str(),
-                      pid ? pid : getpid()), buf_size);
-  }
+  CHECK_LT(snprintf(buf, buf_size,
+                    spec,
+                    pid ? pid : getpid()), buf_size);
 }
+#endif
 
 ProcMapsIterator::ProcMapsIterator(pid_t pid) {
   Init(pid, NULL, false);
@@ -131,8 +138,9 @@
     // If the user didn't pass in any buffer storage, allocate it
     // now. This is the normal case; the signal handler passes in a
     // static buffer.
-    dynamic_buffer_ = new Buffer;
-    buffer = dynamic_buffer_;
+    buffer = dynamic_buffer_ = new Buffer;
+  } else {
+    dynamic_buffer_ = NULL;
   }
 
   ibuf_ = buffer->buf_;
@@ -141,23 +149,72 @@
   ebuf_ = ibuf_ + Buffer::kBufSize - 1;
   nextline_ = ibuf_;
 
-  if (use_maps_backing) {
-    ConstructFilename("/proc/%d/maps_backing", pid,
-                      ibuf_, Buffer::kBufSize);
+#if defined(__linux__)
+  if (use_maps_backing) {  // don't bother with clever "self" stuff in this case
+    ConstructFilename("/proc/%d/maps_backing", pid, ibuf_, Buffer::kBufSize);
+  } else if (pid == 0) {
+    // We have to kludge a bit to deal with the args ConstructFilename
+    // expects.  The 1 is never used -- it's only impt. that it's not 0.
+    ConstructFilename("/proc/self/maps", 1, ibuf_, Buffer::kBufSize);
   } else {
-    ConstructFilename("/proc/%d/maps", pid,
-                      ibuf_, Buffer::kBufSize);
+    ConstructFilename("/proc/%d/maps", pid, ibuf_, Buffer::kBufSize);
   }
-
   // No error logging since this can be called from the crash dump
   // handler at awkward moments. Users should call Valid() before
   // using.
-  fd_ = open(ibuf_, O_RDONLY);
+  NO_INTR(fd_ = open(ibuf_, O_RDONLY));
+#elif defined(__FreeBSD__)
+  // We don't support maps_backing on freebsd
+  if (pid == 0) {
+    ConstructFilename("/proc/curproc/map", 1, ibuf_, Buffer::kBufSize);
+  } else {
+    ConstructFilename("/proc/%d/map", pid, ibuf_, Buffer::kBufSize);
+  }
+  NO_INTR(fd_ = open(ibuf_, O_RDONLY));
+#elif defined(__sun__)
+  if (pid == 0) {
+    ConstructFilename("/proc/self/map", 1, ibuf_, Buffer::kBufSize);
+  } else {
+    ConstructFilename("/proc/%d/map", pid, ibuf_, Buffer::kBufSize);
+  }
+  NO_INTR(fd_ = open(ibuf_, O_RDONLY));
+#elif defined(__MACH__)
+  if (_dyld_present())
+    current_image_ = _dyld_image_count();   // count down from the top
+  else
+    current_image_ = -1;
+  current_load_cmd_ = -1;
+#elif defined(WIN32)
+  snapshot_ = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE |
+                                       TH32CS_SNAPMODULE32,
+                                       GetCurrentProcessId());
+  memset(&module_, 0, sizeof(module_));
+#else
+  fd_ = -1;   // so Valid() is always false
+#endif
+
 }
 
 ProcMapsIterator::~ProcMapsIterator() {
   delete dynamic_buffer_;
-  if (fd_ != -1) close(fd_);
+#if defined(WIN32)
+  if (snapshot_ != INVALID_HANDLE_VALUE) CloseHandle(snapshot_);
+#elif defined(__MACH__)
+  // no cleanup necessary!
+#else
+  if (fd_ >= 0) NO_INTR(close(fd_));
+#endif
+  delete dynamic_buffer_;
+}
+
+bool ProcMapsIterator::Valid() const {
+#if defined(WIN32)
+  return snapshot_ != INVALID_HANDLE_VALUE;
+#elif defined(__MACH__)
+  return _dyld_present();
+#else
+  return fd_ != -1;
+#endif
 }
 
 bool ProcMapsIterator::Next(uint64 *start, uint64 *end, char **flags,
@@ -175,6 +232,7 @@
                                uint64 *anon_mapping, uint64 *anon_pages,
                                dev_t *dev) {
 
+#if defined(__linux__) || defined(__FreeBSD__)
   do {
     // Advance to the start of the next line
     stext_ = nextline_;
@@ -191,8 +249,12 @@
       etext_ = ibuf_ + count;
 
       int nread = 0;            // fill up buffer with text
-      while (etext_ < ebuf_ && (nread = read(fd_, etext_, ebuf_ - etext_)) > 0) {
-        etext_ += nread;
+      while (etext_ < ebuf_) {
+        NO_INTR(nread = read(fd_, etext_, ebuf_ - etext_));
+        if (nread > 0)
+          etext_ += nread;
+        else
+          break;
       }
 
       // Zero out remaining characters in buffer at EOF to avoid returning
@@ -210,16 +272,34 @@
     int64 tmpinode;
     int major, minor;
     unsigned filename_offset;
-    if (sscanf(stext_, "%llx-%llx %4s %llx %x:%x %lld %n",
+#if defined(__linux__)  // for now, assume all linuxes have the same format
+    if (sscanf(stext_, "%"SCNx64"-%"SCNx64" %4s %"SCNx64" %x:%x %"SCNd64" %n",
                start ? start : &tmpstart,
                end ? end : &tmpend,
                flags_,
                offset ? offset : &tmpoffset,
                &major, &minor,
                inode ? inode : &tmpinode, &filename_offset) != 7) continue;
+#elif defined(__FreeBSD__)
+    // For the format, see http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/fs/procfs/procfs_map.c?rev=1.31&content-type=text/x-cvsweb-markup
+    tmpstart = tmpend = tmpoffset = 0;
+    tmpinode = 0;
+    major = minor = 0;   // can't get this info in freebsd
+    if (inode)
+      *inode = 0;        // nor this
+    if (offset)
+      *offset = 0;       // seems like this should be in there, but maybe not
+    // start end resident privateresident obj(?) prot refcnt shadowcnt
+    // flags copy_on_write needs_copy type filename:
+    // 0x8048000 0x804a000 2 0 0xc104ce70 r-x 1 0 0x0 COW NC vnode /bin/cat
+    if (sscanf(stext_, "0x%"SCNx64" 0x%"SCNx64" %*d %*d %*p %3s %*d %*d 0x%*x %*s %*s %*s %n",
+               start ? start : &tmpstart,
+               end ? end : &tmpend,
+               flags_,
+               &filename_offset) != 3) continue;
+#endif
 
     // We found an entry
-
     if (flags) *flags = flags_;
     if (filename) *filename = stext_ + filename_offset;
     if (dev) *dev = minor | (major << 8);
@@ -240,7 +320,7 @@
             uint64 tmp_anon_mapping;
             uint64 tmp_anon_pages;
 
-            sscanf(backing_ptr+1, "F %llx %lld) (A %llx %lld)",
+            sscanf(backing_ptr+1, "F %"SCNx64" %"SCNd64") (A %"SCNx64" %"SCNd64")",
                    file_mapping ? file_mapping : &tmp_file_mapping,
                    file_pages ? file_pages : &tmp_file_pages,
                    anon_mapping ? anon_mapping : &tmp_anon_mapping,
@@ -256,7 +336,121 @@
 
     return true;
   } while (etext_ > ibuf_);
+#elif defined(__sun__)
+  // This is based on MA_READ == 4, MA_WRITE == 2, MA_EXEC == 1
+  static char kPerms[8][4] = { "---", "--x", "-w-", "-wx",
+                               "r--", "r-x", "rw-", "rwx" };
+  COMPILE_ASSERT(MA_READ == 4, solaris_ma_read_must_equal_4);
+  COMPILE_ASSERT(MA_WRITE == 2, solaris_ma_write_must_equal_2);
+  COMPILE_ASSERT(MA_EXEC == 1, solaris_ma_exec_must_equal_1);
+  int nread = 0;            // fill up buffer with text
+  NO_INTR(nread = read(fd_, ibuf_, sizeof(prmap_t)));
+  if (nread == sizeof(prmap_t)) {
+    long inode_from_mapname = 0;
+    prmap_t* mapinfo = reinterpret_cast<prmap_t*>(ibuf_);
+    // Best-effort attempt to get the inode from the filename.  I think the
+    // two middle ints are major and minor device numbers, but I'm not sure.
+    sscanf(mapinfo->pr_mapname, "ufs.%*d.%*d.%ld", &inode_from_mapname);
+
+    if (start) *start = mapinfo->pr_vaddr;
+    if (end) *end = mapinfo->pr_vaddr + mapinfo->pr_size;
+    if (flags) *flags = kPerms[mapinfo->pr_mflags & 7];
+    if (offset) *offset = mapinfo->pr_offset;
+    if (inode) *inode = inode_from_mapname;
+    // TODO(csilvers): How to map from /proc/map/object to filename?
+    if (filename) *filename = mapinfo->pr_mapname;  // format is ufs.?.?.inode
+    if (file_mapping) *file_mapping = 0;
+    if (file_pages) *file_pages = 0;
+    if (anon_mapping) *anon_mapping = 0;
+    if (anon_pages) *anon_pages = 0;
+    if (dev) *dev = 0;
+    return true;
+  }
+#elif defined(__MACH__)
+  static char kDefaultPerms[5] = "r-xp";
+  // We return a separate entry for each segment in the DLL. (TODO(csilvers):
+  // can we do better?)  A DLL ("image") has load-commands, some of which
+  // talk about segment boundaries.
+  // cf image_for_address from http://svn.digium.com/view/asterisk/team/oej/minivoicemail/dlfcn.c?revision=53912
+  for (; current_image_ >= 0; current_image_--) {
+    const mach_header* hdr = _dyld_get_image_header(current_image_);
+    if (!hdr) continue;
+    if (current_load_cmd_ < 0)   // set up for this image
+      current_load_cmd_ = hdr->ncmds;  // again, go from the top down
+
+    // We start with the next load command (we've already looked at this one).
+    for (current_load_cmd_--; current_load_cmd_ >= 0; current_load_cmd_--) {
+      const char* lc = ((const char *)hdr + sizeof(struct mach_header));
+      // TODO(csilvers): make this not-quadradic (increment and hold state)
+      for (int j = 0; j < current_load_cmd_; j++)  // advance to *our* load_cmd
+        lc += ((const load_command *)lc)->cmdsize;
+      if (((const load_command *)lc)->cmd == LC_SEGMENT) {
+        const intptr_t dlloff = _dyld_get_image_vmaddr_slide(current_image_);
+        const segment_command* sc = (const segment_command *)lc;
+        if (start) *start = sc->vmaddr + dlloff;
+        if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
+        if (flags) *flags = kDefaultPerms;  // can we do better?
+        if (offset) *offset = sc->fileoff;
+        if (inode) *inode = 0;
+        if (filename)
+          *filename = const_cast<char*>(_dyld_get_image_name(current_image_));
+        if (file_mapping) *file_mapping = 0;
+        if (file_pages) *file_pages = 0;   // could we use sc->filesize?
+        if (anon_mapping) *anon_mapping = 0;
+        if (anon_pages) *anon_pages = 0;
+        if (dev) *dev = 0;
+        return true;
+      }
+    }
+    // If we get here, no more load_cmd's in this image talk about
+    // segments.  Go on to the next image.
+  }
+#elif defined(WIN32)
+  static char kDefaultPerms[5] = "r-xp";
+  BOOL ok;
+  if (module_.dwSize == 0) {  // only possible before first call
+    module_.dwSize = sizeof(module_);
+    ok = Module32First(snapshot_, &module_);
+  } else {
+    ok = Module32Next(snapshot_, &module_);
+  }
+  if (ok) {
+    uint64 base_addr = reinterpret_cast<DWORD_PTR>(module_.modBaseAddr);
+    if (start) *start = base_addr;
+    if (end) *end = base_addr + module_.modBaseSize;
+    if (flags) *flags = kDefaultPerms;
+    if (offset) *offset = 0;
+    if (inode) *inode = 0;
+    if (filename) *filename = module_.szExePath;
+    if (file_mapping) *file_mapping = 0;
+    if (file_pages) *file_pages = 0;
+    if (anon_mapping) *anon_mapping = 0;
+    if (anon_pages) *anon_pages = 0;
+    if (dev) *dev = 0;
+    return true;
+  }
+#endif
 
   // We didn't find anything
   return false;
 }
+
+int ProcMapsIterator::FormatLine(char* buffer, int bufsize,
+                                 uint64 start, uint64 end, const char *flags,
+                                 uint64 offset, int64 inode,
+                                 const char *filename, dev_t dev) {
+  // We assume 'flags' looks like 'rwxp' or 'rwx'.
+  char r = (flags && flags[0] == 'r') ? 'r' : '-';
+  char w = (flags && flags[0] && flags[1] == 'w') ? 'w' : '-';
+  char x = (flags && flags[0] && flags[1] && flags[2] == 'x') ? 'x' : '-';
+  // p always seems set on linux, so we set the default to 'p', not '-'
+  char p = (flags && flags[0] && flags[1] && flags[2] && flags[3] != 'p')
+      ? '-' : 'p';
+
+  const int rc = snprintf(buffer, bufsize,
+                          "%08"PRIx64"-%08"PRIx64" %c%c%c%c %08"PRIx64" %02x:%02x %-11"PRId64" %s\n",
+                          start, end, r,w,x,p, offset,
+                          static_cast<int>(dev/256), static_cast<int>(dev%256),
+                          inode, filename);
+  return (rc < 0 || rc >= bufsize) ? 0 : rc;
+}
diff --git a/src/base/sysinfo.h b/src/base/sysinfo.h
index 748d072..35f31ad 100644
--- a/src/base/sysinfo.h
+++ b/src/base/sysinfo.h
@@ -36,6 +36,10 @@
 #include "config.h"
 
 #include <time.h>
+#ifdef WIN32
+#include <windows.h>   // for DWORD
+#include <TlHelp32.h>  // for CreateToolhelp32Snapshot
+#endif
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>    // for pid_t
 #endif
@@ -56,18 +60,30 @@
 
 // A ProcMapsIterator abstracts access to /proc/maps for a given
 // process. Needs to be stack-allocatable and avoid using stdio/malloc
-// so it can be used in the google stack dumper.
+// so it can be used in the google stack dumper, heap-profiler, etc.
+//
+// On Windows and Mac OS X, this iterator iterates *only* over DLLs
+// mapped into this process space.  For Linux, FreeBSD, and Solaris,
+// it iterates over *all* mapped memory regions, including anonymous
+// mmaps.  For other O/Ss, it is unlikely to work at all, and Valid()
+// will always return false.  Also note: this routine only works on
+// FreeBSD if procfs is mounted: make sure this is in your /etc/fstab:
+//    proc            /proc   procfs  rw 0 0
 class ProcMapsIterator {
-
  public:
-
   struct Buffer {
+#ifdef __FreeBSD__
+    // FreeBSD requires us to read all of the maps file at once, so
+    // we have to make a buffer that's "always" big enough
+    static const size_t kBufSize = 102400;
+#else   // a one-line buffer is good enough
     static const size_t kBufSize = PATH_MAX + 1024;
+#endif
     char buf_[kBufSize];
   };
 
 
-  // Create a new iterator for the specified pid
+  // Create a new iterator for the specified pid.  pid can be 0 for "self".
   explicit ProcMapsIterator(pid_t pid);
 
   // Create an iterator with specified storage (for use in signal
@@ -82,13 +98,36 @@
                    bool use_maps_backing);
 
   // Returns true if the iterator successfully initialized;
-  bool Valid() const { return fd_ != -1; }
+  bool Valid() const;
 
   // Returns a pointer to the most recently parsed line. Only valid
   // after Next() returns true, and until the iterator is destroyed or
-  // Next() is called again.
+  // Next() is called again.  This may give strange results on non-Linux
+  // systems.  Prefer FormatLine() if that may be a concern.
   const char *CurrentLine() const { return stext_; }
 
+  // Writes the "canonical" form of the /proc/xxx/maps info for a single
+  // line to the passed-in buffer. Returns the number of bytes written,
+  // or 0 if it was not able to write the complete line.  (To guarantee
+  // success, buffer should have size at least Buffer::kBufSize.)
+  // Takes as arguments values set via a call to Next().  The
+  // "canonical" form of the line (taken from linux's /proc/xxx/maps):
+  //    <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)>   +
+  //    <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
+  // eg
+  //    08048000-0804c000 r-xp 00000000 03:01 3793678    /bin/cat
+  // If you don't have the dev_t (dev), feel free to pass in 0.
+  // (Next() doesn't return a dev_t, though NextExt does.)
+  //
+  // Note: if filename and flags were obtained via a call to Next(),
+  // then the output of this function is only valid if Next() returned
+  // true, and only until the iterator is destroyed or Next() is
+  // called again.  (Since filename, at least, points into CurrentLine.)
+  static int FormatLine(char* buffer, int bufsize,
+                        uint64 start, uint64 end, const char *flags,
+                        uint64 offset, int64 inode, const char *filename,
+                        dev_t dev);
+
   // Find the next entry in /proc/maps; return true if found or false
   // if at the end of the file.
   //
@@ -103,6 +142,10 @@
 
   // The offsets are all uint64 in order to handle the case of a
   // 32-bit process running on a 64-bit kernel
+  //
+  // IMPORTANT NOTE: see top-of-class notes for details about what
+  // mapped regions Next() iterates over, depending on O/S.
+  // TODO(csilvers): make flags and filename const.
   bool Next(uint64 *start, uint64 *end, char **flags,
             uint64 *offset, int64 *inode, char **filename);
 
@@ -115,7 +158,6 @@
   ~ProcMapsIterator();
 
  private:
-
   void Init(pid_t pid, Buffer *buffer, bool use_maps_backing);
 
   char *ibuf_;        // input buffer
@@ -123,11 +165,29 @@
   char *etext_;       // end of text
   char *nextline_;    // start of next line
   char *ebuf_;        // end of buffer (1 char for a nul)
-  int   fd_;          // filehandle on /proc/*/maps
+#if defined(WIN32)
+  HANDLE snapshot_;   // filehandle on dll info
+  // In a change from the usual W-A pattern, there is no A variant of
+  // MODULEENTRY32.  Tlhelp32.h #defines the W variant, but not the A.
+  // We want the original A variants, and this #undef is the only
+  // way I see to get them.  Redefining it when we're done prevents us
+  // from affecting other .cc files.
+# ifdef MODULEENTRY32  // Alias of W
+#   undef MODULEENTRY32
+  MODULEENTRY32 module_;   // info about current dll (and dll iterator)
+#   define MODULEENTRY32 MODULEENTRY32W
+# else  // It's the ascii, the one we want.
+  MODULEENTRY32 module_;   // info about current dll (and dll iterator)
+# endif
+#elif defined(__MACH__)
+  int current_image_; // dll's are called "images" in macos parlance
+  int current_load_cmd_;   // the segment of this dll we're examining
+#else
+  int fd_;            // filehandle on /proc/*/maps
+#endif
   char flags_[10];
-  Buffer* dynamic_buffer_; // dynamically-allocated Buffer
+  Buffer* dynamic_buffer_;  // dynamically-allocated Buffer
   bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
-
 };
 
 #endif   /* #ifndef _SYSINFO_H_ */
diff --git a/src/base/thread_lister.c b/src/base/thread_lister.c
index 8c19fde..517d0cf 100644
--- a/src/base/thread_lister.c
+++ b/src/base/thread_lister.c
@@ -31,8 +31,11 @@
  * Author: Markus Gutschke
  */
 
+#include "config.h"
 #include <stdio.h>         /* needed for NULL on some powerpc platforms (?!) */
-#include <sys/prctl.h>
+#ifdef HAVE_SYS_PRCTL
+# include <sys/prctl.h>
+#endif
 #include "base/thread_lister.h"
 #include "base/linuxthreads.h"
 /* Include other thread listers here that define THREADS macro
@@ -50,15 +53,19 @@
   int rc;
   va_list ap;
 
+#ifdef HAVE_SYS_PRCTL
   int dumpable = prctl(PR_GET_DUMPABLE, 0);
   if (!dumpable)
     prctl(PR_SET_DUMPABLE, 1);
+#endif
   va_start(ap, callback);
   pid_t pid = getpid();
   rc = callback(parameter, 1, &pid, ap);
   va_end(ap);
+#ifdef HAVE_SYS_PRCTL
   if (!dumpable)
     prctl(PR_SET_DUMPABLE, 0);
+#endif
   return rc;
 }
 
@@ -66,4 +73,4 @@
   return 1;
 }
 
-#endif
+#endif   /* ifndef THREADS */
diff --git a/src/config.h.in b/src/config.h.in
index ac9feed..b7cea41 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -45,6 +45,9 @@
 /* Define to 1 if you have the <execinfo.h> header file. */
 #undef HAVE_EXECINFO_H
 
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
 /* Define to 1 if you have the `geteuid' function. */
 #undef HAVE_GETEUID
 
@@ -111,42 +114,24 @@
 /* Define to 1 if the system has the type `struct mallinfo'. */
 #undef HAVE_STRUCT_MALLINFO
 
-/* Define to 1 if `eip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_EIP
-
-/* Define to 1 if `regs->nip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_REGS__NIP
-
-/* Define to 1 if `rip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_RIP
-
-/* Define to 1 if `sc_eip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_SC_EIP
-
-/* Define to 1 if `sc_ip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_SC_IP
-
-/* Define to 1 if `sc_ir' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_SC_IR
-
-/* Define to 1 if `si_faddr' is member of `struct siginfo'. */
-#undef HAVE_STRUCT_SIGINFO_SI_FADDR
-
-/* Define to 1 if `uc_mcontext' is member of `struct ucontext'. */
-#undef HAVE_STRUCT_UCONTEXT_UC_MCONTEXT
-
-/* Define to 1 if you have the <syscall.h> header file. */
-#undef HAVE_SYSCALL_H
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
 /* Define to 1 if compiler supports __thread */
 #undef HAVE_TLS
 
+/* Define to 1 if you have the <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
@@ -183,6 +168,9 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* How to access the PC from a struct ucontext */
+#undef PC_FROM_UCONTEXT
+
 /* Always the empty-string on non-windows systems. On windows, should be
    "__declspec(dllexport)". This way, when we compile the dll, we export our
    functions/classes. It's safe to define this here because config.h is only
@@ -212,6 +200,11 @@
 /* Version number of package */
 #undef VERSION
 
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
 /* Define to `__inline__' or `__inline' if that's what the C compiler
    calls it, or to nothing if 'inline' is not supported under any name.  */
 #ifndef __cplusplus
diff --git a/src/config_for_unittests.h b/src/config_for_unittests.h
index dc1e164..b418dbf 100644
--- a/src/config_for_unittests.h
+++ b/src/config_for_unittests.h
@@ -41,13 +41,24 @@
 // (since it's not the dll).
 //
 // The solution is to have this file, which is just like config.h but
-// undefines PERFTOOLS_DLL_DECL so it doesn't try to export symbols.
+// sets PERFTOOLS_DLL_DECL to do a dllimport instead of a dllexport.
 //
-// This file is equivalent to config.h on non-windows systems.
+// The reason we need this extra PERFTOOLS_DLL_DECL_FOR_UNITTESTS
+// variable is in case people want to set PERFTOOLS_DLL_DECL explicitly
+// to something other than __declspec(dllexport).  In that case, they
+// may want to use something other than __declspec(dllimport) for the
+// unittest case.  For that, we allow folks to define both
+// PERFTOOLS_DLL_DECL and PERFTOOLS_DLL_DECL_FOR_UNITTESTS explicitly.
+//
+// NOTE: This file is equivalent to config.h on non-windows systems,
+// which never defined PERFTOOLS_DLL_DECL_FOR_UNITTESTS and always
+// define PERFTOOLS_DLL_DECL to the empty string.
 
 #include "config.h"
 
-#ifdef WIN32
-# undef PERFTOOLS_DLL_DECL
-# define PERFTOOLS_DLL_DECL  __declspec(dllimport)
+#undef PERFTOOLS_DLL_DECL
+#ifdef PERFTOOLS_DLL_DECL_FOR_UNITTESTS
+# define PERFTOOLS_DLL_DECL  PERFTOOLS_DLL_DECL_FOR_UNITTESTS
+#else
+# define PERFTOOLS_DLL_DECL  // if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
 #endif
diff --git a/src/getpc.h b/src/getpc.h
new file mode 100644
index 0000000..b7cfce9
--- /dev/null
+++ b/src/getpc.h
@@ -0,0 +1,176 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+//
+// This is an internal header file used by profiler.cc.  It defines
+// the single (inline) function GetPC.  GetPC is used in a signal
+// handler to figure out the instruction that was being executed when
+// the signal-handler was triggered.
+//
+// To get this, we use the ucontext_t argument to the signal-handler
+// callback, which holds the full context of what was going on when
+// the signal triggered.  How to get from a ucontext_t to a Program
+// Counter is OS-dependent.
+
+#ifndef BASE_GETPC_H__
+#define BASE_GETPC_H__
+
+#include "config.h"
+
+// On many linux systems, we may need _GNU_SOURCE to get access to
+// the defined constants that define the register we want to see (eg
+// REG_EIP).  Note this #define must come first!
+#define _GNU_SOURCE 1
+// If #define _GNU_SOURCE causes problems, this might work instead.
+// It will cause problems for FreeBSD though!, because it turns off
+// the needed __BSD_VISIBLE.
+//#define _XOPEN_SOURCE 500
+
+#include <string.h>         // for memcmp
+#ifdef HAVE_UCONTEXT_H
+#include <ucontext.h>       // for ucontext_t (and also mcontext_t)
+#endif
+
+
+// Take the example where function Foo() calls function Bar().  For
+// many architectures, Bar() is responsible for setting up and tearing
+// down its own stack frame.  In that case, it's possible for the
+// interrupt to happen when execution is in Bar(), but the stack frame
+// is not properly set up (either before it's done being set up, or
+// after it's been torn down but before Bar() returns).  In those
+// cases, the stack trace cannot see the caller function anymore.
+//
+// GetPC can try to identify this situation, on architectures where it
+// might occur, and unwind the current function call in that case to
+// avoid false edges in the profile graph (that is, edges that appear
+// to show a call skipping over a function).  To do this, we hard-code
+// in the asm instructions we might see when setting up or tearing
+// down a stack frame.
+//
+// This is difficult to get right: the instructions depend on the
+// processor, the compiler ABI, and even the optimization level.  This
+// is a best effort patch -- if we fail to detect such a situation, or
+// mess up the PC, nothing happens; the returned PC is not used for
+// any further processing.
+struct CallUnrollInfo {
+  // Offset from (e)ip register where this instruction sequence
+  // should be matched. Interpreted as bytes. Offset 0 is the next
+  // instruction to execute. Be extra careful with negative offsets in
+  // architectures of variable instruction length (like x86) - it is
+  // not that easy as taking an offset to step one instruction back!
+  int pc_offset;
+  // The actual instruction bytes. Feel free to make it larger if you
+  // need a longer sequence.
+  char ins[16];
+  // How many bytes to match from ins array?
+  int ins_size;
+  // The offset from the stack pointer (e)sp where to look for the
+  // call return address. Interpreted as bytes.
+  int return_sp_offset;
+};
+
+
+// The dereferences needed to get the PC from a struct ucontext were
+// determined at configure time, and stored in the macro
+// PC_FROM_UCONTEXT in config.h.  The only thing we need to do here,
+// then, is to do the magic call-unrolling for systems that support it.
+
+// -- Special case 1: linux x86, for which we have CallUnrollInfo
+#if defined(__linux) && defined(__i386) && defined(__GNUC__)
+static const CallUnrollInfo callunrollinfo[] = {
+  // Entry to a function:  push %ebp;  mov  %esp,%ebp
+  // Top-of-stack contains the caller IP.
+  { 0,
+    {0x55, 0x89, 0xe5}, 3,
+    0
+  },
+  // Entry to a function, second instruction:  push %ebp;  mov  %esp,%ebp
+  // Top-of-stack contains the old frame, caller IP is +4.
+  { -1,
+    {0x55, 0x89, 0xe5}, 3,
+    4
+  },
+  // Return from a function: RET.
+  // Top-of-stack contains the caller IP.
+  { 0,
+    {0xc3}, 1,
+    0
+  }
+};
+
+inline void* GetPC(const ucontext_t& signal_ucontext) {
+  // See comment above struct CallUnrollInfo.  Only try instruction
+  // flow matching if both eip and esp looks reasonable.
+  const int eip = signal_ucontext.uc_mcontext.gregs[REG_EIP];
+  const int esp = signal_ucontext.uc_mcontext.gregs[REG_ESP];
+  if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 &&
+      (esp & 0xffff0000) != 0) {
+    char* eip_char = reinterpret_cast<char*>(eip);
+    for (int i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) {
+      if (!memcmp(eip_char + callunrollinfo[i].pc_offset,
+                  callunrollinfo[i].ins, callunrollinfo[i].ins_size)) {
+        // We have a match.
+        void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset);
+        return *retaddr;
+      }
+    }
+  }
+  return (void*)eip;
+}
+
+// Special case #2: Windows, which has to do something totally different.
+#elif defined(WIN32)
+// If this is ever implemented, probably the way to do it is to have
+// profiler.cc use a high-precision timer via timeSetEvent:
+//    http://msdn2.microsoft.com/en-us/library/ms712713.aspx
+// We'd use it in mode TIME_CALLBACK_FUNCTION/TIME_PERIODIC.
+// The callback function would be something like prof_handler, but
+// alas the arguments are different: no ucontext_t!  I don't know
+// how we'd get the PC (using StackWalk64?)
+//    http://msdn2.microsoft.com/en-us/library/ms680650.aspx
+
+inline void* GetPC(const ucontext_t& signal_ucontext) {
+  RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n");
+  return NULL;
+}
+
+// Normal cases.  If this doesn't compile, it's probably because
+// PC_FROM_UCONTEXT is the empty string.  You need to figure out
+// the right value for your system, and add it to the list in
+// configure.ac (or set it manually in your config.h).
+#else
+inline void* GetPC(const ucontext_t& signal_ucontext) {
+  return (void*)signal_ucontext.PC_FROM_UCONTEXT;   // defined in config.h
+}
+
+#endif
+
+#endif  // BASE_GETPC_H__
diff --git a/src/google/heap-checker.h b/src/google/heap-checker.h
index 19b2510..8ba6e21 100644
--- a/src/google/heap-checker.h
+++ b/src/google/heap-checker.h
@@ -209,7 +209,7 @@
   // because this disabling works by remembering the range of
   // return program counter addresses for the two calls.
   static void* GetDisableChecksStart();
-  static void DisableChecksToHereFrom(void* start_address);
+  static void DisableChecksToHereFrom(const void* start_address);
 
   // ADVICE: Use GetDisableChecksStart, DisableChecksToHereFrom
   //         instead of DisableChecksUp|At whenever possible
@@ -238,7 +238,7 @@
 
   // Same as DisableChecksUp,
   // but the function return program counter address is given explicitly.
-  static void DisableChecksAt(void* address);
+  static void DisableChecksAt(const void* address);
 
   // Tests for checking that DisableChecksUp and DisableChecksAt
   // behaved as expected, for example
@@ -256,7 +256,7 @@
   //    }
   // These return false when heap leak checking is turned off.
   static bool HaveDisabledChecksUp(int stack_frames);
-  static bool HaveDisabledChecksAt(void* address);
+  static bool HaveDisabledChecksAt(const void* address);
 
   // Ignore an object located at 'ptr'
   // (as well as all heap objects (transitively) referenced from it)
@@ -265,12 +265,12 @@
   // at the time of this call, it is ignored;
   // but if it does, the object must not get deleted from the heap later on;
   // it must also be not already ignored at the time of this call.
-  static void IgnoreObject(void* ptr);
+  static void IgnoreObject(const void* ptr);
 
   // Undo what an earlier IgnoreObject() call promised and asked to do.
   // At the time of this call 'ptr' must point to an active allocated object
   // which was previously registered with IgnoreObject().
-  static void UnIgnoreObject(void* ptr);
+  static void UnIgnoreObject(const void* ptr);
 
  public:  // Initializations; to be called from main() only.
 
@@ -288,7 +288,7 @@
   enum ProfileType { START_PROFILE, END_PROFILE };
   // Helper for dumping start/end heap leak checking profiles
   // and getting the byte/object counts.
-  void DumpProfileLocked(ProfileType profile_type, void* self_stack_top,
+  void DumpProfileLocked(ProfileType profile_type, const void* self_stack_top,
                          size_t* alloc_bytes, size_t* alloc_objects);
   // Helper for constructors
   void Create(const char *name);
@@ -304,17 +304,17 @@
                      CheckFullness fullness,
                      ReportMode report_mode);
   // Helper for IgnoreObject
-  static void IgnoreObjectLocked(void* ptr);
+  static void IgnoreObjectLocked(const void* ptr);
   // Helper for DisableChecksAt
-  static void DisableChecksAtLocked(void* address);
+  static void DisableChecksAtLocked(const void* address);
   // Helper for DisableChecksIn
   static void DisableChecksInLocked(const char* pattern);
   // Helper for DisableChecksToHereFrom
-  static void DisableChecksFromToLocked(void* start_address,
-                                        void* end_address,
+  static void DisableChecksFromToLocked(const void* start_address,
+                                        const void* end_address,
                                         int max_depth);
   // Helper for DoNoLeaks to ignore all objects reachable from all live data
-  static void IgnoreAllLiveObjectsLocked(void* self_stack_top);
+  static void IgnoreAllLiveObjectsLocked(const void* self_stack_top);
   // Callback we pass to ListAllProcessThreads (see thread_lister.h)
   // that is invoked when all threads of our process are found and stopped.
   // The call back does the things needed to ignore live data reachable from
@@ -346,7 +346,7 @@
   // are being used.
   static void IgnoreLiveObjectsLocked(const char* name, const char* name2);
   // Heap profile object filtering callback to filter out live objects.
-  static bool HeapProfileFilter(void* ptr, size_t size);
+  static bool HeapProfileFilter(const void* ptr, size_t size);
   // Runs REGISTER_HEAPCHECK_CLEANUP cleanups and potentially
   // calls DoMainHeapCheck
   static void RunHeapCleanups();
@@ -378,14 +378,14 @@
   // If yes, we might move "*ptr" to point to the very start of the object
   // (this needs to happen for C++ class array allocations
   // and for basic_string-s of C++ library that comes with gcc 3.4).
-  static bool HaveOnHeapLocked(void** ptr, size_t* object_size);
+  static bool HaveOnHeapLocked(const void** ptr, size_t* object_size);
 
  private:
 
   // Helper for VerifyHeapProfileTableStackGet in the unittest
   // to get the recorded allocation caller for ptr,
   // which must be a heap object.
-  static void* GetAllocCaller(void* ptr);
+  static const void* GetAllocCaller(void* ptr);
   friend void VerifyHeapProfileTableStackGet();
 
   // This gets to execute before constructors for all global objects
diff --git a/src/google/malloc_hook.h b/src/google/malloc_hook.h
index acfc46c..ab580b6 100644
--- a/src/google/malloc_hook.h
+++ b/src/google/malloc_hook.h
@@ -61,34 +61,34 @@
  public:
   // The NewHook is invoked whenever an object is allocated.
   // It may be passed NULL if the allocator returned NULL.
-  typedef void (*NewHook)(void* ptr, size_t size);
+  typedef void (*NewHook)(const void* ptr, size_t size);
   inline static NewHook GetNewHook() { return new_hook_; }
   inline static NewHook SetNewHook(NewHook hook) {
     NewHook result = new_hook_;
     new_hook_ = hook;
     return result;
   }
-  inline static void InvokeNewHook(void* p, size_t s) {
+  inline static void InvokeNewHook(const void* p, size_t s) {
     if (new_hook_ != NULL) (*new_hook_)(p, s);
   }
 
   // The DeleteHook is invoked whenever an object is deallocated.
   // It may be passed NULL if the caller is trying to delete NULL.
-  typedef void (*DeleteHook)(void* ptr);
+  typedef void (*DeleteHook)(const void* ptr);
   inline static DeleteHook GetDeleteHook() { return delete_hook_; }
   inline static DeleteHook SetDeleteHook(DeleteHook hook) {
     DeleteHook result = delete_hook_;
     delete_hook_ = hook;
     return result;
   }
-  inline static void InvokeDeleteHook(void* p) {
+  inline static void InvokeDeleteHook(const void* p) {
     if (delete_hook_ != NULL) (*delete_hook_)(p);
   }
 
   // The MmapHook is invoked whenever a region of memory is mapped.
   // It may be passed MAP_FAILED if the mmap failed.
-  typedef void (*MmapHook)(void* result,
-                           void* start,
+  typedef void (*MmapHook)(const void* result,
+                           const void* start,
                            size_t size,
                            int protection,
                            int flags,
@@ -100,8 +100,8 @@
     mmap_hook_ = hook;
     return result;
   }
-  inline static void InvokeMmapHook(void* result,
-                                    void* start,
+  inline static void InvokeMmapHook(const void* result,
+                                    const void* start,
                                     size_t size,
                                     int protection,
                                     int flags,
@@ -114,51 +114,54 @@
   }
 
   // The MunmapHook is invoked whenever a region of memory is unmapped.
-  typedef void (*MunmapHook)(void* ptr, size_t size);
+  typedef void (*MunmapHook)(const void* ptr, size_t size);
   inline static MunmapHook GetMunmapHook() { return munmap_hook_; }
   inline static MunmapHook SetMunmapHook(MunmapHook hook) {
     MunmapHook result = munmap_hook_;
     munmap_hook_ = hook;
     return result;
   }
-  inline static void InvokeMunmapHook(void* p, size_t size) {
+  inline static void InvokeMunmapHook(const void* p, size_t size) {
     if (munmap_hook_ != NULL) (*munmap_hook_)(p, size);
   }
 
   // The MremapHook is invoked whenever a region of memory is remapped.
-  typedef void (*MremapHook)(void* result,
-                             void* old_addr,
+  typedef void (*MremapHook)(const void* result,
+                             const void* old_addr,
                              size_t old_size,
                              size_t new_size,
                              int flags,
-                             void* new_addr);
+                             const void* new_addr);
   inline static MremapHook GetMremapHook() { return mremap_hook_; }
   inline static MremapHook SetMremapHook(MremapHook hook) {
     MremapHook result = mremap_hook_;
     mremap_hook_ = hook;
     return result;
   }
-  inline static void InvokeMremapHook(void* result,
-                                      void* old_addr,
+  inline static void InvokeMremapHook(const void* result,
+                                      const void* old_addr,
                                       size_t old_size,
                                       size_t new_size,
                                       int flags,
-                                      void* new_addr) {
+                                      const void* new_addr) {
     if (mremap_hook_ != NULL) (*mremap_hook_)(result,
                                               old_addr, old_size,
                                               new_size, flags, new_addr);
   }
 
-  // The SbrkHook is invoked whenever sbrk is called.
-  typedef void (*SbrkHook)(void* result, ptrdiff_t increment);
+  // The SbrkHook is invoked whenever sbrk is called -- except when
+  // the increment is 0.  This is because sbrk(0) is often called
+  // to get the top of the memory stack, and is not actually a
+  // memory-allocation call.
+  typedef void (*SbrkHook)(const void* result, ptrdiff_t increment);
   inline static SbrkHook GetSbrkHook() { return sbrk_hook_; }
   inline static SbrkHook SetSbrkHook(SbrkHook hook) {
     SbrkHook result = sbrk_hook_;
     sbrk_hook_ = hook;
     return result;
   }
-  inline static void InvokeSbrkHook(void* result, ptrdiff_t increment) {
-    if (sbrk_hook_ != NULL) (*sbrk_hook_)(result, increment);
+  inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment) {
+    if (sbrk_hook_ != NULL && increment != 0) (*sbrk_hook_)(result, increment);
   }
 
   // Get the current stack trace.  Try to skip all routines up to and
diff --git a/src/heap-checker.cc b/src/heap-checker.cc
index 95d55e6..c523810 100644
--- a/src/heap-checker.cc
+++ b/src/heap-checker.cc
@@ -52,8 +52,8 @@
 #ifdef HAVE_LINUX_PTRACE_H
 #include <linux/ptrace.h>
 #endif
-#ifdef HAVE_SYSCALL_H
-#include <syscall.h>
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
 #endif
 
 #include <string>
@@ -263,11 +263,11 @@
 
 // Information about an allocated object
 struct AllocObject {
-  void* ptr;              // the object
+  const void* ptr;        // the object
   uintptr_t size;         // its size
   ObjectPlacement place;  // where ptr points to
 
-  AllocObject(void* p, size_t s, ObjectPlacement l)
+  AllocObject(const void* p, size_t s, ObjectPlacement l)
     : ptr(p), size(s), place(l) { }
 };
 
@@ -309,8 +309,8 @@
 static LibraryLiveObjectsStacks* library_live_objects = NULL;
 
 // Objects to be removed from the heap profile when we dump it.
-typedef set<void*, less<void*>,
-            STL_Allocator<void*, HeapLeakChecker::Allocator>
+typedef set<const void*, less<const void*>,
+            STL_Allocator<const void*, HeapLeakChecker::Allocator>
            > ProfileAdjustObjectSet;
 static ProfileAdjustObjectSet* profile_adjust_objects = NULL;
 
@@ -366,7 +366,7 @@
 static bool initializer = (libpthread_initialized = true, true);
 
 // Our hooks for MallocHook
-static void NewHook(void* ptr, size_t size) {
+static void NewHook(const void* ptr, size_t size) {
   if (ptr != NULL) {
     RAW_VLOG(7, "Recording Alloc: %p of %"PRIuS, ptr, size);
     heap_checker_lock.Lock();
@@ -376,7 +376,7 @@
   }
 }
 
-static void DeleteHook(void* ptr) {
+static void DeleteHook(const void* ptr) {
   if (ptr != NULL) {
     RAW_VLOG(7, "Recording Free %p", ptr);
     heap_checker_lock.Lock();
@@ -394,14 +394,14 @@
   UNKNOWN_DIRECTION
 };
 
-static StackDirection GetStackDirection(int* ptr);  // defined below
+static StackDirection GetStackDirection(const int* ptr);  // defined below
 
 // Function pointer to trick compiler into not inlining a call:
-static StackDirection (*do_stack_direction)(int* ptr) = GetStackDirection;
+static StackDirection (*do_stack_direction)(const int* ptr) = GetStackDirection;
 
 // Determine which way the stack grows:
 // Call with NULL argument.
-static StackDirection GetStackDirection(int* ptr) {
+static StackDirection GetStackDirection(const int* ptr) {
   int a_local;
   if (ptr == NULL) return do_stack_direction(&a_local);
   if (&a_local > ptr) return GROWS_TOWARDS_HIGH_ADDRESSES;
@@ -415,7 +415,7 @@
 static StackDirection stack_direction = UNKNOWN_DIRECTION;
 
 // This routine is called for every thread stack we know about to register it.
-static void RegisterStack(void* top_ptr) {
+static void RegisterStack(const void* top_ptr) {
   RAW_VLOG(1, "Thread stack at %p", top_ptr);
   uintptr_t top = reinterpret_cast<uintptr_t>(top_ptr);
   stack_tops->insert(top);  // add for later use
@@ -505,7 +505,7 @@
 
 // Iterator for heap allocation map data to make objects allocated from
 // disabled regions of code to be live.
-static void MakeDisabledLiveCallback(void* ptr,
+static void MakeDisabledLiveCallback(const void* ptr,
                                      const HeapProfileTable::AllocInfo& info) {
   bool stack_disable = false;
   bool range_disable = false;
@@ -772,7 +772,7 @@
     // specially via self_thread_stack, not here:
     if (thread_pids[i] == self_thread_pid) continue;
     RAW_VLOG(2, "Handling thread with pid %d", thread_pids[i]);
-#if defined(HAVE_LINUX_PTRACE_H) && defined(HAVE_SYSCALL_H) && defined(DUMPER)
+#if defined(HAVE_LINUX_PTRACE_H) && defined(HAVE_SYS_SYSCALL_H) && defined(DUMPER)
     i386_regs thread_regs;
 #define sys_ptrace(r, p, a, d)  syscall(SYS_ptrace, (r), (p), (a), (d))
     // We use sys_ptrace to avoid thread locking
@@ -817,7 +817,7 @@
 
 // Stack top of the thread that is doing the current leak check
 // (protected by our lock; IgnoreAllLiveObjectsLocked sets it)
-static void* self_thread_stack_top;
+static const void* self_thread_stack_top;
 
 void HeapLeakChecker::IgnoreNonThreadLiveObjectsLocked() {
   RAW_VLOG(2, "Handling self thread with pid %d", self_thread_pid);
@@ -832,7 +832,7 @@
   if (ignored_objects) {
     for (IgnoredObjectsMap::const_iterator object = ignored_objects->begin();
          object != ignored_objects->end(); ++object) {
-      void* ptr = reinterpret_cast<void*>(object->first);
+      const void* ptr = reinterpret_cast<const void*>(object->first);
       RAW_VLOG(2, "Ignored live object at %p of %"PRIuS" bytes",
                   ptr, object->second);
       live_objects->
@@ -956,7 +956,7 @@
   }
 }
 
-void HeapLeakChecker::IgnoreAllLiveObjectsLocked(void* self_stack_top) {
+void HeapLeakChecker::IgnoreAllLiveObjectsLocked(const void* self_stack_top) {
   RAW_CHECK(live_objects == NULL, "");
   live_objects = new (Allocator::Allocate(sizeof(LiveObjectsStack)))
                    LiveObjectsStack;
@@ -1036,7 +1036,7 @@
   int64 live_object_count = 0;
   int64 live_byte_count = 0;
   while (!live_objects->empty()) {
-    void* object = live_objects->back().ptr;
+    const void* object = live_objects->back().ptr;
     size_t size = live_objects->back().size;
     const ObjectPlacement place = live_objects->back().place;
     live_objects->pop_back();
@@ -1053,7 +1053,8 @@
     const size_t remainder =
       reinterpret_cast<uintptr_t>(object) % pointer_alignment;
     if (remainder) {
-      object = reinterpret_cast<char*>(object) + pointer_alignment - remainder;
+      object = (reinterpret_cast<const char*>(object) +
+                pointer_alignment - remainder);
       if (size >= pointer_alignment - remainder) {
         size -= pointer_alignment - remainder;
       } else {
@@ -1061,10 +1062,10 @@
       }
     }
     while (size >= sizeof(void*)) {
-      void* ptr;
-      memcpy(&ptr, object, sizeof(void*));  // size-independent UNALIGNED_LOAD
-      void* current_object = object;
-      object = reinterpret_cast<char*>(object) + pointer_alignment;
+      const void* ptr;
+      memcpy(&ptr, object, sizeof(ptr));  // size-independent UNALIGNED_LOAD
+      const void* current_object = object;
+      object = reinterpret_cast<const char*>(object) + pointer_alignment;
       size -= pointer_alignment;
       if (ptr == NULL)  continue;
       RAW_VLOG(8, "Trying pointer to %p at %p", ptr, current_object);
@@ -1092,7 +1093,7 @@
   }
 }
 
-bool HeapLeakChecker::HeapProfileFilter(void* ptr, size_t size) {
+bool HeapLeakChecker::HeapProfileFilter(const void* ptr, size_t size) {
   if (profile_adjust_objects->find(ptr) != profile_adjust_objects->end()) {
     RAW_VLOG(4, "Ignoring object at %p of %"PRIuS" bytes", ptr, size);
     // erase so we can later test that all adjust-objects got utilized
@@ -1116,7 +1117,7 @@
   DisableChecksAt(stack[0]);
 }
 
-void HeapLeakChecker::DisableChecksAt(void* address) {
+void HeapLeakChecker::DisableChecksAt(const void* address) {
   if (!heap_checker_on) return;
   heap_checker_lock.Lock();
   DisableChecksAtLocked(address);
@@ -1133,7 +1134,7 @@
   return HaveDisabledChecksAt(stack[0]);
 }
 
-bool HeapLeakChecker::HaveDisabledChecksAt(void* address) {
+bool HeapLeakChecker::HaveDisabledChecksAt(const void* address) {
   if (!heap_checker_on) return false;
   heap_checker_lock.Lock();
   bool result = disabled_addresses != NULL  &&
@@ -1160,12 +1161,13 @@
   return start_address;
 }
 
-void HeapLeakChecker::DisableChecksToHereFrom(void* start_address) {
+void HeapLeakChecker::DisableChecksToHereFrom(const void* start_address) {
   if (!heap_checker_on) return;
-  void* end_address = NULL;
-  if (GetStackTrace(&end_address, 1, 1) != 1) {
+  void* end_address_ptr = NULL;
+  if (GetStackTrace(&end_address_ptr, 1, 1) != 1) {
     RAW_LOG(FATAL, "Can't get stack trace");
   }
+  const void* end_address = end_address_ptr;
   if (start_address > end_address)  swap(start_address, end_address);
   heap_checker_lock.Lock();
   DisableChecksFromToLocked(start_address, end_address, 10000);
@@ -1174,14 +1176,14 @@
   heap_checker_lock.Unlock();
 }
 
-void HeapLeakChecker::IgnoreObject(void* ptr) {
+void HeapLeakChecker::IgnoreObject(const void* ptr) {
   if (!heap_checker_on) return;
   heap_checker_lock.Lock();
   IgnoreObjectLocked(ptr);
   heap_checker_lock.Unlock();
 }
 
-void HeapLeakChecker::IgnoreObjectLocked(void* ptr) {
+void HeapLeakChecker::IgnoreObjectLocked(const void* ptr) {
   size_t object_size;
   if (HaveOnHeapLocked(&ptr, &object_size)) {
     RAW_VLOG(1, "Going to ignore live object at %p of %"PRIuS" bytes",
@@ -1197,7 +1199,7 @@
   }
 }
 
-void HeapLeakChecker::UnIgnoreObject(void* ptr) {
+void HeapLeakChecker::UnIgnoreObject(const void* ptr) {
   if (!heap_checker_on) return;
   heap_checker_lock.Lock();
   size_t object_size;
@@ -1224,7 +1226,7 @@
 //----------------------------------------------------------------------
 
 void HeapLeakChecker::DumpProfileLocked(ProfileType profile_type,
-                                        void* self_stack_top,
+                                        const void* self_stack_top,
                                         size_t* alloc_bytes,
                                         size_t* alloc_objects) {
   RAW_VLOG(0, "%s check \"%s\"%s",
@@ -1861,9 +1863,8 @@
 
 static bool in_initial_malloc_hook = false;
 
-#if (defined(__GNUC__) && __GNUC__ >= 3) \
- && (defined(__i386__) || defined(__x86_64__)) \
- && (!defined(SWIG))
+#ifdef HAVE___ATTRIBUTE___   // we need __attribute__((weak)) for this to work
+#define INSTALLED_INITIAL_MALLOC_HOOKS
 
 void HeapLeakChecker_BeforeConstructors();  // below
 
@@ -1880,15 +1881,15 @@
 // These will owerwrite the weak definitions in malloc_hook.cc:
 
 // Important to have this to catch the first allocation call from the binary:
-extern void InitialMallocHook_New(void* ptr, size_t size) {
+extern void InitialMallocHook_New(const void* ptr, size_t size) {
   InitHeapLeakCheckerFromMallocHook();
   // record this first allocation as well (if we need to):
   MallocHook::InvokeNewHook(ptr, size);
 }
 
 // Important to have this to catch the first mmap call (say from tcmalloc):
-extern void InitialMallocHook_MMap(void* result,
-                                   void* start,
+extern void InitialMallocHook_MMap(const void* result,
+                                   const void* start,
                                    size_t size,
                                    int protection,
                                    int flags,
@@ -1901,7 +1902,7 @@
 }
 
 // Important to have this to catch the first sbrk call (say from tcmalloc):
-extern void InitialMallocHook_Sbrk(void* result, ptrdiff_t increment) {
+extern void InitialMallocHook_Sbrk(const void* result, ptrdiff_t increment) {
   InitHeapLeakCheckerFromMallocHook();
   // record this first sbrk as well (if we need to):
   MallocHook::InvokeSbrkHook(result, increment);
@@ -1977,7 +1978,7 @@
 static int GetCommandLineFrom(const char* file, char* cmdline, int size) {
   // This routine is only used to check if we're running under gdb, so
   // it's ok if this #if fails and the routine is a no-op.
-#if defined(HAVE_SYSCALL_H)
+#if defined(HAVE_SYS_SYSCALL_H)
   // This function is called before memory allocation hooks are set up
   // so we must not have any memory allocations in it.  We use syscall
   // versions of open/read/close here because we don't trust the non-syscall
@@ -2002,7 +2003,7 @@
     syscall(SYS_close, fd);
   }
   return result;
-#else   // HAVE_SYSCALL_H
+#else   // HAVE_SYS_SYSCALL_H
   return 0;
 #endif
 }
@@ -2052,9 +2053,14 @@
   if (need_heap_check) {
     HeapLeakChecker::BeforeConstructors();
   } else {  // cancel our initial hooks
-    MallocHook::SetNewHook(NULL);
-    MallocHook::SetMmapHook(NULL);
-    MallocHook::SetSbrkHook(NULL);
+#ifdef INSTALLED_INITIAL_MALLOC_HOOKS
+    if (MallocHook::GetNewHook() == &InitialMallocHook_New)
+      MallocHook::SetNewHook(NULL);
+    if (MallocHook::GetMmapHook() == &InitialMallocHook_MMap)
+      MallocHook::SetMmapHook(NULL);
+    if (MallocHook::GetSbrkHook() == &InitialMallocHook_Sbrk)
+      MallocHook::SetSbrkHook(NULL);
+#endif
   }
 }
 
@@ -2090,8 +2096,8 @@
   *disabled_regexp += pattern;
 }
 
-void HeapLeakChecker::DisableChecksFromToLocked(void* start_address,
-                                                void* end_address,
+void HeapLeakChecker::DisableChecksFromToLocked(const void* start_address,
+                                                const void* end_address,
                                                 int max_depth) {
   RAW_DCHECK(heap_checker_lock.IsHeld(), "");
   RAW_DCHECK(start_address < end_address, "");
@@ -2122,7 +2128,7 @@
   }
 }
 
-void HeapLeakChecker::DisableChecksAtLocked(void* address) {
+void HeapLeakChecker::DisableChecksAtLocked(const void* address) {
   RAW_DCHECK(heap_checker_lock.IsHeld(), "");
   if (disabled_addresses == NULL) {
     disabled_addresses = new (Allocator::Allocate(sizeof(DisabledAddressSet)))
@@ -2135,7 +2141,7 @@
   }
 }
 
-bool HeapLeakChecker::HaveOnHeapLocked(void** ptr, size_t* object_size) {
+bool HeapLeakChecker::HaveOnHeapLocked(const void** ptr, size_t* object_size) {
   RAW_DCHECK(heap_checker_lock.IsHeld(), "");
   // Size of the C++ object array size integer
   // (potentially compiler dependent; 4 on i386 and gcc; 8 on x86_64 and gcc)
@@ -2155,33 +2161,33 @@
   bool result = true;
   if (heap_profile->FindAlloc(*ptr, object_size)) {
     // done
-  } else if (heap_profile->FindAlloc(reinterpret_cast<char*>(*ptr)
+  } else if (heap_profile->FindAlloc(reinterpret_cast<const char*>(*ptr)
                                      - kArraySizeOffset,
                                      object_size)  &&
              *object_size > kArraySizeOffset) {
     // this case is to account for the array size stored inside of
     // the memory allocated by new FooClass[size] for classes with destructors
-    *ptr = reinterpret_cast<char*>(*ptr) - kArraySizeOffset;
+    *ptr = reinterpret_cast<const char*>(*ptr) - kArraySizeOffset;
     RAW_VLOG(7, "Got poiter into %p at +%d", ptr, kArraySizeOffset);
-  } else if (heap_profile->FindAlloc(reinterpret_cast<char*>(*ptr)
+  } else if (heap_profile->FindAlloc(reinterpret_cast<const char*>(*ptr)
                                      - kStringOffset,
                                      object_size)  &&
              *object_size > kStringOffset) {
     // this case is to account for basic_string<> representation in
     // newer C++ library versions when the kept pointer points to inside of
     // the allocated region
-    *ptr = reinterpret_cast<char*>(*ptr) - kStringOffset;
+    *ptr = reinterpret_cast<const char*>(*ptr) - kStringOffset;
     RAW_VLOG(7, "Got poiter into %p at +%d", ptr, kStringOffset);
   } else if (kUnicodeStringOffset != kArraySizeOffset &&
              heap_profile->FindAlloc(
-                 reinterpret_cast<char*>(*ptr) - kUnicodeStringOffset,
+                 reinterpret_cast<const char*>(*ptr) - kUnicodeStringOffset,
                  object_size)  &&
              *object_size > kUnicodeStringOffset) {
     // this case is to account for third party UnicodeString.
     // UnicodeString stores a 32-bit refcount (in both 32-bit and
     // 64-bit binaries) as the first uint32 in the allocated memory
     // and a pointer points into the second uint32 behind the refcount.
-    *ptr = reinterpret_cast<char*>(*ptr) - kUnicodeStringOffset;
+    *ptr = reinterpret_cast<const char*>(*ptr) - kUnicodeStringOffset;
     RAW_VLOG(7, "Got poiter into %p at +%d", ptr, kUnicodeStringOffset);
   } else {
     result = false;
@@ -2189,7 +2195,7 @@
   return result;
 }
 
-void* HeapLeakChecker::GetAllocCaller(void* ptr) {
+const void* HeapLeakChecker::GetAllocCaller(void* ptr) {
   // this is used only in unittest, so the heavy checks are fine
   HeapProfileTable::AllocInfo info;
   heap_checker_lock.Lock();
diff --git a/src/heap-profile-table.cc b/src/heap-profile-table.cc
index 3b06a18..f1d76d0 100644
--- a/src/heap-profile-table.cc
+++ b/src/heap-profile-table.cc
@@ -54,6 +54,7 @@
 #include <google/stacktrace.h>
 #include <google/malloc_hook.h>
 #include "base/commandlineflags.h"
+#include "base/sysinfo.h"
 
 using std::sort;
 using std::string;
@@ -92,7 +93,7 @@
 
 // Wrapper around ::write to undo it's potential partiality.
 static void FDWrite(int fd, const char* buf, size_t len) {
-  while (1) {
+  while (len > 0) {
     ssize_t r;
     NO_INTR(r = write(fd, buf, len));
     if (r <= 0) break;
@@ -113,34 +114,37 @@
 // and return the actual size occupied in 'buf'.
 // We do not provision for 0-terminating 'buf'.
 static int FillProcSelfMaps(char buf[], int size) {
-  const int maps = open("/proc/self/maps", O_RDONLY);
-  int buflen = 0;
-  if (maps >= 0) {
-    while (buflen < size) {
-      ssize_t r;
-      NO_INTR(r = read(maps, buf + buflen, size - buflen));
-      if (r <= 0) break;
-      buflen += r;
-    }
-    NO_INTR(close(maps));
+  ProcMapsIterator::Buffer iterbuf;
+  ProcMapsIterator it(0, &iterbuf);   // 0 means "current pid"
+
+  uint64 start, end, offset;
+  int64 inode;
+  char *flags, *filename;
+  int bytes_written = 0;
+  while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
+    bytes_written += it.FormatLine(buf + bytes_written, size - bytes_written,
+                                   start, end, flags, offset, inode, filename,
+                                   0);
   }
-  return buflen;
+  return bytes_written;
 }
 
 // Dump the same data as FillProcSelfMaps reads to fd.
 // It seems easier to repeat parts of FillProcSelfMaps here than to
 // reuse it via a call.
 static void DumpProcSelfMaps(int fd) {
-  const int maps = open("/proc/self/maps", O_RDONLY);
-  if (maps >= 0) {
-    char buf[512];
-    while (1) {
-      ssize_t r;
-      NO_INTR(r = read(maps, buf, sizeof(buf)));
-      if (r <= 0) break;
-      FDWrite(fd, buf, r);
-    }
-    NO_INTR(close(maps));
+  ProcMapsIterator::Buffer iterbuf;
+  ProcMapsIterator it(0, &iterbuf);   // 0 means "current pid"
+
+  uint64 start, end, offset;
+  int64 inode;
+  char *flags, *filename;
+  ProcMapsIterator::Buffer linebuf;
+  while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
+    int written = it.FormatLine(linebuf.buf_, sizeof(linebuf.buf_),
+                                start, end, flags, offset, inode, filename,
+                                0);
+    FDWrite(fd, linebuf.buf_, written);
   }
 }
 
@@ -205,7 +209,7 @@
   }
 
   // Create new bucket
-  void** kcopy = reinterpret_cast<void**>(alloc_(key_size));
+  const void** kcopy = reinterpret_cast<const void**>(alloc_(key_size));
   memcpy(kcopy, key, key_size);
   Bucket* b = reinterpret_cast<Bucket*>(alloc_(sizeof(Bucket)));
   memset(b, 0, sizeof(*b));
@@ -218,7 +222,8 @@
   return b;
 }
 
-void HeapProfileTable::RecordAlloc(void* ptr, size_t bytes, int skip_count) {
+void HeapProfileTable::RecordAlloc(const void* ptr, size_t bytes,
+                                   int skip_count) {
   Bucket* b = GetBucket(kStripFrames + skip_count + 1);
   b->allocs++;
   b->alloc_size += bytes;
@@ -231,7 +236,7 @@
   allocation_->Insert(ptr, v);
 }
 
-void HeapProfileTable::RecordFree(void* ptr) {
+void HeapProfileTable::RecordFree(const void* ptr) {
   AllocValue v;
   if (allocation_->FindAndRemove(ptr, &v)) {
     Bucket* b = v.bucket;
@@ -242,7 +247,7 @@
   }
 }
 
-bool HeapProfileTable::FindAlloc(void* ptr, size_t* object_size) const {
+bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const {
   AllocValue alloc_value;
   if (allocation_->Find(ptr, &alloc_value)) {
     *object_size = alloc_value.bytes;
@@ -251,7 +256,7 @@
   return false;
 }
 
-bool HeapProfileTable::FindAllocDetails(void* ptr, AllocInfo* info) const {
+bool HeapProfileTable::FindAllocDetails(const void* ptr, AllocInfo* info) const {
   AllocValue alloc_value;
   if (allocation_->Find(ptr, &alloc_value)) {
     info->object_size = alloc_value.bytes;
@@ -263,7 +268,7 @@
 }
 
 void HeapProfileTable::MapArgsAllocIterator(
-    void* ptr, AllocValue v, AllocIterator callback) {
+    const void* ptr, AllocValue v, AllocIterator callback) {
   AllocInfo info;
   info.object_size = v.bytes;
   info.call_stack = v.bucket->stack;
@@ -284,7 +289,7 @@
   profile_stats->frees += b.frees;
   profile_stats->free_size += b.free_size;
   int printed =
-    snprintf(buf + buflen, bufsize - buflen, "%6d: %8lld [%6d: %8lld] @",
+    snprintf(buf + buflen, bufsize - buflen, "%6d: %8"PRId64" [%6d: %8"PRId64"] @",
              b.allocs - b.frees,
              b.alloc_size - b.free_size,
              b.allocs,
@@ -353,14 +358,14 @@
   return bucket_length + map_length;
 }
 
-void HeapProfileTable::FilteredDumpIterator(void* ptr, AllocValue v,
+void HeapProfileTable::FilteredDumpIterator(const void* ptr, AllocValue v,
                                             const DumpArgs& args) {
   if (args.filter(ptr, v.bytes)) return;
   Bucket b;
   memset(&b, 0, sizeof(b));
   b.allocs = 1;
   b.alloc_size = v.bytes;
-  void* stack[kMaxStackTrace + 1];
+  const void* stack[kMaxStackTrace + 1];
   b.depth = v.bucket->depth + int(args.dump_alloc_addresses);
   b.stack = stack;
   if (args.dump_alloc_addresses) stack[0] = ptr;
diff --git a/src/heap-profile-table.h b/src/heap-profile-table.h
index 18b4a88..2775edd 100644
--- a/src/heap-profile-table.h
+++ b/src/heap-profile-table.h
@@ -64,7 +64,7 @@
   // Info we can return about an allocation.
   struct AllocInfo {
     size_t object_size;  // size of the allocation
-    void* const* call_stack;  // call stack that made the allocation call
+    const void* const* call_stack;  // call stack that made the allocation call
     int stack_depth;  // depth of call_stack
   };
 
@@ -80,23 +80,23 @@
   // Record an allocation at 'ptr' of 'bytes' bytes.
   // skip_count gives the number of stack frames between this call
   // and the memory allocation function that was asked to do the allocation.
-  void RecordAlloc(void* ptr, size_t bytes, int skip_count);
+  void RecordAlloc(const void* ptr, size_t bytes, int skip_count);
 
   // Record the deallocation of memory at 'ptr'.
-  void RecordFree(void* ptr);
+  void RecordFree(const void* ptr);
 
   // Return true iff we have recorded an allocation at 'ptr'.
   // If yes, fill *object_size with the allocation byte size.
-  bool FindAlloc(void* ptr, size_t* object_size) const;
+  bool FindAlloc(const void* ptr, size_t* object_size) const;
   // Same as FindAlloc, but fills all of *info.
-  bool FindAllocDetails(void* ptr, AllocInfo* info) const;
+  bool FindAllocDetails(const void* ptr, AllocInfo* info) const;
 
   // Return current total (de)allocation statistics.
   const Stats& total() const { return total_; }
 
   // Allocation data iteration callback: gets passed object pointer and
   // fully-filled AllocInfo.
-  typedef void (*AllocIterator)(void* ptr, const AllocInfo& info);
+  typedef void (*AllocIterator)(const void* ptr, const AllocInfo& info);
 
   // Iterate over the allocation profile data calling "callback"
   // for every allocation.
@@ -112,7 +112,7 @@
   // Allocation data dump filtering callback:
   // gets passed object pointer and size
   // needs to return true iff the object is to be filtered out of the dump.
-  typedef bool (*DumpFilter)(void* ptr, size_t size);
+  typedef bool (*DumpFilter)(const void* ptr, size_t size);
 
   // Dump current heap profile for leak checking purposes to file_name
   // while filtering the objects by "filter".
@@ -134,10 +134,10 @@
   // Hash table bucket to hold (de)allocation stats
   // for a given allocation call stack trace.
   struct Bucket : public Stats {
-    uintptr_t hash;   // Hash value of the stack trace
-    int       depth;  // Depth of stack trace
-    void**    stack;  // Stack trace
-    Bucket*   next;   // Next entry in hash-table
+    uintptr_t    hash;   // Hash value of the stack trace
+    int          depth;  // Depth of stack trace
+    const void** stack;  // Stack trace
+    Bucket*      next;   // Next entry in hash-table
   };
 
   // Info stored in the address map
@@ -176,12 +176,12 @@
 
   // Helper for IterateAllocs to do callback signature conversion
   // from AllocationMap::Iterate to AllocIterator.
-  static void MapArgsAllocIterator(void* ptr, AllocValue v,
+  static void MapArgsAllocIterator(const void* ptr, AllocValue v,
                                    AllocIterator callback);
 
   // Helper for DumpFilteredProfile to do object-granularity
   // heap profile dumping. It gets passed to AllocationMap::Iterate.
-  static void FilteredDumpIterator(void* ptr, AllocValue v,
+  static void FilteredDumpIterator(const void* ptr, AllocValue v,
                                    const DumpArgs& args);
 
   // data ----------------------------
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index fe74e8e..8718111 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -194,7 +194,7 @@
 //----------------------------------------------------------------------
 
 // Record an allocation in the profile.
-static void RecordAlloc(void* ptr, size_t bytes, int skip_count) {
+static void RecordAlloc(const void* ptr, size_t bytes, int skip_count) {
   heap_lock.Lock();
   if (is_on) {
     heap_profile->RecordAlloc(ptr, bytes, skip_count + 1);
@@ -226,7 +226,7 @@
 }
 
 // Record a deallocation in the profile.
-static void RecordFree(void* ptr) {
+static void RecordFree(const void* ptr) {
   heap_lock.Lock();
   if (is_on) {
     heap_profile->RecordFree(ptr);
@@ -239,15 +239,15 @@
 // Allocation/deallocation hooks for MallocHook
 //----------------------------------------------------------------------
 
-static void NewHook(void* ptr, size_t size) {
+static void NewHook(const void* ptr, size_t size) {
   if (ptr != NULL) RecordAlloc(ptr, size, 0);
 }
 
-static void DeleteHook(void* ptr) {
+static void DeleteHook(const void* ptr) {
   if (ptr != NULL) RecordFree(ptr);
 }
 
-static void MmapHook(void* result, void* start, size_t size,
+static void MmapHook(const void* result, const void* start, size_t size,
                      int prot, int flags, int fd, off_t offset) {
   // Log the mmap if necessary
   if (FLAGS_mmap_log) {
@@ -271,7 +271,7 @@
   }
 }
 
-static void MunmapHook(void* ptr, size_t size) {
+static void MunmapHook(const void* ptr, size_t size) {
   if (FLAGS_mmap_profile) {
     RecordFree(ptr);
   }
diff --git a/src/malloc_extension.cc b/src/malloc_extension.cc
index d816e65..a7eee11 100644
--- a/src/malloc_extension.cc
+++ b/src/malloc_extension.cc
@@ -101,7 +101,7 @@
                                        int histogram[kMallocHistogramSize]) {
   *blocks = 0;
   *total = 0;
-  memset(histogram, sizeof(histogram), 0);
+  memset(histogram, 0, sizeof(histogram));
   return true;
 }
 
diff --git a/src/malloc_hook.cc b/src/malloc_hook.cc
index a3e8d75..4104229 100644
--- a/src/malloc_hook.cc
+++ b/src/malloc_hook.cc
@@ -68,11 +68,11 @@
 // (weak) here, then defining it below after its use, we can avoid the problem.
 //
 ATTRIBUTE_WEAK
-extern void InitialMallocHook_New(void* ptr, size_t size);
+extern void InitialMallocHook_New(const void* ptr, size_t size);
 
 ATTRIBUTE_WEAK
-extern void InitialMallocHook_MMap(void* result,
-                                   void* start,
+extern void InitialMallocHook_MMap(const void* result,
+                                   const void* start,
                                    size_t size,
                                    int protection,
                                    int flags,
@@ -80,7 +80,7 @@
                                    off_t offset);
 
 ATTRIBUTE_WEAK
-extern void InitialMallocHook_Sbrk(void* result, ptrdiff_t increment);
+extern void InitialMallocHook_Sbrk(const void* result, ptrdiff_t increment);
 
 MallocHook::NewHook    MallocHook::new_hook_ = InitialMallocHook_New;
 MallocHook::DeleteHook MallocHook::delete_hook_ = NULL;
@@ -111,13 +111,13 @@
 // hook will be called, and do an if check, for every new.  Alas.
 // TODO(csilvers): add support for removing a hook from the middle of a chain.
 
-void InitialMallocHook_New(void* ptr, size_t size) {
+void InitialMallocHook_New(const void* ptr, size_t size) {
    if (MallocHook::GetNewHook() == &InitialMallocHook_New)
      MallocHook::SetNewHook(NULL);
 }
 
-void InitialMallocHook_MMap(void* result,
-                            void* start,
+void InitialMallocHook_MMap(const void* result,
+                            const void* start,
                             size_t size,
                             int protection,
                             int flags,
@@ -127,14 +127,16 @@
     MallocHook::SetMmapHook(NULL);
 }
 
-void InitialMallocHook_Sbrk(void* result, ptrdiff_t increment) {
+void InitialMallocHook_Sbrk(const void* result, ptrdiff_t increment) {
   if (MallocHook::GetSbrkHook() == &InitialMallocHook_Sbrk)
     MallocHook::SetSbrkHook(NULL);
 }
 
-DECLARE_ATTRIBUTE_SECTION(google_malloc);
+DEFINE_ATTRIBUTE_SECTION_VARS(google_malloc);
+DECLARE_ATTRIBUTE_SECTION_VARS(google_malloc);
   // actual functions are in debugallocation.cc or tcmalloc.cc
-DECLARE_ATTRIBUTE_SECTION(malloc_hook);
+DEFINE_ATTRIBUTE_SECTION_VARS(malloc_hook);
+DECLARE_ATTRIBUTE_SECTION_VARS(malloc_hook);
   // actual functions are in this file, malloc_hook.cc, and low_level_alloc.cc
 
 #define ADDR_IN_ATTRIBUTE_SECTION(addr, name) \
@@ -146,7 +148,7 @@
 // Return true iff 'caller' is a return address within a function
 // that calls one of our hooks via MallocHook:Invoke*.
 // A helper for GetCallerStackTrace.
-static inline bool InHookCaller(void* caller) {
+static inline bool InHookCaller(const void* caller) {
   return ADDR_IN_ATTRIBUTE_SECTION(caller, google_malloc) ||
          ADDR_IN_ATTRIBUTE_SECTION(caller, malloc_hook);
   // We can use one section for everything except tcmalloc_or_debug
@@ -159,11 +161,13 @@
 
 static inline void CheckInHookCaller() {
   if (!checked_sections) {
+    INIT_ATTRIBUTE_SECTION_VARS(google_malloc);
     if (ATTRIBUTE_SECTION_START(google_malloc) ==
         ATTRIBUTE_SECTION_STOP(google_malloc)) {
       RAW_LOG(ERROR, "google_malloc section is missing, "
                      "thus InHookCaller is broken!");
     }
+    INIT_ATTRIBUTE_SECTION_VARS(malloc_hook);
     if (ATTRIBUTE_SECTION_START(malloc_hook) ==
         ATTRIBUTE_SECTION_STOP(malloc_hook)) {
       RAW_LOG(ERROR, "malloc_hook section is missing, "
@@ -178,7 +182,7 @@
 // into the implementations for GetStackTrace instead of the skip_count.
 int MallocHook::GetCallerStackTrace(void** result, int max_depth,
                                     int skip_count) {
-#ifndef HAVE___ATTRIBUTE__
+#ifndef HAVE_ATTRIBUTE_SECTION_START
   // Fall back to GetStackTrace and good old but fragile frame skip counts.
   // Note: this path is inaccurate when a hook is not called directly by an
   // allocation function but is daisy-chained through another hook,
diff --git a/src/memfs_malloc.cc b/src/memfs_malloc.cc
new file mode 100644
index 0000000..438758d
--- /dev/null
+++ b/src/memfs_malloc.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// 
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Arun Sharma
+//
+// A tcmalloc system allocator that uses a memory based filesystem such as
+// tmpfs or hugetlbfs
+//
+// Since these only exist on linux, we only register this allocator there.
+
+#ifdef __linux
+
+#include "config.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/vfs.h>           // for statfs
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/googleinit.h"
+#include "base/logging.h"
+#include "base/sysinfo.h"
+#include "system-alloc.h"
+
+using std::string;
+
+DEFINE_string(memfs_malloc_path, EnvToString("TCMALLOC_MEMFS_MALLOC_PATH", ""),
+              "Path where hugetlbfs or tmpfs is mounted. The caller is "
+              "responsible for ensuring that the path is unique and does "
+              "not conflict with another process");
+
+// Hugetlbfs based allocator for tcmalloc
+class HugetlbSysAllocator: public SysAllocator {
+public:
+  HugetlbSysAllocator(int fd, int page_size)
+    : big_page_size_(page_size),
+      hugetlb_fd_(fd),
+      hugetlb_base_(0) {
+  }
+
+  void* Alloc(size_t size, size_t *actual_size, size_t alignment);
+
+private:
+  int64 big_page_size_;
+  int hugetlb_fd_;      // file descriptor for hugetlb
+  off_t hugetlb_base_;
+};
+
+// No locking needed here since we assume that tcmalloc calls
+// us with an internal lock held (see tcmalloc/system-alloc.cc).
+void* HugetlbSysAllocator::Alloc(size_t size, size_t *actual_size,
+                                 size_t alignment) {
+
+  // We don't respond to allocation requests smaller than big_page_size_ unless
+  // the caller is willing to take more than they asked for.
+  if (actual_size == NULL && size < big_page_size_) {
+    return NULL;
+  }
+
+  // Enforce huge page alignment.  Be careful to deal with overflow.
+  if (alignment < big_page_size_) alignment = big_page_size_;
+  size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
+  if (aligned_size < size) {
+    return NULL;
+  }
+  size = aligned_size;
+
+  // Ask for extra memory if alignment > pagesize
+  size_t extra = 0;
+  if (alignment > big_page_size_) {
+    extra = alignment - big_page_size_;
+  }
+
+  // This is not needed for hugetlbfs, but needed for tmpfs.  Annoyingly
+  // hugetlbfs returns EINVAL for ftruncate.
+  int ret = ftruncate(hugetlb_fd_, hugetlb_base_ + size + extra);
+  if (ret != 0 && errno != EINVAL) {
+    failed_ = true;
+    return NULL;
+  }
+
+  // Note: size + extra does not overflow since:
+  //            size + alignment < (1<<NBITS).
+  // and        extra <= alignment
+  // therefore  size + extra < (1<<NBITS)
+  void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
+                      MAP_SHARED, hugetlb_fd_, hugetlb_base_);
+  if (result == reinterpret_cast<void*>(MAP_FAILED)) {
+    failed_ = true;
+    return NULL;
+  }
+  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
+
+  // Adjust the return memory so it is aligned
+  size_t adjust = 0;
+  if ((ptr & (alignment - 1)) != 0) {
+    adjust = alignment - (ptr & (alignment - 1));
+  }
+  ptr += adjust;
+  hugetlb_base_ += (size + extra);
+
+  if (actual_size) {
+    *actual_size = size + extra - adjust;
+  }
+
+  return reinterpret_cast<void*>(ptr);
+}
+
+static void InitSystemAllocator() {
+  if (FLAGS_memfs_malloc_path.length()) {
+    // Don't rely on the caller to ensure unique path name
+    char pid[64];              // pids are smaller than this!
+    int n = snprintf(pid, sizeof(pid), "%u", (unsigned int)(getpid()));
+    CHECK(n < sizeof(pid));
+    string hugetlbfs_path = FLAGS_memfs_malloc_path
+      + "." + pid;
+
+    int hugetlb_fd = open(hugetlbfs_path.c_str(), O_RDWR | O_CREAT | O_EXCL,
+                          0600);
+    CHECK_ERR(hugetlb_fd);
+    // Cleanup memory on process exit
+    CHECK_ERR(unlink(hugetlbfs_path.c_str()));
+
+    // Use fstatfs to figure out the default page size for memfs
+    struct statfs sfs;
+    CHECK_ERR(fstatfs(hugetlb_fd, &sfs));
+    int64 page_size = sfs.f_bsize;
+
+    SysAllocator *alloc = new HugetlbSysAllocator(hugetlb_fd, page_size);
+    // Register ourselves with tcmalloc
+    RegisterSystemAllocator(alloc, 0);
+  }
+}
+
+REGISTER_MODULE_INITIALIZER(memfs_malloc, { InitSystemAllocator(); });
+
+#endif   /* ifdef __linux */
diff --git a/src/memory_region_map.cc b/src/memory_region_map.cc
index 1a3d8d8..96d4f32 100644
--- a/src/memory_region_map.cc
+++ b/src/memory_region_map.cc
@@ -129,7 +129,7 @@
   MallocHook::SetMremapHook(NULL);
   MallocHook::SetSbrkHook(NULL);
   MallocHook::SetMunmapHook(NULL);
-  regions_->~RegionSet();
+  if (regions_) regions_->~RegionSet();
   regions_ = NULL;
   bool deleted_arena = LowLevelAlloc::DeleteArena(arena_);
   if (deleted_arena) {
@@ -293,7 +293,7 @@
 static const int kStripFrames = 3;
 #endif
 
-void MemoryRegionMap::RecordRegionAddition(void* start, size_t size) {
+void MemoryRegionMap::RecordRegionAddition(const void* start, size_t size) {
   Region region;
   // Record data about this memory acquisition call:
   region.start_addr = reinterpret_cast<uintptr_t>(start);
@@ -318,7 +318,7 @@
   Unlock();
 }
 
-void MemoryRegionMap::RecordRegionRemoval(void* start, size_t size) {
+void MemoryRegionMap::RecordRegionRemoval(const void* start, size_t size) {
   Lock();
   HandleSavedRegionsLocked(&InsertRegionLocked);
     // first handle saved regions if any
@@ -389,8 +389,8 @@
   Unlock();
 }
 
-void MemoryRegionMap::MmapHook(void* result,
-                               void* start, size_t size,
+void MemoryRegionMap::MmapHook(const void* result,
+                               const void* start, size_t size,
                                int prot, int flags,
                                int fd, off_t offset) {
   // TODO(maxim): replace all 0x%"PRIxS" by %p when RAW_VLOG uses a safe
@@ -405,16 +405,17 @@
   }
 }
 
-void MemoryRegionMap::MunmapHook(void* ptr, size_t size) {
+void MemoryRegionMap::MunmapHook(const void* ptr, size_t size) {
   RAW_VLOG(2, "MUnmap of %p %"PRIuS"", ptr, size);
   if (size != 0) {
     RecordRegionRemoval(ptr, size);
   }
 }
 
-void MemoryRegionMap::MremapHook(void* result,
-                                 void* old_addr, size_t old_size,
-                                 size_t new_size, int flags, void* new_addr) {
+void MemoryRegionMap::MremapHook(const void* result,
+                                 const void* old_addr, size_t old_size,
+                                 size_t new_size, int flags,
+                                 const void* new_addr) {
   RAW_VLOG(2, "MRemap = 0x%"PRIxS" of 0x%"PRIxS" %"PRIuS" "
               "to %"PRIuS" flags %d new_addr=0x%"PRIxS,
               (uintptr_t)result, (uintptr_t)old_addr,
@@ -428,15 +429,15 @@
 
 extern "C" void* __sbrk(ptrdiff_t increment);  // defined in libc
 
-void MemoryRegionMap::SbrkHook(void* result, ptrdiff_t increment) {
+void MemoryRegionMap::SbrkHook(const void* result, ptrdiff_t increment) {
   RAW_VLOG(2, "Sbrk = 0x%"PRIxS" of %"PRIdS"", (uintptr_t)result, increment);
   if (result != reinterpret_cast<void*>(-1)) {
     if (increment > 0) {
-      void* new_end = __sbrk(0);
+      void* new_end = sbrk(0);
       RecordRegionAddition(result, reinterpret_cast<uintptr_t>(new_end) -
                                    reinterpret_cast<uintptr_t>(result));
     } else if (increment < 0) {
-      void* new_end = __sbrk(0);
+      void* new_end = sbrk(0);
       RecordRegionRemoval(new_end, reinterpret_cast<uintptr_t>(result) -
                                    reinterpret_cast<uintptr_t>(new_end));
     }
diff --git a/src/memory_region_map.h b/src/memory_region_map.h
index 0e72341..f6df6af 100644
--- a/src/memory_region_map.h
+++ b/src/memory_region_map.h
@@ -179,20 +179,21 @@
 
   // Record addition of a memory region at address "start" of size "size"
   // (called from our mmap/mremap/sbrk hooks).
-  static void RecordRegionAddition(void* start, size_t size);
+  static void RecordRegionAddition(const void* start, size_t size);
   // Record deletion of a memory region at address "start" of size "size"
   // (called from our munmap/mremap/sbrk hooks).
-  static void RecordRegionRemoval(void* start, size_t size);
+  static void RecordRegionRemoval(const void* start, size_t size);
 
   // Hooks for MallocHook
-  static void MmapHook(void* result,
-                       void* start, size_t size,
+  static void MmapHook(const void* result,
+                       const void* start, size_t size,
                        int prot, int flags,
                        int fd, off_t offset);
-  static void MunmapHook(void* ptr, size_t size);
-  static void MremapHook(void* result, void* old_addr, size_t old_size,
-                         size_t new_size, int flags, void* new_addr);
-  static void SbrkHook(void* result, ptrdiff_t increment);
+  static void MunmapHook(const void* ptr, size_t size);
+  static void MremapHook(const void* result, const void* old_addr,
+                         size_t old_size, size_t new_size, int flags,
+                         const void* new_addr);
+  static void SbrkHook(const void* result, ptrdiff_t increment);
 
   // Log all memory regions; Useful for debugging only.
   // Assumes Lock() is held
diff --git a/src/pprof b/src/pprof
index 1e81c38..625829e 100755
--- a/src/pprof
+++ b/src/pprof
@@ -72,7 +72,7 @@
 use warnings;
 use Getopt::Long;
 
-my $PPROF_VERSION = "0.92";
+my $PPROF_VERSION = "0.93";
 
 # These are the object tools we use, which come from various sources.
 # We want to invoke them directly, rather than via users' aliases and/or
@@ -2873,18 +2873,16 @@
   # type:
   my $default_prefix = "/usr/bin/";
   # Follow symlinks (at least for systems where "file" supports that)
-  my $file_type = `/usr/bin/file -L $prog_file || /usr/bin/file $prog_file`;
-  if ($file_type =~ /ELF 32-bit/) {
-    $default_prefix = "/usr/bin/";
-  } elsif ($file_type =~ /ELF 64-bit/) {
+  my $file_type = `/usr/bin/file -L $prog_file 2>/dev/null || /usr/bin/file $prog_file`;
+  if ($file_type !~ /executable/) {
+    warn "WARNING: program $prog_file is apparently not an executable\n";
+    # Don't change the default prefix.
+  } elsif ($file_type =~ /64-bit/) {
     # Change $address_length to 16 if the program file is ELF 64-bit.
     # We can't detect this from many (most?) heap or lock contention
     # profiles, since the actual addresses referenced are generally in low
     # memory even for 64-bit programs.
     $address_length = 16;
-  } else {
-    print STDERR "WARNING: program $prog_file is apparently not an ELF file\n";
-    # Don't change the default prefix.
   }
 
   # Go fill in %obj_tool_map with the pathnames to use:
@@ -2915,7 +2913,7 @@
   if (-x $path) { return $path; }
 
   # Try the normal system default (/usr/bin/):
-  if ($prefix ne "/usr/bin") {
+  if ($prefix ne "/usr/bin/") {
     $path = "/usr/bin/$tool";
     if ($main::opt_debug) { print STDERR "  (c) Trying '$path'\n"; }
     if (-x $path) { return $path; }
@@ -3000,17 +2998,21 @@
     $image = "/usr/lib/debug$image";
   }
   my $nm = $obj_tool_map{"nm"};
-  # Not all nm's in the world can do demangling themselves, so rely on c++filt
   my $cppfilt = $obj_tool_map{"c++filt"};
-  my $nm_command = "$nm -n $image | $cppfilt";
-  my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);
-  if (!(%{$symbol_table})) {
-    # Coulnd't get any symbols: probably $image isn't a debug library.
-    # In that case, we can at least get the *exported* symbols via -D
-    $nm_command = "$nm -D -n $image | $cppfilt";
-    $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);
+
+  # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
+  # binary doesn't support --demangle.  For the first, we try with -D
+  # to at least get *exported* symbols.  For the second, we use c++filt
+  # instead of --demangle.  (c++filt is less reliable though, because it
+  # might interpret nm meta-data as c++ symbols and try to demangle it :-/)
+  foreach my $nm_command ("$nm -n --demangle $image 2>/dev/null",
+			  "$nm -n $image 2>&1 | $cppfilt",
+			  "$nm -D -n --demangle $image 2>/dev/null",
+			  "$nm -D -n $image 2>&1 | $cppfilt") {
+    my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);
+    return $symbol_table if (%{$symbol_table});
   }
-  return $symbol_table;
+  return GetProcedureBoundariesViaNm("$nm -n $image", $regexp);   # last hope
 }
 
 
diff --git a/src/profiler.cc b/src/profiler.cc
index c2d7487..ffd39be 100644
--- a/src/profiler.cc
+++ b/src/profiler.cc
@@ -38,18 +38,8 @@
 // do nothing in the per-thread registration code.
 
 #include "config.h"
-
-// On __x86_64__ systems, we may need _XOPEN_SOURCE defined to get access
-// to the struct ucontext, via signal.h.  We need _GNU_SOURCE to get access
-// to REG_RIP.  (We can use some trickery to get around that need, though.)
-// Note this #define must come first!
-#define _GNU_SOURCE 1
-// If #define _GNU_SOURCE causes problems, this might work instead
-// for __x86_64__.  It will cause problems for FreeBSD though!, because
-// it turns off the needed __BSD_VISIBLE.
-//#define _XOPEN_SOURCE 500
+#include "getpc.h"      // should be first to get the _GNU_SOURCE dfn
 #include <signal.h>
-
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -61,6 +51,9 @@
 #include <sys/types.h>
 #endif
 #include <errno.h>
+#ifdef HAVE_UCONTEXT_H
+#include <ucontext.h>           // for ucontext_t (and also mcontext_t)
+#endif
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -70,162 +63,20 @@
 #include <google/profiler.h>
 #include <google/stacktrace.h>
 #include "base/commandlineflags.h"
+#include "base/logging.h"
 #include "base/googleinit.h"
 #include "base/mutex.h"
 #include "base/spinlock.h"
+#include "base/sysinfo.h"
 #ifdef HAVE_CONFLICT_SIGNAL_H
 #include "conflict-signal.h"          /* used on msvc machines */
 #endif
-#include "base/logging.h"
 
 using std::string;
 
 DEFINE_string(cpu_profile, "",
               "Profile file name (used if CPUPROFILE env var not specified)");
 
-
-// This might be used by GetPC, below.
-// If the profiler interrupt happened just when the current function was
-// entering the stack frame, or after leaving it but just before
-// returning, then the stack trace cannot see the caller function
-// anymore.
-// GetPC tries to unwind the current function call in this case to avoid
-// false edges in the profile graph skipping over a function.
-// A static array of this struct helps GetPC detect these situations.
-//
-// This is a best effort patch -- if we fail to detect such a situation, or
-// mess up the PC, nothing happens; the returned PC is not used for any
-// further processing.
-struct CallUnrollInfo {
-  // Offset from (e)ip register where this instruction sequence should be
-  // matched. Interpreted as bytes. Offset 0 is the next instruction to
-  // execute. Be extra careful with negative offsets in architectures of
-  // variable instruction length (like x86) - it is not that easy as taking
-  // an offset to step one instruction back!
-  int pc_offset;
-  // The actual instruction bytes. Feel free to make it larger if you need
-  // a longer sequence.
-  char ins[16];
-  // How many byutes to match from ins array?
-  size_t ins_size;
-  // The offset from the stack pointer (e)sp where to look for the call
-  // return address. Interpreted as bytes.
-  int return_sp_offset;
-};
-
-
-// TODO: gather the necessary instruction bytes for other architectures.
-#if defined __i386
-static CallUnrollInfo callunrollinfo[] = {
-  // Entry to a function:  push %ebp;  mov  %esp,%ebp
-  // Top-of-stack contains the caller IP.
-  { 0,
-    {0x55, 0x89, 0xe5}, 3,
-    0
-  },
-  // Entry to a function, second instruction:  push %ebp;  mov  %esp,%ebp
-  // Top-of-stack contains the old frame, caller IP is +4.
-  { -1,
-    {0x55, 0x89, 0xe5}, 3,
-    4
-  },
-  // Return from a function: RET.
-  // Top-of-stack contains the caller IP.
-  { 0,
-    {0xc3}, 1,
-    0
-  }
-};
-
-#endif
-
-// Figure out how to get the PC for our architecture.
-
-// __i386, including (at least) Linux
-#if defined HAVE_STRUCT_SIGCONTEXT_EIP
-typedef struct sigcontext SigStructure;
-inline void* GetPC(const SigStructure& sig_structure ) {
-#if defined __i386
-  // See comment above struct CallUnrollInfo.
-  // Only try instruction flow matching if both eip and esp looks
-  // reasonable.
-  if ((sig_structure.eip & 0xffff0000) != 0 &&
-      (~sig_structure.eip & 0xffff0000) != 0 &&
-      (sig_structure.esp & 0xffff0000) != 0) {
-    char* eip = (char*)sig_structure.eip;
-    for (int i = 0; i < arraysize(callunrollinfo); ++i) {
-      if (!memcmp(eip + callunrollinfo[i].pc_offset, callunrollinfo[i].ins,
-                  callunrollinfo[i].ins_size)) {
-        // We have a match.
-        void **retaddr = (void**)(sig_structure.esp +
-                                  callunrollinfo[i].return_sp_offset);
-        return *retaddr;
-      }
-    }
-  }
-#endif
-  return (void*)sig_structure.eip;
-}
-
-// freebsd (__i386, I assume) and Mac OS X (i386)
-#elif defined HAVE_STRUCT_SIGCONTEXT_SC_EIP
-typedef struct sigcontext SigStructure;
-inline void* GetPC(const SigStructure& sig_structure ) {
-  return (void*)sig_structure.sc_eip;
-}
-
-// __ia64
-#elif defined HAVE_STRUCT_SIGCONTEXT_SC_IP
-typedef struct sigcontext SigStructure;
-inline void* GetPC(const SigStructure& sig_structure ) {
-  return (void*)sig_structure.sc_ip;
-}
-
-// __x86_64__
-// This may require _XOPEN_SOURCE to have access to ucontext
-#elif defined HAVE_STRUCT_UCONTEXT_UC_MCONTEXT
-typedef struct ucontext SigStructure;
-inline void* GetPC(const SigStructure& sig_structure ) {
-  // For this architecture, the regs are stored in a data structure that can
-  // be accessed either as a flat array or (via some trickery) as a struct.
-  // Alas, the index we need into the array, is only defined for _GNU_SOURCE.
-  // Lacking that, we can interpret the register array as a struct sigcontext.
-  // This works in practice, but is probably not guaranteed by anything.
-# ifdef REG_RIP    // only defined if _GNU_SOURCE is 1, probably
-  return (void*)(sig_structure.uc_mcontext.gregs[REG_RIP]);
-# else
-  const struct sigcontext* const sc =
-      reinterpret_cast<const struct sigcontext*>(&sig_structure.uc_mcontext.gregs);
-  return (void*)(sc->rip);
-# endif
-}
-
-// solaris (probably solaris-x86, but I'm not sure)
-#elif defined HAVE_STRUCT_SIGINFO_SI_FADDR
-typedef struct siginfo SigStructure;
-inline void* GetPC(const SigStructure& sig_structure ) {
-  return (void*)sig_structure.si_faddr; // maybe not correct
-}
-
-// mac (OS X) powerpc, 32 bit (64-bit would use sigcontext64, on OS X 10.4+)
-#elif defined HAVE_STRUCT_SIGCONTEXT_SC_IR
-typedef struct sigcontext SigStructure;
-inline void* GetPC(const SigStructure& sig_structure ) {
-  return (void*)sig_structure.sc_ir;  // a guess, based on the comment /* pc */
-}
-
-// ibook powerpc
-#elif defined HAVE_STRUCT_SIGCONTEXT_REGS__NIP
-typedef struct sigcontext SigStructure;
-inline void* GetPC(const SigStructure& sig_structure ) {
-  return (void*)sig_structure.regs->nip;
-}
-
-#else
-#error I dont know what your PC is
-
-#endif
-
 // This takes as an argument an environment-variable name (like
 // CPUPROFILE) whose value is supposed to be a file-path, and sets
 // path to that path, and returns true.  If the env var doesn't exist,
@@ -274,13 +125,13 @@
   ~ProfileData();
 
   // Is profiling turned on at all
-  inline bool enabled() { return out_ >= 0; }
+  inline bool enabled() const { return out_ >= 0; }
 
   // What is the frequency of interrupts (ticks per second)
-  inline int frequency() { return frequency_; }
+  inline int frequency() const { return frequency_; }
 
   // Record an interrupt at "pc"
-  void Add(unsigned long pc);
+  void Add(void* pc);
 
   void FlushTable();
 
@@ -304,9 +155,9 @@
 
   // Hash-table/eviction-buffer entry
   struct Entry {
-    Slot count;                 // Number of hits
-    Slot depth;                 // Stack depth
-    Slot stack[kMaxStackDepth]; // Stack contents
+    Slot count;                  // Number of hits
+    Slot depth;                  // Stack depth
+    Slot stack[kMaxStackDepth];  // Stack contents
   };
 
   // Hash table bucket
@@ -339,10 +190,12 @@
   void FlushEvicted();
 
   // Handler that records the interrupted pc in the profile data
-  static void prof_handler(int sig, SigStructure sig_structure );
+  static void prof_handler(int sig, siginfo_t*, void* signal_ucontext);
 
-  // Sets the timer interrupt signal handler to the specified routine
-  static void SetHandler(void (*handler)(int));
+  // Sets the timer interrupt signal handler to one that stores the pc
+  static void EnableHandler();
+  // "Turn off" the timer interrupt signal handler
+  static void DisableHandler();
 };
 
 // Evict the specified entry to the evicted-entry buffer
@@ -361,18 +214,17 @@
 }
 
 // Initialize profiling: activated if getenv("CPUPROFILE") exists.
-ProfileData::ProfileData() :
-  hash_(0),
-  evict_(0),
-  num_evicted_(0),
-  out_(-1),
-  count_(0),
-  evictions_(0),
-  total_bytes_(0),
-  fname_(0),
-  frequency_(0),
-  start_time_(0) {
-
+ProfileData::ProfileData()
+    : hash_(0),
+      evict_(0),
+      num_evicted_(0),
+      out_(-1),
+      count_(0),
+      evictions_(0),
+      total_bytes_(0),
+      fname_(0),
+      frequency_(0),
+      start_time_(0) {
   // Get frequency of interrupts (if specified)
   char junk;
   const char* fr = getenv("CPUPROFILE_FREQUENCY");
@@ -385,7 +237,7 @@
   }
 
   // Ignore signals until we decide to turn profiling on
-  SetHandler(SIG_IGN);
+  DisableHandler();
 
   ProfilerRegisterThread();
 
@@ -401,9 +253,8 @@
 #endif
 
   if (!Start(fname.c_str())) {
-    fprintf(stderr, "Can't turn on cpu profiling: ");
-    perror(fname.c_str());
-    exit(1);
+    RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n",
+            fname.c_str(), strerror(errno));
   }
 }
 
@@ -453,7 +304,7 @@
   }
 
   // Setup handler for SIGPROF interrupts
-  SetHandler((void (*)(int)) prof_handler);
+  EnableHandler();
 
   return true;
 }
@@ -463,12 +314,41 @@
   Stop();
 }
 
+// Dump /proc/maps data to fd.  Copied from heap-profile-table.cc.
+#define NO_INTR(fn)  do {} while ((fn) < 0 && errno == EINTR)
+
+static void FDWrite(int fd, const char* buf, size_t len) {
+  while (len > 0) {
+    ssize_t r;
+    NO_INTR(r = write(fd, buf, len));
+    RAW_CHECK(r >= 0, "write failed");
+    buf += r;
+    len -= r;
+  }
+}
+
+static void DumpProcSelfMaps(int fd) {
+  ProcMapsIterator::Buffer iterbuf;
+  ProcMapsIterator it(0, &iterbuf);   // 0 means "current pid"
+
+  uint64 start, end, offset;
+  int64 inode;
+  char *flags, *filename;
+  ProcMapsIterator::Buffer linebuf;
+  while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
+    int written = it.FormatLine(linebuf.buf_, sizeof(linebuf.buf_),
+                                start, end, flags, offset, inode, filename,
+                                0);
+    FDWrite(fd, linebuf.buf_, written);
+  }
+}
+
 // Stop profiling and write out any collected profile data
 void ProfileData::Stop() {
   MutexLock l(&state_lock_);
 
   // Prevent handler from running anymore
-  SetHandler(SIG_IGN);
+  DisableHandler();
 
   // This lock prevents interference with signal handlers in other threads
   SpinLockHolder l2(&table_lock_);
@@ -500,15 +380,7 @@
   FlushEvicted();
 
   // Dump "/proc/self/maps" so we get list of mapped shared libraries
-  int maps = open("/proc/self/maps", O_RDONLY);
-  if (maps >= 0) {
-    char buf[100];
-    ssize_t r;
-    while ((r = read(maps, buf, sizeof(buf))) > 0) {
-      write(out_, buf, r);
-    }
-    close(maps);
-  }
+  DumpProcSelfMaps(out_);
 
   close(out_);
   fprintf(stderr, "PROFILE: interrupts/evictions/bytes = %d/%d/%" PRIuS "\n",
@@ -541,24 +413,30 @@
   }
 }
 
-void ProfileData::SetHandler(void (*handler)(int)) {
+void ProfileData::EnableHandler() {
   struct sigaction sa;
-  sa.sa_handler = handler;
-  sa.sa_flags   = SA_RESTART;
+  sa.sa_sigaction = prof_handler;
+  sa.sa_flags = SA_RESTART | SA_SIGINFO;
   sigemptyset(&sa.sa_mask);
-  if (sigaction(SIGPROF, &sa, NULL) != 0) {
-    perror("sigaction(SIGPROF)");
-    exit(1);
-  }
+  RAW_CHECK(sigaction(SIGPROF, &sa, NULL) == 0, "sigaction failed");
 }
 
+void ProfileData::DisableHandler() {
+  struct sigaction sa;
+  sa.sa_handler = SIG_IGN;
+  sa.sa_flags = SA_RESTART;
+  sigemptyset(&sa.sa_mask);
+  RAW_CHECK(sigaction(SIGPROF, &sa, NULL) == 0, "sigaction failed");
+}
+
+
 void ProfileData::FlushTable() {
   MutexLock l(&state_lock_);
   if (out_ < 0) {
     // Profiling is not enabled
     return;
   }
-  SetHandler(SIG_IGN);       // Disable timer interrupts while we're flushing
+  DisableHandler();       // Disable timer interrupts while we're flushing
   {
     // Move data from hash table to eviction buffer
     SpinLockHolder l(&table_lock_);
@@ -576,16 +454,16 @@
     // Write out all pending data
     FlushEvicted();
   }
-  SetHandler((void (*)(int)) prof_handler);
+  EnableHandler();
 }
 
 // Record the specified "pc" in the profile data
-void ProfileData::Add(unsigned long pc) {
+void ProfileData::Add(void* pc) {
   void* stack[kMaxStackDepth];
 
   // The top-most active routine doesn't show up as a normal
   // frame, but as the "pc" value in the signal handler context.
-  stack[0] = (void*)pc;
+  stack[0] = pc;
 
   // We remove the top three entries (typically Add, prof_handler, and
   // a signal handler setup routine) since they are artifacts of
@@ -605,6 +483,18 @@
   }
 
   SpinLockHolder l(&table_lock_);
+
+  // If the signal handler starts executing (and calls this function)
+  // just as a thread calls Stop, it is possible for Stop to acquire
+  // state_lock_, disable the signal, and acquire table_lock_ before
+  // this function can grab table_lock_.  If that happens, Stop will
+  // delete hash_ and the rest of the allocated structures before this
+  // function grabs table_lock_ and continues.  In that case, hash_
+  // will be NULL here.
+  if (hash_ == NULL) {
+    return;
+  }
+
   count_++;
 
   // See if table already has an entry for this stack trace
@@ -656,15 +546,7 @@
     const char* buf = reinterpret_cast<char*>(evict_);
     size_t bytes = sizeof(evict_[0]) * num_evicted_;
     total_bytes_ += bytes;
-    while (bytes > 0) {
-      ssize_t r = write(out_, buf, bytes);
-      if (r < 0) {
-        perror("write");
-        exit(1);
-      }
-      buf += r;
-      bytes -= r;
-    }
+    FDWrite(out_, buf, bytes);
   }
   num_evicted_ = 0;
 }
@@ -674,9 +556,9 @@
 static ProfileData pdata;
 
 // Signal handler that records the pc in the profile-data structure
-void ProfileData::prof_handler(int sig, SigStructure sig_structure) {
+void ProfileData::prof_handler(int sig, siginfo_t*, void* signal_ucontext) {
   int saved_errno = errno;
-  pdata.Add( (unsigned long int)GetPC( sig_structure ) );
+  pdata.Add(GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext)));
   errno = saved_errno;
 }
 
diff --git a/src/stacktrace_powerpc-inl.h b/src/stacktrace_powerpc-inl.h
index 67eb2ed..a3be131 100644
--- a/src/stacktrace_powerpc-inl.h
+++ b/src/stacktrace_powerpc-inl.h
@@ -4,6 +4,7 @@
 // Produce stack trace.  I'm guessing (hoping!) the code is much like
 // for x86.  For apple machines, at least, it seems to be; see
 //    http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
+//    http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
 // Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
 
 #include <stdint.h>   // for uintptr_t
@@ -42,11 +43,18 @@
     if (skip_count > 0) {
       skip_count--;
     } else {
-#ifdef __LP64__   // Indicates 64-bit pointers under OS
-      result[n++] = *(sp+2);   // ?? untested
-#else
-      result[n++] = *(sp+1);
-#endif
+      // sp[2] holds the "Link Record", according to RTArch-59.html.
+      // On PPC, the Link Record is the return address of the
+      // subroutine call (what instruction we run after our function
+      // finishes).  This is the same as the stack-pointer of our
+      // parent routine, which is what we want here.  We believe that
+      // the compiler will always set up the LR for subroutine calls.
+      //
+      // It may be possible to get the stack-pointer of the parent
+      // routine directly.  In my experiments, this code works:
+      //    result[n++] = NextStackFrame(sp)[-18]
+      // But I'm not sure what this is doing, exactly, or how reliable it is.
+      result[n++] = *(sp+2);  // sp[2] holds the Link Record (return address)
     }
     sp = NextStackFrame(sp);
   }
diff --git a/src/system-alloc.cc b/src/system-alloc.cc
index 60fdf70..8b400aa 100644
--- a/src/system-alloc.cc
+++ b/src/system-alloc.cc
@@ -96,7 +96,7 @@
 public:
   SbrkSysAllocator() : SysAllocator() {
   }
-  void* Alloc(size_t size, size_t alignment);
+  void* Alloc(size_t size, size_t *actual_size, size_t alignment);
 };
 static char sbrk_space[sizeof(SbrkSysAllocator)];
 
@@ -104,7 +104,7 @@
 public:
   MmapSysAllocator() : SysAllocator() {
   }
-  void* Alloc(size_t size, size_t alignment);
+  void* Alloc(size_t size, size_t *actual_size, size_t alignment);
 };
 static char mmap_space[sizeof(MmapSysAllocator)];
 
@@ -112,13 +112,13 @@
 public:
   DevMemSysAllocator() : SysAllocator() {
   }
-  void* Alloc(size_t size, size_t alignment);
+  void* Alloc(size_t size, size_t *actual_size, size_t alignment);
 };
 static char devmem_space[sizeof(DevMemSysAllocator)];
 
 static const int kStaticAllocators = 3;
 // kMaxDynamicAllocators + kStaticAllocators;
-static const int kMaxAllocators = 4;
+static const int kMaxAllocators = 5;
 SysAllocator *allocators[kMaxAllocators];
 
 bool RegisterSystemAllocator(SysAllocator *a, int priority) {
@@ -132,11 +132,20 @@
 }
 
 
-void* SbrkSysAllocator::Alloc(size_t size, size_t alignment) {
+void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size,
+                              size_t alignment) {
   // sbrk will release memory if passed a negative number, so we do
   // a strict check here
   if (static_cast<ptrdiff_t>(size + alignment) < 0) return NULL;
 
+  // could theoretically return the "extra" bytes here, but this
+  // is simple and correct.
+  if (actual_size) {
+    *actual_size = size;
+  }
+
+  // This doesn't overflow because TCMalloc_SystemAlloc has already
+  // tested for overflow at the alignment boundary.
   size = ((size + alignment - 1) / alignment) * alignment;
   void* result = sbrk(size);
   if (result == reinterpret_cast<void*>(-1)) {
@@ -170,11 +179,22 @@
   return reinterpret_cast<void*>(ptr);
 }
 
-void* MmapSysAllocator::Alloc(size_t size, size_t alignment) {
+void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size,
+                              size_t alignment) {
+  // could theoretically return the "extra" bytes here, but this
+  // is simple and correct.
+  if (actual_size) {
+    *actual_size = size;
+  }
+
   // Enforce page alignment
   if (pagesize == 0) pagesize = getpagesize();
   if (alignment < pagesize) alignment = pagesize;
-  size = ((size + alignment - 1) / alignment) * alignment;
+  size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
+  if (aligned_size < size) {
+    return NULL;
+  }
+  size = aligned_size;
 
   // Ask for extra memory if alignment > pagesize
   size_t extra = 0;
@@ -214,7 +234,8 @@
   return reinterpret_cast<void*>(ptr);
 }
 
-void* DevMemSysAllocator::Alloc(size_t size, size_t alignment) {
+void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size,
+                                size_t alignment) {
   static bool initialized = false;
   static off_t physmem_base;  // next physical memory address to allocate
   static off_t physmem_limit; // maximum physical address allowed
@@ -241,10 +262,20 @@
     initialized = true;
   }
 
+  // could theoretically return the "extra" bytes here, but this
+  // is simple and correct.
+  if (actual_size) {
+    *actual_size = size;
+  }
+
   // Enforce page alignment
   if (pagesize == 0) pagesize = getpagesize();
   if (alignment < pagesize) alignment = pagesize;
-  size = ((size + alignment - 1) / alignment) * alignment;
+  size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
+  if (aligned_size < size) {
+    return NULL;
+  }
+  size = aligned_size;
 
   // Ask for extra memory if alignment > pagesize
   size_t extra = 0;
@@ -300,7 +331,8 @@
   allocators[i++] = new (mmap_space) MmapSysAllocator();
 }
 
-void* TCMalloc_SystemAlloc(size_t size, size_t alignment) {
+void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
+                           size_t alignment) {
   // Discard requests that overflow
   if (size + alignment < size) return NULL;
 
@@ -321,7 +353,7 @@
       SysAllocator *a = allocators[j];
       if (a == NULL) continue;
       if (a->usable_ && !a->failed_) {
-        void* result = a->Alloc(size, alignment);
+        void* result = a->Alloc(size, actual_size, alignment);
         if (result != NULL) return result;
       }
     }
diff --git a/src/system-alloc.h b/src/system-alloc.h
index e1ba66e..13f01a8 100644
--- a/src/system-alloc.h
+++ b/src/system-alloc.h
@@ -40,10 +40,18 @@
 
 // REQUIRES: "alignment" is a power of two or "0" to indicate default alignment
 //
-// Allocate and return "N" bytes of zeroed memory.  The returned
-// pointer is a multiple of "alignment" if non-zero.  Returns NULL
-// when out of memory.
-extern void* TCMalloc_SystemAlloc(size_t bytes, size_t alignment = 0);
+// Allocate and return "N" bytes of zeroed memory.
+//
+// If actual_bytes is NULL then the returned memory is exactly the
+// requested size.  If actual bytes is non-NULL then the allocator
+// may optionally return more bytes than asked for (i.e. return an
+// entire "huge" page if a huge page allocator is in use).
+//
+// The returned pointer is a multiple of "alignment" if non-zero.
+//
+// Returns NULL when out of memory.
+extern void* TCMalloc_SystemAlloc(size_t bytes, size_t *actual_bytes,
+                                  size_t alignment = 0);
 
 // This call is a hint to the operating system that the pages
 // contained in the specified range of memory will not be used for a
@@ -65,7 +73,7 @@
   };
   virtual ~SysAllocator() {};
 
-  virtual void* Alloc(size_t size, size_t alignment) = 0;
+  virtual void* Alloc(size_t size, size_t *actual_size, size_t alignment) = 0;
 
   // So the allocator can be turned off at compile time
   bool usable_;
@@ -90,6 +98,6 @@
                                                        int priority);
 
 // Number of SysAllocators known to call RegisterSystemAllocator
-static const int kMaxDynamicAllocators = 1;
+static const int kMaxDynamicAllocators = 2;
 
 #endif /* TCMALLOC_SYSTEM_ALLOC_H__ */
diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc
index 08ae2fa..c4577c1 100644
--- a/src/tcmalloc.cc
+++ b/src/tcmalloc.cc
@@ -546,7 +546,7 @@
 // Metadata allocator -- keeps stats about how many bytes allocated
 static uint64_t metadata_system_bytes = 0;
 static void* MetaDataAlloc(size_t bytes) {
-  void* result = TCMalloc_SystemAlloc(bytes);
+  void* result = TCMalloc_SystemAlloc(bytes, NULL);
   if (result != NULL) {
     metadata_system_bytes += bytes;
   }
@@ -1260,15 +1260,17 @@
   ASSERT(kMaxPages >= kMinSystemAlloc);
   if (n > kMaxValidPages) return false;
   Length ask = (n>kMinSystemAlloc) ? n : static_cast<Length>(kMinSystemAlloc);
-  void* ptr = TCMalloc_SystemAlloc(ask << kPageShift, kPageSize);
+  size_t actual_size;
+  void* ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
   if (ptr == NULL) {
     if (n < ask) {
       // Try growing just "n" pages
       ask = n;
-      ptr = TCMalloc_SystemAlloc(ask << kPageShift, kPageSize);
+      ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
     }
     if (ptr == NULL) return false;
   }
+  ask = actual_size >> kPageShift;
   RecordGrowth(ask << kPageShift);
 
   uint64_t old_system_bytes = system_bytes_;
@@ -2562,6 +2564,9 @@
     // Check whether the kernel also supports TLS (needs to happen at runtime)
     CheckIfKernelSupportsTLS();
 #endif
+#ifdef WIN32                    // patch the windows VirtualAlloc, etc.
+    PatchWindowsFunctions();    // defined in windows/patch_functions.cc
+#endif
     free(malloc(1));
     TCMalloc_ThreadCache::InitTSD();
     free(malloc(1));
@@ -2575,6 +2580,9 @@
       if (level < 1) level = 1;
       PrintStats(level);
     }
+#ifdef WIN32
+    UnpatchWindowsFunctions();
+#endif
   }
 };
 static TCMallocGuard module_enter_exit_hook;
@@ -2804,6 +2812,17 @@
 // Exported routines
 //-------------------------------------------------------------------
 
+// For Windows, it's not possible to override the system
+// malloc/calloc/realloc/free.  Instead, we define our own version and
+// then patch the windows assembly code to have the windows code call
+// ours.  This requires our functions have distinct names.
+#ifdef WIN32
+# define malloc   Perftools_malloc
+# define calloc   Perftools_calloc
+# define realloc  Perftools_realloc
+# define free     Perftools_free
+#endif
+
 // CAVEAT: The code structure below ensures that MallocHook methods are always
 //         called from the stack frame of the invoked allocation function.
 //         heap-checker.cc depends on this to start a stack trace from
diff --git a/src/tests/addressmap_unittest.cc b/src/tests/addressmap_unittest.cc
index 868235d..2cf125d 100644
--- a/src/tests/addressmap_unittest.cc
+++ b/src/tests/addressmap_unittest.cc
@@ -46,8 +46,8 @@
 using std::set;
 using std::random_shuffle;
 
-static void SetCheckCallback(void* ptr, int val,
-                             set<pair<void*, int> >* check_set) {
+static void SetCheckCallback(const void* ptr, int val,
+                             set<pair<const void*, int> >* check_set) {
   check_set->insert(make_pair(ptr, val));
 }
 
@@ -105,7 +105,7 @@
     }
 
     // Check all entries
-    set<pair<void*, int> > check_set;
+    set<pair<const void*, int> > check_set;
     map.Iterate(SetCheckCallback, &check_set);
     CHECK_EQ(check_set.size(), N);
     for (int i = 0; i < N; ++i) {
diff --git a/src/tests/getpc_test.cc b/src/tests/getpc_test.cc
new file mode 100644
index 0000000..f1497d5
--- /dev/null
+++ b/src/tests/getpc_test.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+//
+// This verifies that GetPC works correctly.  This test uses a minimum
+// of Google infrastructure, to make it very easy to port to various
+// O/Ses and CPUs and test that GetPC is working.
+
+#include "config.h"
+#include "getpc.h"        // should be first to get the _GNU_SOURCE dfn
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/time.h>     // for setitimer
+
+// Needs to be volatile so compiler doesn't try to optimize it away
+static volatile void* getpc_retval = NULL;    // what GetPC returns
+static volatile bool prof_handler_called = false;
+
+static void prof_handler(int sig, siginfo_t*, void* signal_ucontext) {
+  if (!prof_handler_called)
+    getpc_retval = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
+  prof_handler_called = true;  // only store the retval once
+}
+
+static void RoutineCallingTheSignal() {
+  struct sigaction sa;
+  sa.sa_sigaction = prof_handler;
+  sa.sa_flags = SA_RESTART | SA_SIGINFO;
+  sigemptyset(&sa.sa_mask);
+  if (sigaction(SIGPROF, &sa, NULL) != 0) {
+    perror("sigaction");
+    exit(1);
+  }
+
+  struct itimerval timer;
+  timer.it_interval.tv_sec = 0;
+  timer.it_interval.tv_usec = 1000;
+  timer.it_value = timer.it_interval;
+  setitimer(ITIMER_PROF, &timer, 0);
+
+  // Now we need to do some work for a while, that doesn't call any
+  // other functions, so we can be guaranteed that when the SIGPROF
+  // fires, we're the routine executing.
+  int r = 0;
+  for (int i = 0; !prof_handler_called; ++i) {
+    for (int j = 0; j < i; j++) {
+      r ^= i;
+      r <<= 1;
+      r ^= j;
+      r >>= 1;
+    }
+  }
+
+  // Now make sure the above loop doesn't get optimized out
+  srand(r);
+}
+
+// This is an upper bound of how many bytes the instructions for
+// RoutineCallingTheSignal might be.  There's probably a more
+// principled way to do this, but I don't know how portable it would be.
+// (The function is 372 bytes when compiled with -g on Mac OS X 10.4.
+// I can imagine it would be even bigger in 64-bit architectures.)
+const int kRoutineSize = 512 * sizeof(void*)/4;    // allow 1024 for 64-bit
+
+int main(int argc, char** argv) {
+  RoutineCallingTheSignal();
+
+  // Annoyingly, C++ disallows casting pointer-to-function to
+  // pointer-to-object, so we use a C-style cast instead.
+  char* expected = (char*)&RoutineCallingTheSignal;
+  char* actual = (char*)getpc_retval;
+
+  // For ia64, ppc64, and parisc64, the function pointer is actually
+  // a struct.  For instance, ia64's dl-fptr.h:
+  //   struct fdesc {          /* An FDESC is a function descriptor.  */
+  //      ElfW(Addr) ip;      /* code entry point */
+  //      ElfW(Addr) gp;      /* global pointer */
+  //   };
+  // We want the code entry point.
+#if defined(__ia64) || defined(__ppc64)     // NOTE: ppc64 is UNTESTED
+  expected = ((char**)expected)[0];         // this is "ip"
+#endif
+
+  if (actual < expected || actual > expected + kRoutineSize) {
+    printf("Test FAILED: actual PC: %p, expected PC: %p\n", actual, expected);
+    return 1;
+  } else {
+    printf("PASS\n");
+    return 0;
+  }
+}
diff --git a/src/tests/heap-checker-death_unittest.sh b/src/tests/heap-checker-death_unittest.sh
index 6ba628b..5e2e8ae 100755
--- a/src/tests/heap-checker-death_unittest.sh
+++ b/src/tests/heap-checker-death_unittest.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 # Copyright (c) 2005, Google Inc.
 # All rights reserved.
 # 
@@ -47,7 +47,7 @@
 EXE="${1:-$BINDIR}/heap-checker_unittest"
 TMPDIR="/tmp/heap_check_death_info"
 
-function ALARM() {
+ALARM() {
   # You need perl to run pprof, so I assume it's installed
   perl -e '
     $timeout=$ARGV[0]; shift;
@@ -69,25 +69,26 @@
 # $3: regexp to match a line in the output;
 # $4: regexp to not match a line in the output;
 # $5+ args to pass to $EXE
-function Test() {
-  local timeout="$1"
+Test() {
+  # Note: make sure these varnames don't conflict with any vars outside Test()!
+  timeout="$1"
   shift
-  local expected_ec="$1"
+  expected_ec="$1"
   shift
-  local expected_regexp="$1"
+  expected_regexp="$1"
   shift
-  local unexpected_regexp="$1"
+  unexpected_regexp="$1"
   shift
 
   echo -n "Testing $EXE with $@ ... "
-  local output="$TMPDIR/output"
+  output="$TMPDIR/output"
   ALARM $timeout env "$@" $EXE > "$output" 2>&1
-  local actual_ec=$?
-  local ec_ok=$(expr "$actual_ec" : "$expected_ec$" >/dev/null || echo false)
-  local matches_ok=$(test -z "$expected_regexp" || \
-                     grep -q "$expected_regexp" "$output" || echo false)
-  local negmatches_ok=$(test -z "$unexpected_regexp" || \
-                        ! grep -q "$unexpected_regexp" "$output" || echo false)
+  actual_ec=$?
+  ec_ok=$(expr "$actual_ec" : "$expected_ec$" >/dev/null || echo false)
+  matches_ok=$(test -z "$expected_regexp" || \
+               grep -q "$expected_regexp" "$output" || echo false)
+  negmatches_ok=$(test -z "$unexpected_regexp" || \
+                  ! grep -q "$unexpected_regexp" "$output" || echo false)
   if $ec_ok && $matches_ok && $negmatches_ok; then
     echo "PASS"
     return 0  # 0: success
diff --git a/src/tests/heap-checker_unittest.cc b/src/tests/heap-checker_unittest.cc
index e1bf73f..594323a 100644
--- a/src/tests/heap-checker_unittest.cc
+++ b/src/tests/heap-checker_unittest.cc
@@ -106,6 +106,12 @@
 #include <google/malloc_extension.h>
 #include <google/stacktrace.h>
 
+// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
+// form of the name instead.
+#ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
 using namespace std;
 
 
@@ -809,8 +815,8 @@
   inet_ntoa(addr);
   const time_t now = time(NULL);
   ctime(&now);
-  void *stack[1];
 #ifdef HAVE_EXECINFO_H
+  void *stack[1];
   backtrace(stack, 1);
 #endif
 #ifdef HAVE_GRP_H
diff --git a/src/tests/heap-profiler_unittest.sh b/src/tests/heap-profiler_unittest.sh
index e559c72..04bf7cc 100755
--- a/src/tests/heap-profiler_unittest.sh
+++ b/src/tests/heap-profiler_unittest.sh
@@ -77,11 +77,11 @@
   exec=`unset HEAPPROFILE; $HEAP_PROFILER --help | awk '{print $2; exit;}'`
 
   if [ $# = 2 ]; then
-    [ -e "$1" ] || { echo "Profile not found: $1"; exit 1; }
-    [ -e "$2" ] || { echo "Profile not found: $2"; exit 1; }
+    [ -f "$1" ] || { echo "Profile not found: $1"; exit 1; }
+    [ -f "$2" ] || { echo "Profile not found: $2"; exit 1; }
     $PPROF --base="$1" $exec "$2" >$TEST_TMPDIR/output.pprof 2>&1
   else
-    [ -e "$1" ] || { echo "Profile not found: $1"; exit 1; }
+    [ -f "$1" ] || { echo "Profile not found: $1"; exit 1; }
     $PPROF $exec "$1" >$TEST_TMPDIR/output.pprof 2>&1
   fi
 
@@ -99,8 +99,10 @@
   fi
 }
 
-export HEAPPROFILE="$TEST_TMPDIR/test"
-export HEAP_PROFILE_INUSE_INTERVAL="10240"   # need this to be 10Kb
+HEAPPROFILE="$TEST_TMPDIR/test"
+HEAP_PROFILE_INUSE_INTERVAL="10240"   # need this to be 10Kb
+export HEAPPROFILE
+export HEAP_PROFILE_INUSE_INTERVAL
 
 # We make the unittest run a child process, to test that the child
 # process doesn't try to write a heap profile as well and step on the
diff --git a/src/tests/low_level_alloc_unittest.cc b/src/tests/low_level_alloc_unittest.cc
index a305bcb..1e6f0a5 100644
--- a/src/tests/low_level_alloc_unittest.cc
+++ b/src/tests/low_level_alloc_unittest.cc
@@ -147,7 +147,7 @@
 static MallocHook::DeleteHook old_free_hook;
 
 // called on each alloc if kCallMallocHook specified
-static void AllocHook(void *p, size_t size) {
+static void AllocHook(const void *p, size_t size) {
   if (using_low_level_alloc) {
     allocates++;
   }
@@ -157,7 +157,7 @@
 }
 
 // called on each free if kCallMallocHook specified
-static void FreeHook(void *p) {
+static void FreeHook(const void *p) {
   if (using_low_level_alloc) {
     frees++;
   }
diff --git a/src/tests/maybe_threads_unittest.sh b/src/tests/maybe_threads_unittest.sh
index ce26765..f319ea1 100755
--- a/src/tests/maybe_threads_unittest.sh
+++ b/src/tests/maybe_threads_unittest.sh
@@ -62,5 +62,7 @@
               | xargs dirname`
 
 # We need to set the library-path too: libtcmalloc depends on libstacktrace
-LD_LIBRARY_PATH="$UNITTEST_DIR" LD_PRELOAD="$UNITTEST_DIR/libtcmalloc.so" \
+# (Note we try several different names: OS X uses its own libpath varname).
+LD_LIBRARY_PATH="$UNITTEST_DIR" DYLD_LIBRARY_PATH="$UNITTEST_DIR" \
+LD_PRELOAD="$UNITTEST_DIR/libtcmalloc.so" \
     $UNITTEST_DIR/low_level_alloc_unittest
diff --git a/src/tests/memalign_unittest.cc b/src/tests/memalign_unittest.cc
index 359e104..f83f57d 100644
--- a/src/tests/memalign_unittest.cc
+++ b/src/tests/memalign_unittest.cc
@@ -37,15 +37,23 @@
 // aligned, and that writing into the objects works.
 
 #include "config_for_unittests.h"
-#include "tcmalloc.h"      // must come first, to pick up posix_memalign
+
+// Complicated ordering requirements.  tcmalloc.h defines (indirectly)
+// _POSIX_C_SOURCE, which it needs so stdlib.h defines posix_memalign.
+// unistd.h, on the other hand, requires _POSIX_C_SOURCE to be unset,
+// at least on Mac OS X, in order to define getpagesize.  The solution
+// is to #include unistd.h first.  This is safe because unistd.h
+// doesn't sub-include stdlib.h, so we'll still get posix_memalign
+// when we #include stdlib.h.  Blah.
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>        // for getpagesize()
+#endif
+#include "tcmalloc.h"      // must come early, to pick up posix_memalign
 #include <stdlib.h>        // defines posix_memalign
 #include <stdio.h>         // for the printf at the end
 #ifdef HAVE_STDINT_H
 #include <stdint.h>        // for uintptr_t
 #endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>        // for getpagesize()
-#endif
 #include "base/basictypes.h"
 #include "base/logging.h"
 
diff --git a/src/tests/system-alloc_unittest.cc b/src/tests/system-alloc_unittest.cc
index 526bbc1..7045abe 100644
--- a/src/tests/system-alloc_unittest.cc
+++ b/src/tests/system-alloc_unittest.cc
@@ -51,11 +51,15 @@
     invoked_ = false;
   }
 
-  void* Alloc(size_t size, size_t alignment) {
+  void* Alloc(size_t size, size_t *actual_size, size_t alignment) {
     invoked_ = true;
     void *result = &array_[ptr_];
     uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
 
+    if (actual_size) {
+      *actual_size = size;
+    }
+
     // Try to get more memory for alignment
     size_t extra = alignment - (ptr & (alignment-1));
     size += extra;
diff --git a/src/tests/tcmalloc_unittest.cc b/src/tests/tcmalloc_unittest.cc
index 1c84cfa..c4c18cd 100644
--- a/src/tests/tcmalloc_unittest.cc
+++ b/src/tests/tcmalloc_unittest.cc
@@ -47,7 +47,17 @@
 //   the memory upper-bound.
 
 #include "config_for_unittests.h"
-#include "tcmalloc.h"      // must come first, to pick up posix_memalign
+// Complicated ordering requirements.  tcmalloc.h defines (indirectly)
+// _POSIX_C_SOURCE, which it needs so stdlib.h defines posix_memalign.
+// unistd.h, on the other hand, requires _POSIX_C_SOURCE to be unset,
+// at least on FreeBSD, in order to define sbrk.  The solution
+// is to #include unistd.h first.  This is safe because unistd.h
+// doesn't sub-include stdlib.h, so we'll still get posix_memalign
+// when we #include stdlib.h.  Blah.
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>        // for testing sbrk hooks
+#endif
+#include "tcmalloc.h"      // must come early, to pick up posix_memalign
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -55,6 +65,12 @@
 #include <stdint.h>        // for intptr_t
 #endif
 #include <sys/types.h>     // for size_t
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>         // for open; used with mmap-hook test
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>      // for testing mmap hooks
+#endif
 #include <assert.h>
 #include <vector>
 #include <string>
@@ -65,6 +81,12 @@
 #include "google/malloc_extension.h"
 #include "tests/testutil.h"
 
+// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
+// form of the name instead.
+#ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
 #define LOGSTREAM   stdout
 
 using std::vector;
@@ -482,7 +504,7 @@
 static void TestCalloc(size_t n, size_t s, bool ok) {
   char* p = reinterpret_cast<char*>(calloc(n, s));
   if (FLAGS_verbose)
-    fprintf(LOGSTREAM, "calloc(%x, %x): %p\n", n, s, p);
+    fprintf(LOGSTREAM, "calloc(%"PRIxS", %"PRIxS"): %p\n", n, s, p);
   if (!ok) {
     CHECK(p == NULL);  // calloc(n, s) should not succeed
   } else {
@@ -586,15 +608,39 @@
   std::set_new_handler(saved_handler);
 }
 
-// These are used as callbacks by the sanity-check
-static int g_new_hook_calls = 0;
-static int g_delete_hook_calls = 0;
-static void IncrementNewHookCalls(void* ptr, size_t size) {
-  g_new_hook_calls++;
-}
-static void IncrementDeleteHookCalls(void* ptr) {
-  g_delete_hook_calls++;
-}
+
+// These are used as callbacks by the sanity-check.  Set* and Reset*
+// register the hook that counts how many times the associated memory
+// function is called.  After each such call, call Verify* to verify
+// that we used the tcmalloc version of the call, and not the libc.
+// Note the ... in the hook signature: we don't care what arguments
+// the hook takes.
+#define MAKE_HOOK_CALLBACK(hook_type)                                   \
+  static int g_##hook_type##_calls = 0;                                 \
+  static void IncrementCallsTo##hook_type(...) {                        \
+    g_##hook_type##_calls++;                                            \
+  }                                                                     \
+  static void Verify##hook_type##WasCalled() {                          \
+    CHECK_GT(g_##hook_type##_calls, 0);                                 \
+    g_##hook_type##_calls = 0;  /* reset for next call */               \
+  }                                                                     \
+  static MallocHook::hook_type g_old_##hook_type;                       \
+  static void Set##hook_type() {                                        \
+    g_old_##hook_type = MallocHook::Set##hook_type(                     \
+     (MallocHook::hook_type)&IncrementCallsTo##hook_type);              \
+  }                                                                     \
+  static void Reset##hook_type() {                                      \
+    CHECK_EQ(MallocHook::Set##hook_type(g_old_##hook_type),             \
+             (MallocHook::hook_type)&IncrementCallsTo##hook_type);      \
+  }
+
+// We do one for each hook typedef in malloc_hook.h
+MAKE_HOOK_CALLBACK(NewHook);
+MAKE_HOOK_CALLBACK(DeleteHook);
+MAKE_HOOK_CALLBACK(MmapHook);
+MAKE_HOOK_CALLBACK(MremapHook);
+MAKE_HOOK_CALLBACK(MunmapHook);
+MAKE_HOOK_CALLBACK(SbrkHook);
 
 
 int main(int argc, char** argv) {
@@ -643,62 +689,110 @@
   {
     // We use new-hook and delete-hook to verify we actually called the
     // tcmalloc version of these routines, and not the libc version.
-    MallocHook::NewHook old_new_hook = MallocHook::GetNewHook();
-    MallocHook::DeleteHook old_delete_hook = MallocHook::GetDeleteHook();
-    MallocHook::SetNewHook(&IncrementNewHookCalls);
-    MallocHook::SetDeleteHook(&IncrementDeleteHookCalls);
-    int expected_new_hook_calls = 0;
-    int expected_delete_hook_calls = 0;
+    SetNewHook();      // defined as part of MAKE_HOOK_CALLBACK, above
+    SetDeleteHook();   // ditto
 
     void* p1 = malloc(10);
-    expected_new_hook_calls++;
+    VerifyNewHookWasCalled();
     free(p1);
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
     p1 = calloc(10, 2);
-    expected_new_hook_calls++;
+    VerifyNewHookWasCalled();
     p1 = realloc(p1, 30);
-    expected_new_hook_calls++;
-    expected_delete_hook_calls++;
+    VerifyNewHookWasCalled();
+    VerifyDeleteHookWasCalled();
     cfree(p1);  // synonym for free
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
-    CHECK(posix_memalign(&p1, sizeof(p1), 40) == 0);
-    expected_new_hook_calls++;
+    CHECK_EQ(posix_memalign(&p1, sizeof(p1), 40), 0);
+    VerifyNewHookWasCalled();
     free(p1);
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
     p1 = memalign(sizeof(p1) * 2, 50);
-    expected_new_hook_calls++;
+    VerifyNewHookWasCalled();
     free(p1);
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
     p1 = valloc(60);
-    expected_new_hook_calls++;
+    VerifyNewHookWasCalled();
     free(p1);
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
     p1 = pvalloc(70);
-    expected_new_hook_calls++;
+    VerifyNewHookWasCalled();
     free(p1);
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
     char* p2 = new char;
-    expected_new_hook_calls++;
+    VerifyNewHookWasCalled();
     delete p2;
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
     p2 = new char[100];
-    expected_new_hook_calls++;
+    VerifyNewHookWasCalled();
     delete p2;
-    expected_delete_hook_calls++;
+    VerifyDeleteHookWasCalled();
 
-    // We'll test the no-throw variants later
-    CHECK_EQ(expected_new_hook_calls, g_new_hook_calls);
-    CHECK_EQ(expected_delete_hook_calls, g_delete_hook_calls);
-    // Reset the hooks to what they used to be
-    MallocHook::SetNewHook(old_new_hook);
-    MallocHook::SetDeleteHook(old_delete_hook);
+    // Test mmap too: both anonymous mmap and mmap of a file
+    // Note that for right now we only override mmap on linux
+    // systems, so those are the only ones for which we check.
+    SetMmapHook();
+    SetMremapHook();
+    SetMunmapHook();
+#if defined(HAVE_MMAP) && defined(__linux) && \
+       (defined(__i386__) || defined(__x86_64__))
+    int size = 8192*2;
+    p1 = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE,
+              -1, 0);
+    VerifyMmapHookWasCalled();
+    p1 = mremap(p1, size, size/2, 0);
+    VerifyMremapHookWasCalled();
+    size /= 2;
+    munmap(p1, size);
+    VerifyMunmapHookWasCalled();
+
+    int fd = open("/dev/zero", O_RDONLY);
+    CHECK_GE(fd, 0);   // make sure the open succeeded
+    p1 = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0);
+    VerifyMmapHookWasCalled();
+    munmap(p1, 8192);
+    VerifyMunmapHookWasCalled();
+    close(fd);
+#else   // this is just to quiet the compiler: make sure all fns are called
+    IncrementCallsToMmapHook();
+    IncrementCallsToMunmapHook();
+    IncrementCallsToMremapHook();
+    VerifyMmapHookWasCalled();
+    VerifyMremapHookWasCalled();
+    VerifyMunmapHookWasCalled();
+#endif
+
+    // Test sbrk
+    SetSbrkHook();
+#if defined(HAVE_SBRK) && defined(__linux) && \
+       (defined(__i386__) || defined(__x86_64__))
+    p1 = sbrk(8192);
+    VerifySbrkHookWasCalled();
+    p1 = sbrk(-8192);
+    VerifySbrkHookWasCalled();
+    // However, sbrk hook should *not* be called with sbrk(0)
+    p1 = sbrk(0);
+    CHECK_EQ(g_SbrkHook_calls, 0);
+#else   // this is just to quiet the compiler: make sure all fns are called
+    IncrementCallsToSbrkHook();
+    VerifySbrkHookWasCalled();
+#endif
+
+    // Reset the hooks to what they used to be.  These are all
+    // defined as part of MAKE_HOOK_CALLBACK, above.
+    ResetNewHook();
+    ResetDeleteHook();
+    ResetMmapHook();
+    ResetMremapHook();
+    ResetMunmapHook();
+    ResetSbrkHook();
   }
 
   // Check that "lots" of memory can be allocated
diff --git a/src/windows/TODO b/src/windows/TODO
index 46972fb..708ec23 100644
--- a/src/windows/TODO
+++ b/src/windows/TODO
@@ -3,9 +3,11 @@
 * Play around with ExperimentalGetStackTrace
 * Support the windows-level memory-allocation functions?  See
     /home/build/googleclient/earth/client/tools/memorytracking/client/memorytrace/src/memorytrace.cpp
-    /home/build/googleclient/earth/client/tools/memorytracking/thirdparty/sidestep/PreamblePatcher.{h,cpp}
+    /home/build/googleclient/total_recall/common/sitestep/*
     http://www.internals.com/articles/apispy/apispy.htm
     http://www.wheaty.net/APISPY32.zip
+* Verify /proc/xxx/maps:
+    http://www.geocities.com/wah_java_dotnet/procmap/index.html
 * Figure out how to edit the executable IAT so tcmalloc.dll is loaded first
 * Use QueryPerformanceCounter instead of GetTickCount() (also for sparsehash)
 
@@ -60,19 +62,25 @@
    http://support.microsoft.com/kb/268343
 
 ----
+Itimer replacement:
+   http://msdn2.microsoft.com/en-us/library/ms712713.aspx
+
+----
 Changes I've had to make to the project file:
 
 0) When creating the project file, click on "no autogenerated files"
 
+--- For each project:
+1) Alt-F7 -> General -> [pulldown "all configurations" ] -> Output Directory -> $(SolutionDir)$(ConfigurationName)
+2) Alt-F7 -> General -> [pulldown "all configurations" ] -> Intermediate Directory -> $(ConfigurationName)
+
+--- For each .cc file:
 1) Alt-F7 -> C/C++ -> General -> [pulldown "all configurations"] -> Additional Include Directives --> src/windows + src/
-1') Alt-F7 -> General -> [pulldown "all configurations" ] -> Output Directory -> $(SolutionDir)$(ConfigurationName)
-    Alt-F7 -> General -> [pulldown "all configurations" ] -> Intermediate Directory -> $(ConfigurationName)
+2) Alt-F7 -> C/C++ -> Code Generation -> Runtime Library -> Multi-threaded, debug/release, DLL or not
 
 --- For DLL:
-2) Alt-F7 -> Linker -> Input -> [pulldown "all configurations" ] -> Module Definition File -> src\windows\vc7and8.def
+3) Alt-F7 -> Linker -> Input -> [pulldown "all configurations" ] -> Module Definition File -> src\windows\vc7and8.def
 --- For binaries depending on a DLL:
-2) Right-click on project -> Project Dependencies -> [add dll]
+3) Right-click on project -> Project Dependencies -> [add dll]
 --- For static binaries (not depending on a DLL)
-2) Alt-F7 -> C/C++ -> Command Line -> [pulldown "all configurations"] -> /D PERFTOOLS_DLL_DECL=
-
-
+3) Alt-F7 -> C/C++ -> Command Line -> [pulldown "all configurations"] -> /D PERFTOOLS_DLL_DECL=
diff --git a/src/windows/config.h b/src/windows/config.h
index 99c7ebe..8b38b32 100644
--- a/src/windows/config.h
+++ b/src/windows/config.h
@@ -47,6 +47,9 @@
 /* Define to 1 if you have the <execinfo.h> header file. */
 #undef HAVE_EXECINFO_H
 
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
 /* Define to 1 if you have the `geteuid' function. */
 #undef HAVE_GETEUID
 
@@ -113,42 +116,24 @@
 /* Define to 1 if the system has the type `struct mallinfo'. */
 #undef HAVE_STRUCT_MALLINFO
 
-/* Define to 1 if `eip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_EIP
-
-/* Define to 1 if `regs->nip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_REGS__NIP
-
-/* Define to 1 if `rip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_RIP
-
-/* Define to 1 if `sc_eip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_SC_EIP
-
-/* Define to 1 if `sc_ip' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_SC_IP
-
-/* Define to 1 if `sc_ir' is member of `struct sigcontext'. */
-#undef HAVE_STRUCT_SIGCONTEXT_SC_IR
-
-/* Define to 1 if `si_faddr' is member of `struct siginfo'. */
-#undef HAVE_STRUCT_SIGINFO_SI_FADDR
-
-/* Define to 1 if `uc_mcontext' is member of `struct ucontext'. */
-#undef HAVE_STRUCT_UCONTEXT_UC_MCONTEXT
-
-/* Define to 1 if you have the <syscall.h> header file. */
-#undef HAVE_SYSCALL_H
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1
 
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
 /* Define to 1 if compiler supports __thread */
 #define HAVE_TLS 1
 
+/* Define to 1 if you have the <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
@@ -185,12 +170,19 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* How to access the PC from a struct ucontext */
+#undef PC_FROM_UCONTEXT
+
 /* Always the empty-string on non-windows systems. On windows, should be
    "__declspec(dllexport)". This way, when we compile the dll, we export our
    functions/classes. It's safe to define this here because config.h is only
    used internally, to compile the DLL, and every DLL source file #includes
    "config.h" before anything else. */
-#define PERFTOOLS_DLL_DECL  __declspec(dllexport)
+#ifndef PERFTOOLS_DLL_DECL
+# define PERFTOOLS_IS_A_DLL  1   /* not set if you're statically linking */
+# define PERFTOOLS_DLL_DECL  __declspec(dllexport)
+# define PERFTOOLS_DLL_DECL_FOR_UNITTESTS  __declspec(dllimport)
+#endif
 
 /* printf format code for printing a size_t and ssize_t */
 #define PRIdS  "Id"
@@ -214,6 +206,11 @@
 /* Version number of package */
 #undef VERSION
 
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
 /* Define to `__inline__' or `__inline' if that's what the C compiler
    calls it, or to nothing if 'inline' is not supported under any name.  */
 #ifndef __cplusplus
diff --git a/src/windows/ia32_modrm_map.cc b/src/windows/ia32_modrm_map.cc
new file mode 100644
index 0000000..f1f1906
--- /dev/null
+++ b/src/windows/ia32_modrm_map.cc
@@ -0,0 +1,121 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Table of relevant information about how to decode the ModR/M byte.
+ * Based on information in the IA-32 Intel® Architecture
+ * Software DeveloperÂ’s Manual Volume 2: Instruction Set Reference.
+ */
+
+#include "mini_disassembler.h"
+#include "mini_disassembler_types.h"
+
+namespace sidestep {
+
+const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = {
+// mod == 00
+  /* r/m == 000 */ { false, false, OS_ZERO },
+  /* r/m == 001 */ { false, false, OS_ZERO },
+  /* r/m == 010 */ { false, false, OS_ZERO },
+  /* r/m == 011 */ { false, false, OS_ZERO },
+  /* r/m == 100 */ { false, false, OS_ZERO },
+  /* r/m == 101 */ { false, false, OS_ZERO },
+  /* r/m == 110 */ { true, false, OS_WORD },
+  /* r/m == 111 */ { false, false, OS_ZERO }, 
+// mod == 01
+  /* r/m == 000 */ { true, false, OS_BYTE },
+  /* r/m == 001 */ { true, false, OS_BYTE },
+  /* r/m == 010 */ { true, false, OS_BYTE },
+  /* r/m == 011 */ { true, false, OS_BYTE },
+  /* r/m == 100 */ { true, false, OS_BYTE },
+  /* r/m == 101 */ { true, false, OS_BYTE },
+  /* r/m == 110 */ { true, false, OS_BYTE },
+  /* r/m == 111 */ { true, false, OS_BYTE }, 
+// mod == 10
+  /* r/m == 000 */ { true, false, OS_WORD },
+  /* r/m == 001 */ { true, false, OS_WORD },
+  /* r/m == 010 */ { true, false, OS_WORD },
+  /* r/m == 011 */ { true, false, OS_WORD },
+  /* r/m == 100 */ { true, false, OS_WORD },
+  /* r/m == 101 */ { true, false, OS_WORD },
+  /* r/m == 110 */ { true, false, OS_WORD },
+  /* r/m == 111 */ { true, false, OS_WORD }, 
+// mod == 11
+  /* r/m == 000 */ { false, false, OS_ZERO },
+  /* r/m == 001 */ { false, false, OS_ZERO },
+  /* r/m == 010 */ { false, false, OS_ZERO },
+  /* r/m == 011 */ { false, false, OS_ZERO },
+  /* r/m == 100 */ { false, false, OS_ZERO },
+  /* r/m == 101 */ { false, false, OS_ZERO },
+  /* r/m == 110 */ { false, false, OS_ZERO },
+  /* r/m == 111 */ { false, false, OS_ZERO }
+};
+
+const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = {
+// mod == 00
+  /* r/m == 000 */ { false, false, OS_ZERO },
+  /* r/m == 001 */ { false, false, OS_ZERO },
+  /* r/m == 010 */ { false, false, OS_ZERO },
+  /* r/m == 011 */ { false, false, OS_ZERO },
+  /* r/m == 100 */ { false, true, OS_ZERO },
+  /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+  /* r/m == 110 */ { false, false, OS_ZERO },
+  /* r/m == 111 */ { false, false, OS_ZERO }, 
+// mod == 01
+  /* r/m == 000 */ { true, false, OS_BYTE },
+  /* r/m == 001 */ { true, false, OS_BYTE },
+  /* r/m == 010 */ { true, false, OS_BYTE },
+  /* r/m == 011 */ { true, false, OS_BYTE },
+  /* r/m == 100 */ { true, true, OS_BYTE },
+  /* r/m == 101 */ { true, false, OS_BYTE },
+  /* r/m == 110 */ { true, false, OS_BYTE },
+  /* r/m == 111 */ { true, false, OS_BYTE }, 
+// mod == 10
+  /* r/m == 000 */ { true, false, OS_DOUBLE_WORD },
+  /* r/m == 001 */ { true, false, OS_DOUBLE_WORD },
+  /* r/m == 010 */ { true, false, OS_DOUBLE_WORD },
+  /* r/m == 011 */ { true, false, OS_DOUBLE_WORD },
+  /* r/m == 100 */ { true, true, OS_DOUBLE_WORD },
+  /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+  /* r/m == 110 */ { true, false, OS_DOUBLE_WORD },
+  /* r/m == 111 */ { true, false, OS_DOUBLE_WORD }, 
+// mod == 11
+  /* r/m == 000 */ { false, false, OS_ZERO },
+  /* r/m == 001 */ { false, false, OS_ZERO },
+  /* r/m == 010 */ { false, false, OS_ZERO },
+  /* r/m == 011 */ { false, false, OS_ZERO },
+  /* r/m == 100 */ { false, false, OS_ZERO },
+  /* r/m == 101 */ { false, false, OS_ZERO },
+  /* r/m == 110 */ { false, false, OS_ZERO },
+  /* r/m == 111 */ { false, false, OS_ZERO },
+};
+
+};  // namespace sidestep
diff --git a/src/windows/ia32_opcode_map.cc b/src/windows/ia32_opcode_map.cc
new file mode 100644
index 0000000..c9ec18b
--- /dev/null
+++ b/src/windows/ia32_opcode_map.cc
@@ -0,0 +1,1188 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Opcode decoding maps.  Based on the IA-32 Intel® Architecture
+ * Software DeveloperÂ’s Manual Volume 2: Instruction Set Reference.  Idea
+ * for how to lay out the tables in memory taken from the implementation
+ * in the Bastard disassembly environment.
+ */
+
+#include "mini_disassembler.h"
+
+namespace sidestep {
+
+/*
+* This is the first table to be searched; the first field of each
+* Opcode in the table is either 0 to indicate you're in the
+* right table, or an index to the correct table, in the global
+* map g_pentiumOpcodeMap
+*/
+const Opcode s_first_opcode_byte[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF */ { 1, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x10 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x11 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x12 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x13 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x14 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x15 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x16 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x17 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x18 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x19 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1E */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1F */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x20 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x21 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x22 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x23 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x24 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x25 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x26 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x27 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "daa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x28 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x29 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "das", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x30 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x31 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x32 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x33 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x34 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x35 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x36 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x37 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aaa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x38 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x39 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aas", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x40 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x41 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x42 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x43 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x44 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x45 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x46 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x47 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x48 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x49 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x50 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x51 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x52 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x53 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x54 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x55 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x56 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x57 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x58 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x59 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x60 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x61 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x62 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_A, AM_NOT_USED, "bound", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x63 */ { 0, IT_GENERIC, AM_E | OT_W, AM_G | OT_W, AM_NOT_USED, "arpl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x64 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x65 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x66 */ { 0, IT_PREFIX_OPERAND, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x67 */ { 0, IT_PREFIX_ADDRESS, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x68 */ { 0, IT_GENERIC, AM_I | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x69 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_V, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6A */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I |  OT_B, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6C */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "insb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6D */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "insd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6E */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X | OT_B, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X | OT_V, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x70 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x71 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x72 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x73 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x74 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x75 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x76 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x77 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x78 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x79 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7A */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7B */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7C */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7D */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7E */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7F */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x80 */ { 2, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x81 */ { 3, IT_REFERENCE, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x82 */ { 4, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x83 */ { 5, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x84 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x85 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x86 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x87 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x88 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x89 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8C */ { 0, IT_GENERIC, AM_E | OT_W, AM_S | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8D */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, "lea", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8E */ { 0, IT_GENERIC, AM_S | OT_W, AM_E | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8F */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x90 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "nop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x91 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x92 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x93 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x94 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x95 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x96 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x97 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x98 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cwde", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x99 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cdq", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9A */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "callf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9B */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wait", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9E */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_O | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_O | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA2 */ { 0, IT_GENERIC, AM_O | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA3 */ { 0, IT_GENERIC, AM_O | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA4 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "movsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA5 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "movsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA6 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "cmpsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA7 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "cmpsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAA */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "stosb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAB */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "stosd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X| OT_B, AM_NOT_USED, "lodsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X| OT_V, AM_NOT_USED, "lodsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAE */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_Y | OT_B, AM_NOT_USED, "scasb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_Y | OT_V, AM_NOT_USED, "scasd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB1 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB2 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB3 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC0 */ { 6, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC1 */ { 7, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC2 */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC3 */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC4 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "les", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "lds", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC8 */ { 0, IT_GENERIC, AM_I | OT_W, AM_I | OT_B, AM_NOT_USED, "enter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "leave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCA */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCB */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "int3", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCD */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "int", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCE */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "into", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCF */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "iret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD0 */ { 8, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD1 */ { 9, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD2 */ { 10, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD3 */ { 11, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD4 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aam", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD5 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "xlat", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  
+  // The following 8 lines would be references to the FPU tables, but we currently
+  // do not support the FPU instructions in this disassembler.
+  
+  /* 0xD8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xDA */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xDB */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xDC */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xDD */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xDE */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xDF */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  
+  
+  /* 0xE0 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE1 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE2 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE3 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jcxz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE6 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE7 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE8 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE9 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xEA */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xEB */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xEC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xED */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xEE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xEF */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_V, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF0 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lock:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF2 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "repne:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF3 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rep:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF4 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "hlt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF6 */ { 12, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF7 */ { 13, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xFA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cli", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xFB */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xFC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xFD */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "std", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xFE */ { 14, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xFF */ { 15, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f[] = {
+  /* 0x0 */ { 16, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 17, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lsl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "invd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wbinvd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud2", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xE */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x10 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movups", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "movsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "movss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movupd" } },
+  /* 0x11 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movups", true,
+    /* F2h */ { 0, IT_GENERIC, AM_W | OT_SD, AM_V | OT_SD, AM_NOT_USED, "movsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_W | OT_SS, AM_V | OT_SS, AM_NOT_USED, "movss" },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movupd" } },
+  /* 0x12 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" },  // only one of ...
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" },  // ...these two is correct, Intel doesn't specify which
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_S, AM_NOT_USED, "movlpd" } },
+  /* 0x13 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlpd" } },
+  /* 0x14 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpcklps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpcklpd" } },
+  /* 0x15 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpckhps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpckhpd" } },
+  /* 0x16 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" },  // only one of...
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" },  // ...these two is correct, Intel doesn't specify which
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhpd" } },
+  /* 0x17 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhpd" } },
+  /* 0x18 */ { 18, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x19 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1C */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x20 */ { 0, IT_GENERIC, AM_R | OT_D, AM_C | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x21 */ { 0, IT_GENERIC, AM_R | OT_D, AM_D | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x22 */ { 0, IT_GENERIC, AM_C | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x23 */ { 0, IT_GENERIC, AM_D | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x24 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x25 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x26 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x27 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x28 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movaps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movapd" } },
+  /* 0x29 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movaps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movapd" } },
+  /* 0x2A */ { 0, IT_GENERIC, AM_V | OT_PS, AM_Q | OT_Q, AM_NOT_USED, "cvtpi2ps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_E | OT_D, AM_NOT_USED, "cvtsi2sd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_E | OT_D, AM_NOT_USED, "cvtsi2ss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_Q | OT_DQ, AM_NOT_USED, "cvtpi2pd" } },
+  /* 0x2B */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movntps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movntpd" } },
+  /* 0x2C */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvttps2pi", true,
+    /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvttsd2si" },
+    /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvttss2si" },
+    /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2pi" } },
+  /* 0x2D */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvtps2pi", true,
+    /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvtsd2si" },
+    /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvtss2si" },
+    /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2pi" } },
+  /* 0x2E */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "ucomiss", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "ucomisd" } },
+  /* 0x2F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_SS, AM_NOT_USED, "comiss", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "comisd" } },
+  /* 0x30 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wrmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x31 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdtsc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x32 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x33 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdpmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x34 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysenter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x35 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysexit", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x36 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x37 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x38 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x39 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x40 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x41 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x42 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x43 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x44 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x45 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x46 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x47 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmova", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x48 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x49 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4A */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4D */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4E */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4F */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x50 */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PS, AM_NOT_USED, "movmskps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PD, AM_NOT_USED, "movmskpd" } },
+  /* 0x51 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "sqrtps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "sqrtsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "sqrtss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "sqrtpd" } },
+  /* 0x52 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rsqrtps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rsqrtss" },
+    /* 66h */ { 0 } },
+  /* 0x53 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rcpps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rcpss" },
+    /* 66h */ { 0 } },
+  /* 0x54 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andpd" } },
+  /* 0x55 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andnps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andnpd" } },
+  /* 0x56 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "orps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "orpd" } },
+  /* 0x57 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "xorps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "xorpd" } },
+  /* 0x58 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "addps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "addsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "addss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "addpd" } },
+  /* 0x59 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "mulps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "mulsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "mulss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "mulpd" } },
+  /* 0x5A */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PS, AM_NOT_USED, "cvtps2pd", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "cvtsd2ss" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "cvtss2sd" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PD, AM_NOT_USED, "cvtpd2ps" } },
+  /* 0x5B */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2ps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvttps2dq" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvtps2dq" } },
+  /* 0x5C */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "subps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "subsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "subss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "subpd" } },
+  /* 0x5D */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "minps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "minsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "minss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "minpd" } },
+  /* 0x5E */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "divps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "divsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "divss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "divpd" } },
+  /* 0x5F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "maxps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "maxsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "maxss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "maxpd" } },
+  /* 0x60 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklbw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklbw" } },
+  /* 0x61 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklwd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklwd" } },
+  /* 0x62 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckldq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpckldq" } },
+  /* 0x63 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packsswb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packsswb" } },
+  /* 0x64 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtb" } },
+  /* 0x65 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtw" } },
+  /* 0x66 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtd" } },
+  /* 0x67 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packuswb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packuswb" } },
+  /* 0x68 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhbw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhbw" } },
+  /* 0x69 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhwd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhwd" } },
+  /* 0x6A */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhdq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhdq" } },
+  /* 0x6B */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packssdw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "packssdw" } },
+  /* 0x6C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
+  /* 0x6D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
+  /* 0x6E */ { 0, IT_GENERIC, AM_P | OT_D, AM_E | OT_D, AM_NOT_USED, "movd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_NOT_USED, "movd" } },
+  /* 0x6F */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "movq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqu" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqa" } },
+  /* 0x70 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_I |  OT_B, "pshuf", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshuflw" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufhw" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufd" } },
+  /* 0x71 */ { 19, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x72 */ { 20, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x73 */ { 21, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x74 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqb" } },
+  /* 0x75 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqw" } },
+  /* 0x76 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqd" } },
+  /* 0x77 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "emms", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  
+  // The following six opcodes are escapes into the MMX stuff, which this disassembler does not support.
+  /* 0x78 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x79 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7A */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7B */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7C */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7D */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  
+  /* 0x7E */ { 0, IT_GENERIC, AM_E | OT_D, AM_P | OT_D, AM_NOT_USED, "movd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movq" },
+    /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_DQ, AM_NOT_USED, "movd" } },
+  /* 0x7F */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_P | OT_Q, AM_NOT_USED, "movq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqu" },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqa" } },
+  /* 0x80 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x81 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x82 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x83 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x84 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x85 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x86 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x87 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x88 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x89 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8A */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8B */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8C */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8D */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8E */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x8F */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x90 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seto", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x91 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x92 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x93 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x94 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x95 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x96 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x97 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seta", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x98 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "sets", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x99 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9A */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9B */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9C */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9D */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9E */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x9F */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cpuid", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA6 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA7 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rsm", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAC */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAD */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAE */ { 22, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xAF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB2 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lss", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB4 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lfs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB5 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lgs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB6 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB7 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xB9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud1", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBA */ { 23, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBC */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBD */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBE */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xBF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC2 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "cmpps", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_I | OT_B, "cmpsd" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W  | OT_SS, AM_I | OT_B, "cmpss" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "cmppd" } },
+  /* 0xC3 */ { 0, IT_GENERIC, AM_E | OT_D, AM_G | OT_D, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_E | OT_D, AM_I | OT_B, "pinsrw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_I | OT_B, "pinsrw" } },
+  /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_I | OT_B, "pextrw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_I | OT_B, "pextrw" } },
+  /* 0xC6 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "shufps", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "shufpd" } },
+  /* 0xC7 */ { 24, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC8 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xC9 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCA */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCB */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCC */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCD */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCE */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xCF */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xD1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlw" } },
+  /* 0xD2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrld", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrld" } },
+  /* 0xD3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlq" } },
+  /* 0xD4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddq" } },
+  /* 0xD5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmullw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmullw" } },
+  /* 0xD6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "unused without prefix", true,
+    /* F2h */ { 0, IT_GENERIC, AM_P | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movdq2q" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_Q | OT_Q, AM_NOT_USED, "movq2dq" },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movq" } },
+  /* 0xD7 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_NOT_USED, "pmovmskb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_NOT_USED, "pmovmskb" } },
+  /* 0xD8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusb" } },
+  /* 0xD9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusw" } },
+  /* 0xDA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminub", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminub" } },
+  /* 0xDB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pand", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pand" } },
+  /* 0xDC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusb" } },
+  /* 0xDD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusw" } },
+  /* 0xDE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxub", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxub" } },
+  /* 0xDF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pandn", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pandn" } },
+  /* 0xE0 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgb" } },
+  /* 0xE1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psraw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrqw" } },
+  /* 0xE2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrad", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrad" } },
+  /* 0xE3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgw" } },
+  /* 0xE4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhuw" } },
+  /* 0xE5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhw" } },
+  /* 0xE6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+    /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2dq" },
+    /* F3h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2pd" },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2dq" } },
+  /* 0xE7 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movntq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movntdq" } },
+  /* 0xE8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsb" } },
+  /* 0xE9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsw" } },
+  /* 0xEA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminsw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminsw" } },
+  /* 0xEB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "por", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "por" } },
+  /* 0xEC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsb" } },
+  /* 0xED */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsw" } },
+  /* 0xEE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxsw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxsw" } },
+  /* 0xEF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pxor", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pxor" } },
+  /* 0xF0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0xF1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllw" } },
+  /* 0xF2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pslld", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pslld" } },
+  /* 0xF3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllq" } },
+  /* 0xF4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmuludq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmuludq" } },
+  /* 0xF5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaddwd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaddwd" } },
+  /* 0xF6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psadbw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psadbw" } },
+  /* 0xF7 */ { 0, IT_GENERIC, AM_P | OT_PI, AM_Q | OT_PI, AM_NOT_USED, "maskmovq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "maskmovdqu" } },
+  /* 0xF8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubb" } },
+  /* 0xF9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubw" } },
+  /* 0xFA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubd" } },
+  /* 0xFB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubq" } },
+  /* 0xFC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddb", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddb" } },
+  /* 0xFD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddw" } },
+  /* 0xFE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddd", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddd" } },
+  /* 0xFF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f00[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "sldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "str", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "ltr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f01[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "smsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lmsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_M | OT_B, AM_NOT_USED, AM_NOT_USED, "invlpg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f18[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f71[] = {
+  /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlw" } },
+  /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psraw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psraw" } },
+  /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllw", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllw" } },
+  /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f72[] = {
+  /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrld", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrld" } },
+  /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrad", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrad" } },
+  /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "pslld", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslld" } },
+  /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f73[] = {
+  /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlq" } },
+  /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllq" } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq", true,
+    /* F2h */ { 0 },
+    /* F3h */ { 0 },
+    /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq" } },
+};
+
+const Opcode s_opcode_byte_after_0fae[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxsave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxrstor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ldmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "mfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clflush/sfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+};
+
+const Opcode s_opcode_byte_after_0fba[] = {
+  /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0fc7[] = {
+  /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_Q, AM_NOT_USED, AM_NOT_USED, "cmpxch8b", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_80[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_81[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_82[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_83[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_c0[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_c1[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d0[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d1[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d2[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d3[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_f6[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_f7[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_fe[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_ff[] = {
+  /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x2 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x3 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x4 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x5 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+  /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+/*
+* A table of all the other tables, containing some extra information, e.g.
+* how to mask out the byte we're looking at.
+*/
+const OpcodeTable MiniDisassembler::s_ia32_opcode_map_[]={
+  // One-byte opcodes and jumps to larger
+  /*  0 */ {s_first_opcode_byte, 0, 0xff, 0, 0xff},
+  // Two-byte opcodes (second byte)
+  /*  1 */ {s_opcode_byte_after_0f, 0, 0xff, 0, 0xff},
+  // Start of tables for opcodes using ModR/M bits as extension
+  /*  2 */ {s_opcode_byte_after_80, 3, 0x07, 0, 0x07},
+  /*  3 */ {s_opcode_byte_after_81, 3, 0x07, 0, 0x07}, 
+  /*  4 */ {s_opcode_byte_after_82, 3, 0x07, 0, 0x07}, 
+  /*  5 */ {s_opcode_byte_after_83, 3, 0x07, 0, 0x07}, 
+  /*  6 */ {s_opcode_byte_after_c0, 3, 0x07, 0, 0x07}, 
+  /*  7 */ {s_opcode_byte_after_c1, 3, 0x07, 0, 0x07}, 
+  /*  8 */ {s_opcode_byte_after_d0, 3, 0x07, 0, 0x07}, 
+  /*  9 */ {s_opcode_byte_after_d1, 3, 0x07, 0, 0x07}, 
+  /* 10 */ {s_opcode_byte_after_d2, 3, 0x07, 0, 0x07}, 
+  /* 11 */ {s_opcode_byte_after_d3, 3, 0x07, 0, 0x07}, 
+  /* 12 */ {s_opcode_byte_after_f6, 3, 0x07, 0, 0x07}, 
+  /* 13 */ {s_opcode_byte_after_f7, 3, 0x07, 0, 0x07}, 
+  /* 14 */ {s_opcode_byte_after_fe, 3, 0x07, 0, 0x01}, 
+  /* 15 */ {s_opcode_byte_after_ff, 3, 0x07, 0, 0x07}, 
+  /* 16 */ {s_opcode_byte_after_0f00, 3, 0x07, 0, 0x07}, 
+  /* 17 */ {s_opcode_byte_after_0f01, 3, 0x07, 0, 0x07}, 
+  /* 18 */ {s_opcode_byte_after_0f18, 3, 0x07, 0, 0x07}, 
+  /* 19 */ {s_opcode_byte_after_0f71, 3, 0x07, 0, 0x07}, 
+  /* 20 */ {s_opcode_byte_after_0f72, 3, 0x07, 0, 0x07}, 
+  /* 21 */ {s_opcode_byte_after_0f73, 3, 0x07, 0, 0x07}, 
+  /* 22 */ {s_opcode_byte_after_0fae, 3, 0x07, 0, 0x07}, 
+  /* 23 */ {s_opcode_byte_after_0fba, 3, 0x07, 0, 0x07}, 
+  /* 24 */ {s_opcode_byte_after_0fc7, 3, 0x07, 0, 0x01}
+};
+
+};  // namespace sidestep
diff --git a/src/windows/mini_disassembler.cc b/src/windows/mini_disassembler.cc
new file mode 100644
index 0000000..45a90b2
--- /dev/null
+++ b/src/windows/mini_disassembler.cc
@@ -0,0 +1,419 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Implementation of MiniDisassembler.
+ */
+
+#include "mini_disassembler.h"
+
+namespace sidestep {
+
+MiniDisassembler::MiniDisassembler(bool operand_default_is_32_bits,
+                                   bool address_default_is_32_bits)
+    : operand_default_is_32_bits_(operand_default_is_32_bits),
+      address_default_is_32_bits_(address_default_is_32_bits) {
+  Initialize();
+}
+
+MiniDisassembler::MiniDisassembler()
+    : operand_default_is_32_bits_(true),
+      address_default_is_32_bits_(true) {
+  Initialize();
+}
+
+InstructionType MiniDisassembler::Disassemble(
+    byte* start_byte,
+    unsigned int& instruction_bytes) {
+  // Clean up any state from previous invocations.
+  Initialize();
+
+  // Start by processing any prefixes.
+  byte* current_byte = start_byte;
+  unsigned int size = 0;
+  InstructionType instruction_type = ProcessPrefixes(current_byte, size);
+
+  if (IT_UNKNOWN == instruction_type)
+    return instruction_type;
+
+  current_byte += size;
+  size = 0;
+
+  // Invariant: We have stripped all prefixes, and the operand_is_32_bits_
+  // and address_is_32_bits_ flags are correctly set.
+
+  instruction_type = ProcessOpcode(current_byte, 0, size);
+
+  // Check for error processing instruction
+  if ((IT_UNKNOWN == instruction_type_) || (IT_UNUSED == instruction_type_)) {
+    return IT_UNKNOWN;
+  }
+
+  current_byte += size;
+
+  // Invariant: operand_bytes_ indicates the total size of operands
+  // specified by the opcode and/or ModR/M byte and/or SIB byte.
+  // pCurrentByte points to the first byte after the ModR/M byte, or after
+  // the SIB byte if it is present (i.e. the first byte of any operands
+  // encoded in the instruction).
+
+  // We get the total length of any prefixes, the opcode, and the ModR/M and
+  // SIB bytes if present, by taking the difference of the original starting
+  // address and the current byte (which points to the first byte of the
+  // operands if present, or to the first byte of the next instruction if
+  // they are not).  Adding the count of bytes in the operands encoded in
+  // the instruction gives us the full length of the instruction in bytes.
+  instruction_bytes += operand_bytes_ + (current_byte - start_byte);
+
+  // Return the instruction type, which was set by ProcessOpcode().
+  return instruction_type_;
+}
+
+void MiniDisassembler::Initialize() {
+  operand_is_32_bits_ = operand_default_is_32_bits_;
+  address_is_32_bits_ = address_default_is_32_bits_;
+  operand_bytes_ = 0;
+  have_modrm_ = false;
+  should_decode_modrm_ = false;
+  instruction_type_ = IT_UNKNOWN;
+  got_f2_prefix_ = false;
+  got_f3_prefix_ = false;
+  got_66_prefix_ = false;
+}
+
+InstructionType MiniDisassembler::ProcessPrefixes(byte* start_byte,
+                                                  unsigned int& size) {
+  InstructionType instruction_type = IT_GENERIC; 
+  const Opcode& opcode = s_ia32_opcode_map_[0].table_[*start_byte];
+
+  switch (opcode.type_) {
+    case IT_PREFIX_ADDRESS:
+      address_is_32_bits_ = !address_default_is_32_bits_;
+      goto nochangeoperand;
+    case IT_PREFIX_OPERAND:
+      operand_is_32_bits_ = !operand_default_is_32_bits_;
+      nochangeoperand:
+    case IT_PREFIX:
+  
+      if (0xF2 == (*start_byte))
+        got_f2_prefix_ = true;
+      else if (0xF3 == (*start_byte))
+        got_f3_prefix_ = true;
+      else if (0x66 == (*start_byte))
+        got_66_prefix_ = true;
+  
+      instruction_type = opcode.type_;
+      size ++;
+      // we got a prefix, so add one and check next byte
+      ProcessPrefixes(start_byte + 1, size);
+    default:
+      break;   // not a prefix byte
+  }
+
+  return instruction_type;
+}
+
+InstructionType MiniDisassembler::ProcessOpcode(byte* start_byte,
+                                                unsigned int table_index,
+                                                unsigned int& size) {
+  const OpcodeTable& table = s_ia32_opcode_map_[table_index];   // Get our table
+  byte current_byte = (*start_byte) >> table.shift_;
+  current_byte = current_byte & table.mask_;  // Mask out the bits we will use
+  
+  // Check whether the byte we have is inside the table we have.
+  if (current_byte < table.min_lim_ || current_byte > table.max_lim_) {
+    instruction_type_ = IT_UNKNOWN;
+    return instruction_type_;
+  }
+
+  const Opcode& opcode = table.table_[current_byte];
+  if (IT_UNUSED == opcode.type_) {
+    // This instruction is not used by the IA-32 ISA, so we indicate
+    // this to the user.  Probably means that we were pointed to
+    // a byte in memory that was not the start of an instruction.
+    instruction_type_ = IT_UNUSED;
+    return instruction_type_;
+  } else if (IT_REFERENCE == opcode.type_) {
+    // We are looking at an opcode that has more bytes (or is continued
+    // in the ModR/M byte).  Recursively find the opcode definition in
+    // the table for the opcode's next byte.
+    size++;
+    ProcessOpcode(start_byte + 1, opcode.table_index_, size);
+    return instruction_type_;
+  }
+
+  const SpecificOpcode* specific_opcode = (SpecificOpcode*)&opcode;
+  if (opcode.is_prefix_dependent_) {
+    if (got_f2_prefix_ && opcode.opcode_if_f2_prefix_.mnemonic_ != 0) {
+      specific_opcode = &opcode.opcode_if_f2_prefix_;
+    } else if (got_f3_prefix_ && opcode.opcode_if_f3_prefix_.mnemonic_ != 0) {
+      specific_opcode = &opcode.opcode_if_f3_prefix_;
+    } else if (got_66_prefix_ && opcode.opcode_if_66_prefix_.mnemonic_ != 0) {
+      specific_opcode = &opcode.opcode_if_66_prefix_;
+    }
+  }
+
+  // Inv: The opcode type is known.
+  instruction_type_ = specific_opcode->type_;
+
+  // Let's process the operand types to see if we have any immediate
+  // operands, and/or a ModR/M byte.
+
+  ProcessOperand(specific_opcode->flag_dest_);
+  ProcessOperand(specific_opcode->flag_source_);
+  ProcessOperand(specific_opcode->flag_aux_);
+
+  // Inv: We have processed the opcode and incremented operand_bytes_
+  // by the number of bytes of any operands specified by the opcode
+  // that are stored in the instruction (not registers etc.).  Now
+  // we need to return the total number of bytes for the opcode and
+  // for the ModR/M or SIB bytes if they are present.
+
+  if (table.mask_ != 0xff) {
+    if (have_modrm_) {
+      // we're looking at a ModR/M byte so we're not going to
+      // count that into the opcode size
+      ProcessModrm(start_byte, size);
+      return IT_GENERIC;
+    } else {
+      // need to count the ModR/M byte even if it's just being
+      // used for opcode extension
+      size++;
+      return IT_GENERIC;
+    }
+  } else {
+    if (have_modrm_) {
+      // The ModR/M byte is the next byte.
+      size++;
+      ProcessModrm(start_byte + 1, size);
+      return IT_GENERIC;
+    } else {
+      size++;
+      return IT_GENERIC;
+    }
+  }
+}
+
+bool MiniDisassembler::ProcessOperand(int flag_operand) {
+  bool succeeded = true;
+  if (AM_NOT_USED == flag_operand)
+    return succeeded;
+
+  // Decide what to do based on the addressing mode.
+  switch (flag_operand & AM_MASK) {
+    // No ModR/M byte indicated by these addressing modes, and no
+    // additional (e.g. immediate) parameters.
+    case AM_A: // Direct address
+    case AM_F: // EFLAGS register
+    case AM_X: // Memory addressed by the DS:SI register pair
+    case AM_Y: // Memory addressed by the ES:DI register pair
+    case AM_IMPLICIT: // Parameter is implicit, occupies no space in 
+                       // instruction
+      break;
+  
+    // There is a ModR/M byte but it does not necessarily need
+    // to be decoded.
+    case AM_C: // reg field of ModR/M selects a control register
+    case AM_D: // reg field of ModR/M selects a debug register
+    case AM_G: // reg field of ModR/M selects a general register
+    case AM_P: // reg field of ModR/M selects an MMX register
+    case AM_R: // mod field of ModR/M may refer only to a general register
+    case AM_S: // reg field of ModR/M selects a segment register
+    case AM_T: // reg field of ModR/M selects a test register
+    case AM_V: // reg field of ModR/M selects a 128-bit XMM register
+      have_modrm_ = true;
+      break;
+  
+    // In these addressing modes, there is a ModR/M byte and it needs to be
+    // decoded. No other (e.g. immediate) params than indicated in ModR/M.
+    case AM_E: // Operand is either a general-purpose register or memory, 
+                 // specified by ModR/M byte
+    case AM_M: // ModR/M byte will refer only to memory
+    case AM_Q: // Operand is either an MMX register or memory (complex 
+                 // evaluation), specified by ModR/M byte
+    case AM_W: // Operand is either a 128-bit XMM register or memory (complex 
+                 // eval), specified by ModR/M byte
+      have_modrm_ = true;
+      should_decode_modrm_ = true;
+      break;
+  
+    // These addressing modes specify an immediate or an offset value
+    // directly, so we need to look at the operand type to see how many
+    // bytes.
+    case AM_I: // Immediate data.
+    case AM_J: // Jump to offset.
+    case AM_O: // Operand is at offset.
+      switch (flag_operand & OT_MASK) {
+        case OT_B: // Byte regardless of operand-size attribute.
+          operand_bytes_ += OS_BYTE;
+          break;
+        case OT_C: // Byte or word, depending on operand-size attribute.
+          if (operand_is_32_bits_)
+            operand_bytes_ += OS_WORD;
+          else
+            operand_bytes_ += OS_BYTE;
+          break;
+        case OT_D: // Doubleword, regardless of operand-size attribute.
+          operand_bytes_ += OS_DOUBLE_WORD;
+          break;
+        case OT_DQ: // Double-quadword, regardless of operand-size attribute.
+          operand_bytes_ += OS_DOUBLE_QUAD_WORD;
+          break;
+        case OT_P: // 32-bit or 48-bit pointer, depending on operand-size 
+                     // attribute.
+          if (operand_is_32_bits_)
+            operand_bytes_ += OS_48_BIT_POINTER;
+          else
+            operand_bytes_ += OS_32_BIT_POINTER;
+          break;
+        case OT_PS: // 128-bit packed single-precision floating-point data.
+          operand_bytes_ += OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING;
+          break;
+        case OT_Q: // Quadword, regardless of operand-size attribute.
+          operand_bytes_ += OS_QUAD_WORD;
+          break;
+        case OT_S: // 6-byte pseudo-descriptor.
+          operand_bytes_ += OS_PSEUDO_DESCRIPTOR;
+          break;
+        case OT_SD: // Scalar Double-Precision Floating-Point Value
+        case OT_PD: // Unaligned packed double-precision floating point value
+          operand_bytes_ += OS_DOUBLE_PRECISION_FLOATING;
+          break;
+        case OT_SS:
+          // Scalar element of a 128-bit packed single-precision 
+          // floating data.
+          // We simply return enItUnknown since we don't have to support 
+          // floating point
+          succeeded = false;
+          break;
+        case OT_V: // Word or doubleword, depending on operand-size attribute.
+          if (operand_is_32_bits_)
+            operand_bytes_ += OS_DOUBLE_WORD;
+          else
+            operand_bytes_ += OS_WORD;
+          break;
+        case OT_W: // Word, regardless of operand-size attribute.
+          operand_bytes_ += OS_WORD;
+          break;
+    
+        // Can safely ignore these.
+        case OT_A: // Two one-word operands in memory or two double-word 
+                     // operands in memory
+        case OT_PI: // Quadword MMX technology register (e.g. mm0)
+        case OT_SI: // Doubleword integer register (e.g., eax)
+          break;
+    
+        default:
+          break;
+      }
+      break;
+  
+    default:
+      break;
+  }
+
+  return succeeded;
+}
+
+bool MiniDisassembler::ProcessModrm(byte* start_byte, 
+                                    unsigned int& size) {
+  // If we don't need to decode, we just return the size of the ModR/M
+  // byte (there is never a SIB byte in this case).
+  if (!should_decode_modrm_) {
+    size++;
+    return true;
+  }
+
+  // We never care about the reg field, only the combination of the mod
+  // and r/m fields, so let's start by packing those fields together into
+  // 5 bits.
+  byte modrm = (*start_byte);
+  byte mod = modrm & 0xC0; // mask out top two bits to get mod field
+  modrm = modrm & 0x07; // mask out bottom 3 bits to get r/m field
+  mod = mod >> 3; // shift the mod field to the right place
+  modrm = mod | modrm; // combine the r/m and mod fields as discussed
+  mod = mod >> 3; // shift the mod field to bits 2..0
+
+  // Invariant: modrm contains the mod field in bits 4..3 and the r/m field
+  // in bits 2..0, and mod contains the mod field in bits 2..0
+
+  const ModrmEntry* modrm_entry = 0;
+  if (address_is_32_bits_)
+    modrm_entry = &s_ia32_modrm_map_[modrm];
+  else
+    modrm_entry = &s_ia16_modrm_map_[modrm];
+
+  // Invariant: modrm_entry points to information that we need to decode
+  // the ModR/M byte.
+  
+  // Add to the count of operand bytes, if the ModR/M byte indicates
+  // that some operands are encoded in the instruction.
+  if (modrm_entry->is_encoded_in_instruction_)
+    operand_bytes_ += modrm_entry->operand_size_;
+
+  // Process the SIB byte if necessary, and return the count
+  // of ModR/M and SIB bytes.
+  if (modrm_entry->use_sib_byte_) {
+    size++;
+    return ProcessSib(start_byte + 1, mod, size);
+  } else {
+    size++;
+    return true;
+  }
+}
+
+bool MiniDisassembler::ProcessSib(byte* start_byte, 
+                                  byte mod, 
+                                  unsigned int& size) {
+  // get the mod field from the 2..0 bits of the SIB byte
+  byte sib_base = (*start_byte) & 0x07;
+  if (0x05 == sib_base) {
+    switch (mod) {
+    case 0x00: // mod == 00
+    case 0x02: // mod == 10
+      operand_bytes_ += OS_DOUBLE_WORD;
+      break;
+    case 0x01: // mod == 01
+      operand_bytes_ += OS_BYTE;
+      break;
+    case 0x03: // mod == 11
+      // According to the IA-32 docs, there does not seem to be a disp
+      // value for this value of mod
+    default:
+      break;
+    }
+  }
+
+  size++;
+  return true;
+}
+
+};  // namespace sidestep
diff --git a/src/windows/mini_disassembler.h b/src/windows/mini_disassembler.h
new file mode 100644
index 0000000..ac14da9
--- /dev/null
+++ b/src/windows/mini_disassembler.h
@@ -0,0 +1,190 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Definition of MiniDisassembler.
+ */
+
+#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
+#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
+
+#include <windows.h>
+#include "mini_disassembler_types.h"
+
+// compatibility shim
+#include "base/logging.h"
+#define ASSERT(cond, msg)  RAW_DCHECK(cond, msg)
+#define ASSERT1(cond)      RAW_DCHECK(cond, #cond)
+
+namespace sidestep {
+
+// This small disassembler is very limited
+// in its functionality, and in fact does only the bare minimum required by the
+// preamble patching utility.  It may be useful for other purposes, however.
+//
+// The limitations include at least the following:
+//  -# No support for coprocessor opcodes, MMX, etc.
+//  -# No machine-readable identification of opcodes or decoding of 
+//     assembly parameters. The name of the opcode (as a string) is given, 
+//     however, to aid debugging.
+//
+// You may ask what this little disassembler actually does, then?  The answer is
+// that it does the following, which is exactly what the patching utility needs:
+//  -# Indicates if opcode is a jump (any kind) or a return (any kind)
+//     because this is important for the patching utility to determine if
+//     a function is too short or there are jumps too early in it for it
+//     to be preamble patched.
+//  -# The opcode length is always calculated, so that the patching utility
+//     can figure out where the next instruction starts, and whether it
+//     already has enough instructions to replace with the absolute jump
+//     to the patching code.
+//
+// The usage is quite simple; just create a MiniDisassembler and use its
+// Disassemble() method.
+//
+// If you would like to extend this disassembler, please refer to the
+// IA-32 Intel® Architecture Software DeveloperÂ’s Manual Volume 2:
+// Instruction Set Reference for information about operand decoding
+// etc.
+class MiniDisassembler {
+ public:
+
+  // Creates a new instance and sets defaults.
+  //
+  // @param operand_default_32_bits If true, the default operand size is
+  // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
+  // @param address_default_32_bits If true, the default address size is
+  // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
+  MiniDisassembler(bool operand_default_32_bits,
+                   bool address_default_32_bits);
+
+  // Equivalent to MiniDisassembler(true, true);
+  MiniDisassembler();
+
+  // Attempts to disassemble a single instruction starting from the
+  // address in memory it is pointed to.
+  //
+  // @param start Address where disassembly should start.
+  // @param instruction_bytes Variable that will be <b>incremented</b> by
+  // the length in bytes of the instruction.
+  // @return enItJump, enItReturn or enItGeneric on success.  enItUnknown
+  // if unable to disassemble, enItUnused if this seems to be an unused
+  // opcode. In the last two (error) cases, cbInstruction will be set
+  // to 0xffffffff.
+  //
+  // @post This instance of the disassembler is ready to be used again,
+  // with unchanged defaults from creation time.
+  InstructionType Disassemble(byte* start, unsigned int& instruction_bytes);
+
+ private:
+
+  // Makes the disassembler ready for reuse.
+  void Initialize();
+
+  // Sets the flags for address and operand sizes.
+  // @return Number of prefix bytes.
+  InstructionType ProcessPrefixes(byte* start, unsigned int& size);
+
+  // Sets the flag for whether we have ModR/M, and increments
+  // operand_bytes_ if any are specifies by the opcode directly.
+  // @return Number of opcode bytes.
+  InstructionType ProcessOpcode(byte* start, 
+                                unsigned int table, 
+                                unsigned int& size);
+
+  // Checks the type of the supplied operand.  Increments
+  // operand_bytes_ if it directly indicates an immediate etc.
+  // operand.  Asserts have_modrm_ if the operand specifies
+  // a ModR/M byte.
+  bool ProcessOperand(int flag_operand);
+
+  // Increments operand_bytes_ by size specified by ModR/M and
+  // by SIB if present.
+  // @return 0 in case of error, 1 if there is just a ModR/M byte,
+  // 2 if there is a ModR/M byte and a SIB byte.
+  bool ProcessModrm(byte* start, unsigned int& size);
+
+  // Processes the SIB byte that it is pointed to.
+  // @param start Pointer to the SIB byte.
+  // @param mod The mod field from the ModR/M byte.
+  // @return 1 to indicate success (indicates 1 SIB byte)
+  bool ProcessSib(byte* start, byte mod, unsigned int& size);
+
+  // The instruction type we have decoded from the opcode.
+  InstructionType instruction_type_;
+
+  // Counts the number of bytes that is occupied by operands in
+  // the current instruction (note: we don't care about how large
+  // operands stored in registers etc. are).
+  unsigned int operand_bytes_;
+
+  // True iff there is a ModR/M byte in this instruction.
+  bool have_modrm_;
+
+  // True iff we need to decode the ModR/M byte (sometimes it just
+  // points to a register, we can tell by the addressing mode).
+  bool should_decode_modrm_;
+
+  // Current operand size is 32 bits if true, 16 bits if false.
+  bool operand_is_32_bits_;
+
+  // Default operand size is 32 bits if true, 16 bits if false.
+  bool operand_default_is_32_bits_;
+
+  // Current address size is 32 bits if true, 16 bits if false.
+  bool address_is_32_bits_;
+
+  // Default address size is 32 bits if true, 16 bits if false.
+  bool address_default_is_32_bits_;
+
+  // Huge big opcode table based on the IA-32 manual, defined
+  // in Ia32OpcodeMap.cpp
+  static const OpcodeTable s_ia32_opcode_map_[];
+
+  // Somewhat smaller table to help with decoding ModR/M bytes
+  // when 16-bit addressing mode is being used.  Defined in
+  // Ia32ModrmMap.cpp
+  static const ModrmEntry s_ia16_modrm_map_[];
+
+  // Somewhat smaller table to help with decoding ModR/M bytes
+  // when 32-bit addressing mode is being used.  Defined in
+  // Ia32ModrmMap.cpp
+  static const ModrmEntry s_ia32_modrm_map_[];
+
+  // Indicators of whether we got certain prefixes that certain
+  // silly Intel instructions depend on in nonstandard ways for
+  // their behaviors.
+  bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_;
+};
+
+};  // namespace sidestep
+
+#endif  // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
diff --git a/src/windows/mini_disassembler_types.h b/src/windows/mini_disassembler_types.h
new file mode 100644
index 0000000..43a6369
--- /dev/null
+++ b/src/windows/mini_disassembler_types.h
@@ -0,0 +1,226 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Several simple types used by the disassembler and some of the patching
+ * mechanisms.
+ */
+
+#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
+#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
+
+namespace sidestep {
+
+// Categories of instructions that we care about
+enum InstructionType {
+  // This opcode is not used
+  IT_UNUSED,
+  // This disassembler does not recognize this opcode (error)
+  IT_UNKNOWN,
+  // This is not an instruction but a reference to another table
+  IT_REFERENCE,
+  // This byte is a prefix byte that we can ignore
+  IT_PREFIX,
+  // This is a prefix byte that switches to the nondefault address size
+  IT_PREFIX_ADDRESS,
+  // This is a prefix byte that switches to the nondefault operand size
+  IT_PREFIX_OPERAND,
+  // A jump or call instruction
+  IT_JUMP,
+  // A return instruction
+  IT_RETURN,
+  // Any other type of instruction (in this case we don't care what it is)
+  IT_GENERIC,
+};
+
+// Lists IA-32 operand sizes in multiples of 8 bits
+enum OperandSize {
+  OS_ZERO = 0,
+  OS_BYTE = 1,
+  OS_WORD = 2,
+  OS_DOUBLE_WORD = 4,
+  OS_QUAD_WORD = 8,
+  OS_DOUBLE_QUAD_WORD = 16,
+  OS_32_BIT_POINTER = 32/8,
+  OS_48_BIT_POINTER = 48/8,
+  OS_SINGLE_PRECISION_FLOATING = 32/8,
+  OS_DOUBLE_PRECISION_FLOATING = 64/8,
+  OS_DOUBLE_EXTENDED_PRECISION_FLOATING = 80/8,
+  OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING = 128/8,
+  OS_PSEUDO_DESCRIPTOR = 6
+};
+
+// Operand addressing methods from the IA-32 manual.  The enAmMask value
+// is a mask for the rest.  The other enumeration values are named for the
+// names given to the addressing methods in the manual, e.g. enAm_D is for
+// the D addressing method.
+// 
+// The reason we use a full 4 bytes and a mask, is that we need to combine
+// these flags with the enOperandType to store the details
+// on the operand in a single integer.
+enum AddressingMethod {
+  AM_NOT_USED = 0,        // This operand is not used for this instruction
+  AM_MASK = 0x00FF0000,  // Mask for the rest of the values in this enumeration
+  AM_A = 0x00010000,    // A addressing type
+  AM_C = 0x00020000,    // C addressing type
+  AM_D = 0x00030000,    // D addressing type
+  AM_E = 0x00040000,    // E addressing type
+  AM_F = 0x00050000,    // F addressing type
+  AM_G = 0x00060000,    // G addressing type
+  AM_I = 0x00070000,    // I addressing type
+  AM_J = 0x00080000,    // J addressing type
+  AM_M = 0x00090000,    // M addressing type
+  AM_O = 0x000A0000,    // O addressing type
+  AM_P = 0x000B0000,    // P addressing type
+  AM_Q = 0x000C0000,    // Q addressing type
+  AM_R = 0x000D0000,    // R addressing type
+  AM_S = 0x000E0000,    // S addressing type
+  AM_T = 0x000F0000,    // T addressing type
+  AM_V = 0x00100000,    // V addressing type
+  AM_W = 0x00110000,    // W addressing type
+  AM_X = 0x00120000,    // X addressing type
+  AM_Y = 0x00130000,    // Y addressing type
+  AM_REGISTER = 0x00140000,  // Specific register is always used as this op
+  AM_IMPLICIT = 0x00150000,  // An implicit, fixed value is used
+};
+
+// Operand types from the IA-32 manual. The enOtMask value is
+// a mask for the rest. The rest of the values are named for the
+// names given to these operand types in the manual, e.g. enOt_ps
+// is for the ps operand type in the manual.
+//
+// The reason we use a full 4 bytes and a mask, is that we need
+// to combine these flags with the enAddressingMethod to store the details
+// on the operand in a single integer.
+enum OperandType {
+  OT_MASK = 0xFF000000,
+  OT_A = 0x01000000,
+  OT_B = 0x02000000,
+  OT_C = 0x03000000,
+  OT_D = 0x04000000,
+  OT_DQ = 0x05000000,
+  OT_P = 0x06000000,
+  OT_PI = 0x07000000,
+  OT_PS = 0x08000000,  // actually unsupported for (we don't know its size)
+  OT_Q = 0x09000000,
+  OT_S = 0x0A000000,
+  OT_SS = 0x0B000000,
+  OT_SI = 0x0C000000,
+  OT_V = 0x0D000000,
+  OT_W = 0x0E000000,
+  OT_SD = 0x0F000000,  // scalar double-precision floating-point value
+  OT_PD = 0x10000000,  // double-precision floating point
+  // dummy "operand type" for address mode M - which doesn't specify 
+  // operand type
+  OT_ADDRESS_MODE_M = 0x80000000
+};
+
+// Everything that's in an Opcode (see below) except the three
+// alternative opcode structs for different prefixes.
+struct SpecificOpcode {
+  // Index to continuation table, or 0 if this is the last
+  // byte in the opcode.
+  int table_index_;    
+
+  // The opcode type
+  InstructionType type_;
+
+  // Description of the type of the dest, src and aux operands,
+  // put together from an enOperandType flag and an enAddressingMethod
+  // flag.
+  int flag_dest_;
+  int flag_source_;
+  int flag_aux_;
+
+  // We indicate the mnemonic for debugging purposes
+  const char* mnemonic_;
+};
+
+// The information we keep in our tables about each of the different
+// valid instructions recognized by the IA-32 architecture.
+struct Opcode {
+  // Index to continuation table, or 0 if this is the last
+  // byte in the opcode.
+  int table_index_;    
+
+  // The opcode type
+  InstructionType type_;
+
+  // Description of the type of the dest, src and aux operands,
+  // put together from an enOperandType flag and an enAddressingMethod
+  // flag.
+  int flag_dest_;
+  int flag_source_;
+  int flag_aux_;
+
+  // We indicate the mnemonic for debugging purposes
+  const char* mnemonic_;
+
+  // Alternative opcode info if certain prefixes are specified.
+  // In most cases, all of these are zeroed-out.  Only used if
+  // bPrefixDependent is true.
+  bool is_prefix_dependent_;
+  SpecificOpcode opcode_if_f2_prefix_;
+  SpecificOpcode opcode_if_f3_prefix_;
+  SpecificOpcode opcode_if_66_prefix_;
+};
+
+// Information about each table entry.
+struct OpcodeTable {
+  // Table of instruction entries
+  const Opcode* table_;
+  // How many bytes left to shift ModR/M byte <b>before</b> applying mask
+  unsigned char shift_;
+  // Mask to apply to byte being looked at before comparing to table
+  unsigned char mask_;
+  // Minimum/maximum indexes in table.
+  unsigned char min_lim_;
+  unsigned char max_lim_;
+};
+
+// Information about each entry in table used to decode ModR/M byte.
+struct ModrmEntry {
+  // Is the operand encoded as bytes in the instruction (rather than
+  // if it's e.g. a register in which case it's just encoded in the
+  // ModR/M byte)
+  bool is_encoded_in_instruction_;
+
+  // Is there a SIB byte?  In this case we always need to decode it.
+  bool use_sib_byte_;
+
+  // What is the size of the operand (only important if it's encoded
+  // in the instruction)?
+  OperandSize operand_size_;
+};
+
+};  // namespace sidestep
+
+#endif  // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
diff --git a/src/windows/patch_functions.cc b/src/windows/patch_functions.cc
new file mode 100644
index 0000000..a5cadd1
--- /dev/null
+++ b/src/windows/patch_functions.cc
@@ -0,0 +1,254 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WIN32
+# error You should only be including windows/patch_functions.cc in a windows environment!
+#endif
+
+#include "config.h"
+#include <windows.h>
+#include <tlhelp32.h>     // for CreateToolhelp32Snapshot()
+#include <base/logging.h>
+#include "google/malloc_hook.h"
+#include "preamble_patcher.h"
+
+// These functions are how we override the memory allocation functions,
+// just like tcmalloc.cc and malloc_hook.cc do.
+
+// These are defined in tcmalloc.cc (with a bit of macro hackiness).
+// We declare them here so we can replace the windows version with ours.
+extern "C" void* Perftools_malloc(size_t size) __THROW;
+extern "C" void Perftools_free(void* ptr) __THROW;
+extern "C" void* Perftools_realloc(void* ptr, size_t size) __THROW;
+extern "C" void* Perftools_calloc(size_t nmemb, size_t size) __THROW;
+
+typedef void* (*Type_malloc)(size_t size) __THROW;
+typedef void (*Type_free)(void* ptr) __THROW;
+typedef void* (*Type_realloc)(void* ptr, size_t size) __THROW;
+typedef  void* (*Type_calloc)(size_t nmemb, size_t size) __THROW;
+
+// A Windows-API equivalent of malloc and free
+typedef LPVOID (WINAPI *Type_HeapAlloc)(HANDLE hHeap, DWORD dwFlags,
+                                        DWORD_PTR dwBytes);
+typedef BOOL (WINAPI *Type_HeapFree)(HANDLE hHeap, DWORD dwFlags,
+                                     LPVOID lpMem);
+// A Windows-API equivalent of mmap and munmap, for "anonymous regions"
+typedef LPVOID (WINAPI *Type_VirtualAllocEx)(HANDLE process, LPVOID address,
+                                             SIZE_T size, DWORD type,
+                                             DWORD protect);
+typedef BOOL (WINAPI *Type_VirtualFreeEx)(HANDLE process, LPVOID address,
+                                          SIZE_T size, DWORD type);
+// A Windows-API equivalent of mmap and munmap, for actual files
+typedef LPVOID (WINAPI *Type_MapViewOfFileEx)(HANDLE hFileMappingObject,
+                                              DWORD dwDesiredAccess,
+                                              DWORD dwFileOffsetHigh,
+                                              DWORD dwFileOffsetLow,
+                                              SIZE_T dwNumberOfBytesToMap,
+                                              LPVOID lpBaseAddress);
+typedef BOOL (WINAPI *Type_UnmapViewOfFile)(LPCVOID lpBaseAddress);
+
+// all libc memory-alloaction routines go through one of these.
+static Type_malloc Windows_malloc;
+static Type_calloc Windows_calloc;
+static Type_realloc Windows_realloc;
+static Type_free Windows_free;
+
+// All Windows memory-allocation routines call through to one of these.
+static Type_HeapAlloc Windows_HeapAlloc;
+static Type_HeapFree Windows_HeapFree;
+static Type_VirtualAllocEx Windows_VirtualAllocEx;
+static Type_VirtualFreeEx Windows_VirtualFreeEx;
+static Type_MapViewOfFileEx Windows_MapViewOfFileEx;
+static Type_UnmapViewOfFile Windows_UnmapViewOfFile;
+
+static LPVOID WINAPI Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
+                                         DWORD_PTR dwBytes) {
+  LPVOID result = Windows_HeapAlloc(hHeap, dwFlags, dwBytes);
+  MallocHook::InvokeNewHook(result, dwBytes);
+  return result;
+}
+
+static BOOL WINAPI Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
+                                      LPVOID lpMem) {
+  MallocHook::InvokeDeleteHook(lpMem);
+  return Windows_HeapFree(hHeap, dwFlags, lpMem);
+}
+
+static LPVOID WINAPI Perftools_VirtualAllocEx(HANDLE process, LPVOID address,
+                                              SIZE_T size, DWORD type,
+                                              DWORD protect) {
+  LPVOID result = Windows_VirtualAllocEx(process, address, size, type, protect);
+  // VirtualAllocEx() seems to be the Windows equivalent of mmap()
+  MallocHook::InvokeMmapHook(result, address, size, protect, type, -1, 0);
+  return result;
+}
+
+static BOOL WINAPI Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
+                                           SIZE_T size, DWORD type) {
+  MallocHook::InvokeMunmapHook(address, size);
+  return Windows_VirtualFreeEx(process, address, size, type);
+}
+
+static LPVOID WINAPI Perftools_MapViewOfFileEx(HANDLE hFileMappingObject,
+                                               DWORD dwDesiredAccess,
+                                               DWORD dwFileOffsetHigh,
+                                               DWORD dwFileOffsetLow,
+                                               SIZE_T dwNumberOfBytesToMap,
+                                               LPVOID lpBaseAddress) {
+  // For this function pair, you always deallocate the full block of
+  // data that you allocate, so NewHook/DeleteHook is the right API.
+  LPVOID result = Windows_MapViewOfFileEx(hFileMappingObject, dwDesiredAccess,
+                                          dwFileOffsetHigh, dwFileOffsetLow,
+                                          dwNumberOfBytesToMap, lpBaseAddress);
+  MallocHook::InvokeNewHook(result, dwNumberOfBytesToMap);
+  return result;
+}
+
+static BOOL WINAPI Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress) {
+  MallocHook::InvokeDeleteHook(lpBaseAddress);
+  return Windows_UnmapViewOfFile(lpBaseAddress);
+}
+
+// ---------------------------------------------------------------------
+
+#define PATCH_KERNEL32(name)  do {                      \
+  CHECK_EQ(sidestep::SIDESTEP_SUCCESS,                  \
+           sidestep::PreamblePatcher::Patch(            \
+               "kernel32", #name,                       \
+               &Perftools_##name, &Windows_##name));    \
+} while (0)
+
+#define UNPATCH(name)  do {                                             \
+  CHECK_EQ(sidestep::SIDESTEP_SUCCESS,                                  \
+           sidestep::PreamblePatcher::Unpatch(                          \
+               (Type_##name)&name, &Perftools_##name, Windows_##name)); \
+} while (0)
+
+void PatchWindowsFunctions() {
+  // Luckily, Patch() doesn't call malloc or windows alloc routines
+  // itself -- though it does call new (we can use PatchWithStub to
+  // get around that, and will need to if we need to patch new).
+
+  // TODO(csilvers): should we be patching GlobalAlloc/LocalAlloc instead,
+  //                 for pre-XP systems?
+  PATCH_KERNEL32(HeapAlloc);
+  PATCH_KERNEL32(HeapFree);
+  PATCH_KERNEL32(VirtualAllocEx);
+  PATCH_KERNEL32(VirtualFreeEx);
+  PATCH_KERNEL32(MapViewOfFileEx);
+  PATCH_KERNEL32(UnmapViewOfFile);
+
+  // Now we need to override malloc, calloc, realloc, and free.  Note
+  // that other memory-allocation routines (including new/delete) are
+  // overridden in tcmalloc.cc.  These are overridden here because
+  // they're special for windows: they're the only libc memory
+  // routines that are defined by the Microsoft C runtime library
+  // (CRT) that we can't just override.  We have two different ways of
+  // patching them: if malloc/etc are defined in a DLL, we just use
+  // the DLL/function name, like above.  If not (we're statically
+  // linked) we can get away with just passing in &malloc directly.
+  // Take a snapshot of all modules in the specified process.
+  HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE |
+                                                TH32CS_SNAPMODULE32,
+                                                GetCurrentProcessId());
+  if (hModuleSnap != INVALID_HANDLE_VALUE) {
+    MODULEENTRY32 me32;
+    me32.dwSize = sizeof(me32);   // needed by windows, apparently
+    if (Module32First(hModuleSnap, &me32)) {
+      do {
+        LPCSTR lib = me32.szModule;
+        if (sidestep::SIDESTEP_SUCCESS ==
+            sidestep::PreamblePatcher::Patch(
+                lib, "malloc", &Perftools_malloc, &Windows_malloc)
+            &&
+            sidestep::SIDESTEP_SUCCESS ==
+            sidestep::PreamblePatcher::Patch(
+                lib, "calloc", &Perftools_calloc, &Windows_calloc)
+            &&
+            sidestep::SIDESTEP_SUCCESS ==
+            sidestep::PreamblePatcher::Patch(
+                lib, "realloc", &Perftools_realloc, &Windows_realloc)
+            &&
+            sidestep::SIDESTEP_SUCCESS ==
+            sidestep::PreamblePatcher::Patch(
+                lib, "free", &Perftools_free, &Windows_free)
+            ) {
+          break;
+        } else {
+          Windows_malloc = NULL;   // reset to indicate failure
+          Windows_calloc = NULL;
+          Windows_realloc = NULL;
+          Windows_free = NULL;
+        }
+      } while (Module32Next(hModuleSnap, &me32));
+    }
+    CloseHandle(hModuleSnap);
+  }
+  if (Windows_malloc == NULL && Windows_calloc == NULL &&
+      Windows_realloc == NULL && Windows_free == NULL) {
+    // probably means we're statically linked
+    // NOTE: we need to cast the windows calls, because we're not quite
+    // sure of their type (in particular, some versions have __THROW, some
+    // don't).  We don't care to that level of detail, hence the cast.
+    CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
+             sidestep::PreamblePatcher::Patch(
+                 (Type_malloc)&malloc, &Perftools_malloc, &Windows_malloc));
+    CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
+             sidestep::PreamblePatcher::Patch(
+                 (Type_calloc)&calloc, &Perftools_calloc, &Windows_calloc));
+    CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
+             sidestep::PreamblePatcher::Patch(
+                 (Type_realloc)&realloc, &Perftools_realloc, &Windows_realloc));
+    CHECK_EQ(sidestep::SIDESTEP_SUCCESS,
+             sidestep::PreamblePatcher::Patch(
+                 (Type_free)&free, &Perftools_free, &Windows_free));
+  }
+}
+
+void UnpatchWindowsFunctions() {
+  // We need to go back to the system malloc/etc at global destruct time,
+  // so objects that were constructed before tcmalloc, using the system
+  // malloc, can destroy themselves using the system free.  This depends
+  // on DLLs unloading in the reverse order in which they load!
+  //
+  // We also go back to the default HeapAlloc/etc, just for consistency.
+  // Who knows, it may help avoid weird bugs in some situations.
+  UNPATCH(HeapAlloc);
+  UNPATCH(HeapFree);
+  UNPATCH(VirtualAllocEx);
+  UNPATCH(VirtualFreeEx);
+  UNPATCH(MapViewOfFileEx);
+  UNPATCH(UnmapViewOfFile);
+
+  UNPATCH(malloc);
+  UNPATCH(calloc);
+  UNPATCH(realloc);
+  UNPATCH(free);
+}
diff --git a/src/windows/port.cc b/src/windows/port.cc
index 40552d0..1e5b586 100644
--- a/src/windows/port.cc
+++ b/src/windows/port.cc
@@ -40,12 +40,14 @@
 #include <assert.h>
 #include <stdarg.h>    // for va_list, va_start, va_end
 #include <windows.h>
-#include <TlHelp32.h>  // for CreateToolhelp32Snapshot
 #include <dbghelp.h>   // Provided with Microsoft Debugging Tools for Windows
 #include "port.h"
 #include "base/logging.h"
 #include "system-alloc.h"
 
+// -----------------------------------------------------------------------
+// Basic libraries
+
 // These call the windows _vsnprintf, but always NUL-terminate.
 int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
   if (size == 0)        // not even room for a \0?
@@ -77,47 +79,8 @@
   return NULL;
 }
 
-// These two functions replace system-alloc.cc
-
-static SpinLock alloc_lock(SpinLock::LINKER_INITIALIZED);
-
-// This is mostly like MmapSysAllocator::Alloc, except it does these weird
-// munmap's in the middle of the page, which is forbidden in windows.
-extern void* TCMalloc_SystemAlloc(size_t size, size_t alignment) {
-  SpinLockHolder sh(&alloc_lock);
-  // Align on the pagesize boundary
-  const int pagesize = getpagesize();
-  if (alignment < pagesize) alignment = pagesize;
-  size = ((size + alignment - 1) / alignment) * alignment;
-
-  // Ask for extra memory if alignment > pagesize
-  size_t extra = 0;
-  if (alignment > pagesize) {
-    extra = alignment - pagesize;
-  }
-
-  void* result = VirtualAlloc(0, size, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
-  if (result == NULL)
-    return NULL;
-
-  // Adjust the return memory so it is aligned
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
-  size_t adjust = 0;
-  if ((ptr & (alignment - 1)) != 0) {
-    adjust = alignment - (ptr & (alignment - 1));
-  }
-
-  ptr += adjust;
-  return reinterpret_cast<void*>(ptr);
-}
-
-void TCMalloc_SystemRelease(void* start, size_t length) {
-  // TODO(csilvers): should I be calling VirtualFree here?
-}
-
-bool RegisterSystemAllocator(SysAllocator *allocator, int priority) {
-  return false;   // we don't allow registration on windows, right now
-}
+// -----------------------------------------------------------------------
+// Threads code
 
 bool CheckIfKernelSupportsTLS() {
   // TODO(csilvers): return true (all win's since win95, at least, support this)
@@ -247,6 +210,61 @@
 }
 
 
+// -----------------------------------------------------------------------
+// These functions replace system-alloc.cc
+
+static SpinLock alloc_lock(SpinLock::LINKER_INITIALIZED);
+
+// This is mostly like MmapSysAllocator::Alloc, except it does these weird
+// munmap's in the middle of the page, which is forbidden in windows.
+extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
+                                  size_t alignment) {
+  // Safest is to make actual_size same as input-size.
+  if (actual_size) {
+    *actual_size = size;
+  }
+
+  SpinLockHolder sh(&alloc_lock);
+  // Align on the pagesize boundary
+  const int pagesize = getpagesize();
+  if (alignment < pagesize) alignment = pagesize;
+  size = ((size + alignment - 1) / alignment) * alignment;
+
+  // Ask for extra memory if alignment > pagesize
+  size_t extra = 0;
+  if (alignment > pagesize) {
+    extra = alignment - pagesize;
+  }
+
+  void* result = VirtualAlloc(0, size + extra,
+                              MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+  if (result == NULL)
+    return NULL;
+
+  // Adjust the return memory so it is aligned
+  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
+  size_t adjust = 0;
+  if ((ptr & (alignment - 1)) != 0) {
+    adjust = alignment - (ptr & (alignment - 1));
+  }
+
+  ptr += adjust;
+  return reinterpret_cast<void*>(ptr);
+}
+
+void TCMalloc_SystemRelease(void* start, size_t length) {
+  // TODO(csilvers): should I be calling VirtualFree here?
+}
+
+bool RegisterSystemAllocator(SysAllocator *allocator, int priority) {
+  return false;   // we don't allow registration on windows, right now
+}
+
+
+// -----------------------------------------------------------------------
+// These functions rework existing functions of the same name in the
+// Google codebase.
+
 // A replacement for HeapProfiler::CleanupOldProfiles.
 void DeleteMatchingFiles(const char* prefix, const char* full_glob) {
   WIN32_FIND_DATAA found;  // that final A is for Ansi (as opposed to Unicode)
@@ -266,67 +284,8 @@
   }
 }
 
-// Returns the number of bytes actually written, or <0 or >= size on error.
-static int PrintOneProcLine(char buf[], int size, const MODULEENTRY32& module) {
-  // Format is start-end flags offset devmajor:devminor inode  name
-  // Notes:
-  // 1) Normally it would be unsafe to use %p, since printf might
-  //    malloc() if the pointer is NULL, but that can't happen here.
-  // 2) These pages can mix text sections and data sections, each
-  //    of which should get a different permission.  We choose "r-xp"
-  //    (text) because that's most conservative for heap-checker, but
-  //    we maybe should actually figure it out and do it right.
-  return snprintf(buf, size,
-                  "%p-%p r-xp 00000000 00:00 0   %s\n",
-                  module.modBaseAddr,
-                  module.modBaseAddr + module.modBaseSize,
-                  module.szExePath);
-}
-
-int FillProcSelfMaps(char buf[], int size) {
-  HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE |
-                                             TH32CS_SNAPMODULE32,
-                                             GetCurrentProcessId());
-
-  MODULEENTRY32 module;
-  memset(&module, 0, sizeof(module));
-  module.dwSize = sizeof(module);
-
-  char* bufend = buf;
-  if (Module32First(snapshot, &module)) {
-    do {
-      const int len = PrintOneProcLine(bufend, size, module);
-      if (len <= 0 || len >= sizeof(buf))
-        break;       // last fully-successful write
-      bufend += len;
-      size -= len;
-    } while (Module32Next(snapshot, &module));
-  }
-
-  CloseHandle(snapshot);
-  return bufend - buf;
-}
-
-void DumpProcSelfMaps(int fd) {
-  HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE |
-                                             TH32CS_SNAPMODULE32,
-                                             GetCurrentProcessId());
-
-  MODULEENTRY32 module;
-  memset(&module, 0, sizeof(module));
-  module.dwSize = sizeof(module);
-
-  if (Module32First(snapshot, &module)) {
-    do {
-      char buf[PATH_MAX + 80];
-      const int len = PrintOneProcLine(buf, sizeof(buf), module);
-      if (len > 0 && len < sizeof(buf))
-        write(fd, buf, len);
-    } while (Module32Next(snapshot, &module));
-  }
-
-  CloseHandle(snapshot);
-}
+// -----------------------------------------------------------------------
+// Stacktrace functionality
 
 static SpinLock get_stack_trace_lock(SpinLock::LINKER_INITIALIZED);
 
diff --git a/src/windows/port.h b/src/windows/port.h
index a553361..f5c6e53 100644
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -223,6 +223,21 @@
 // But maybe play around with ExperimentalGetStackTrace in port.cc
 #define NO_TCMALLOC_SAMPLES
 
+// tcmalloc.cc calls this so we can patch VirtualAlloc() et al.
+// TODO(csilvers): instead of patching the functions, consider just replacing
+// them.  To do this, add the following post-build step the the .vcproj:
+// <Tool Name="VCPostBuildEventTool"
+//       CommandLine="lib /out:$(OutDir)\tmp.lib /remove:build\intel\xst_obj\dbgheap.obj libcd.lib
+//       lib /out:$(OutDir)\foo.lib $(OutDir)\libem.lib $(OutDir)\tmp.lib
+// "/>
+// libem.lib is a library you write that defines calloc, free, malloc,
+// realloc, _calloc_dbg, _free_dbg, _msize_dbg, _malloc_dbg,
+// _realloc_dbg, _CrtDumpMemoryLeaks, and _CrtSetDbgFlag (at least for
+// VC++ 7.1).  The list of functions to override, and the name/location of
+// the files to remove, may differ between VC++ versions.
+
+extern PERFTOOLS_DLL_DECL void PatchWindowsFunctions();
+extern PERFTOOLS_DLL_DECL void UnpatchWindowsFunctions();
 
 #endif  /* WIN32 */
 
diff --git a/src/windows/preamble_patcher.cc b/src/windows/preamble_patcher.cc
new file mode 100644
index 0000000..6a56132
--- /dev/null
+++ b/src/windows/preamble_patcher.cc
@@ -0,0 +1,247 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Implementation of PreamblePatcher
+ */
+
+#include "preamble_patcher.h"
+
+#include "mini_disassembler.h"
+
+// compatibility shims
+#include "base/logging.h"
+
+// Definitions of assembly statements we need
+#define ASM_JMP32REL 0xE9
+#define ASM_INT3 0xCC
+
+namespace sidestep {
+
+SideStepError PreamblePatcher::RawPatchWithStubAndProtections(
+    void* target_function, void *replacement_function,
+    unsigned char* preamble_stub, unsigned long stub_size,
+    unsigned long* bytes_needed) {
+  // We need to be able to write to a process-local copy of the first
+  // MAX_PREAMBLE_STUB_SIZE bytes of target_function
+  DWORD old_target_function_protect = 0;
+  BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function), 
+                                    MAX_PREAMBLE_STUB_SIZE, PAGE_READWRITE, 
+                                    &old_target_function_protect);
+  if (!succeeded) {
+    ASSERT(false, "Failed to make page containing target function "
+                   "copy-on-write.");
+    return SIDESTEP_ACCESS_DENIED;
+  }
+
+  SideStepError error_code = RawPatchWithStub(target_function, 
+                                              replacement_function, 
+                                              preamble_stub, 
+                                              stub_size,
+                                              bytes_needed);
+  if (SIDESTEP_SUCCESS != error_code) {
+    ASSERT1(false);
+    return error_code;
+  }
+
+  // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of
+  // pTargetFunction to what they were before we started goofing around.
+  succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function), 
+                               MAX_PREAMBLE_STUB_SIZE, 
+                               old_target_function_protect, 
+                               &old_target_function_protect);
+  if (!succeeded) {
+    ASSERT(false, "Failed to restore protection to target function.");
+    // We must not return an error here because the function has actually
+    // been patched, and returning an error would likely cause our client
+    // code not to unpatch it.  So we just keep going.
+  }
+
+  // Flush the instruction cache to make sure the processor doesn't execute the
+  // old version of the instructions (before our patch).
+  //
+  // FlushInstructionCache is actually a no-op at least on single-processor
+  // XP machines.  I'm not sure why this is so, but it is, yet I want to keep the
+  // call to the API here for correctness in case there is a difference in
+  // some variants of Windows/hardware.
+  succeeded = ::FlushInstructionCache(::GetCurrentProcess(), 
+                                      target_function, 
+                                      MAX_PREAMBLE_STUB_SIZE);
+  if (!succeeded) {
+    ASSERT(false, "Failed to flush instruction cache.");
+    // We must not return an error here because the function has actually
+    // been patched, and returning an error would likely cause our client
+    // code not to unpatch it.  So we just keep going.
+  }
+
+  return SIDESTEP_SUCCESS;
+}
+
+SideStepError PreamblePatcher::RawPatch(void* target_function,
+                                        void* replacement_function,
+                                        void** original_function_stub) {
+  if (!target_function || !replacement_function || !original_function_stub ||
+      (*original_function_stub) || target_function == replacement_function) {
+    ASSERT(false, "Preconditions not met");
+    return SIDESTEP_INVALID_PARAMETER;
+  }
+
+  // @see MAX_PREAMBLE_STUB_SIZE for an explanation of how we arrives at 
+  // this size
+  byte* preamble_stub = new unsigned char[MAX_PREAMBLE_STUB_SIZE];
+  if (!preamble_stub) {
+    ASSERT(false, "Unable to allocate preamble-stub.");
+    return SIDESTEP_INSUFFICIENT_BUFFER;
+  }
+
+  // Change the protection of the newly allocated preamble stub to
+  // PAGE_EXECUTE_READWRITE. This is required to work with DEP (Data
+  // Execution Prevention) which will cause an exception if code is executed
+  // from a page on which you do not have read access.
+  DWORD old_stub_protect = 0;
+  BOOL succeeded = VirtualProtect(preamble_stub, MAX_PREAMBLE_STUB_SIZE,
+                             PAGE_EXECUTE_READWRITE, &old_stub_protect);
+  if (!succeeded) {
+    ASSERT(false, "Failed to make page preamble stub read-write-execute.");
+    delete[] preamble_stub;
+    return SIDESTEP_ACCESS_DENIED;
+  }
+
+  SideStepError error_code = RawPatchWithStubAndProtections(target_function, 
+                                              replacement_function, 
+                                              preamble_stub, 
+                                              MAX_PREAMBLE_STUB_SIZE,
+                                              NULL);
+  if (SIDESTEP_SUCCESS != error_code) {
+    ASSERT1(false);
+    delete[] preamble_stub;
+    return error_code;
+  }
+
+  RAW_VLOG(1, "PreamblePatcher::RawPatch successfully patched 0x%x",
+           target_function);
+                
+  *original_function_stub = reinterpret_cast<void*>(preamble_stub);
+  return SIDESTEP_SUCCESS;
+}
+
+SideStepError PreamblePatcher::Unpatch(void* target_function,
+                                       void* replacement_function,
+                                       void* original_function_stub) {
+  ASSERT1(target_function && original_function_stub);
+  if (!target_function || !original_function_stub) {
+    return SIDESTEP_INVALID_PARAMETER;
+  }
+
+  // We disassemble the preamble of the _stub_ to see how many bytes we
+  // originally copied to the stub.
+  MiniDisassembler disassembler;
+  unsigned int preamble_bytes = 0;
+  while (preamble_bytes < 5) {
+    InstructionType instruction_type = 
+      disassembler.Disassemble(
+        reinterpret_cast<byte*>(original_function_stub) + preamble_bytes,
+        preamble_bytes);
+    if (IT_GENERIC != instruction_type) {
+      ASSERT(false, "Should only have generic instructions in stub!!");
+      return SIDESTEP_UNSUPPORTED_INSTRUCTION;
+    }
+  }
+
+  // Before unpatching, target_function should be a JMP to
+  // replacement_function.  If it's not, then either it's an error, or
+  // we're falling into the case where the original instruction was a
+  // JMP, and we patched the jumped_to address rather than the JMP
+  // itself.  (For instance, if malloc() is just a JMP to __malloc(),
+  // we patched __malloc() and not malloc().)
+  unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
+  while (1) {    // we stop when target is a JMP to replacement_function
+    if (target[0] != ASM_JMP32REL) {
+      ASSERT(false, "target_function does not look like it was patched.");
+      return SIDESTEP_INVALID_PARAMETER;
+    }
+    int relative_offset;   // Windows guarantees int is 4 bytes
+    ASSERT1(sizeof(relative_offset) == 4);
+    memcpy(reinterpret_cast<void*>(&relative_offset),
+           reinterpret_cast<void*>(target + 1), 4);
+    unsigned char* jump_to = target + 5 + relative_offset;
+    if (jump_to == replacement_function)
+      break;
+    target = jump_to;      // follow the jmp
+  }
+
+  // We need to be able to write to a process-local copy of the first
+  // MAX_PREAMBLE_STUB_SIZE bytes of target_function
+  DWORD old_target_function_protect = 0;
+  BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target), 
+                                    MAX_PREAMBLE_STUB_SIZE, PAGE_READWRITE, 
+                                    &old_target_function_protect);
+  if (!succeeded) {
+    ASSERT(false, "Failed to make page containing target function "
+                   "copy-on-write.");
+    return SIDESTEP_ACCESS_DENIED;
+  }
+
+  // Replace the first few bytes of the original function with the bytes we
+  // previously moved to the preamble stub.
+  memcpy(reinterpret_cast<void*>(target),
+         original_function_stub, preamble_bytes);
+
+  // Stub is now useless so delete it.
+  // [csilvers: Commented out for perftools because it causes big problems
+  //  when we're unpatching malloc.  We just let this live on as a leak.]
+  //delete original_function_stub;
+
+  // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of
+  // target to what they were before we started goofing around.
+  succeeded = ::VirtualProtect(reinterpret_cast<void*>(target), 
+                               MAX_PREAMBLE_STUB_SIZE, 
+                               old_target_function_protect, 
+                               &old_target_function_protect);
+
+  // Flush the instruction cache to make sure the processor doesn't execute the
+  // old version of the instructions (before our patch).
+  //
+  // See comment on FlushInstructionCache elsewhere in this file.
+  succeeded = ::FlushInstructionCache(::GetCurrentProcess(), 
+                                      target, 
+                                      MAX_PREAMBLE_STUB_SIZE);
+  if (!succeeded) {
+    ASSERT(false, "Failed to flush instruction cache.");
+    return SIDESTEP_UNEXPECTED;
+  }
+
+  RAW_VLOG(1, "PreamblePatcher::Unpatch successfully unpatched 0x%x",
+           target_function);
+  return SIDESTEP_SUCCESS;
+}
+
+};  // namespace sidestep
diff --git a/src/windows/preamble_patcher.h b/src/windows/preamble_patcher.h
new file mode 100644
index 0000000..9d5040e
--- /dev/null
+++ b/src/windows/preamble_patcher.h
@@ -0,0 +1,311 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Definition of PreamblePatcher
+ */
+
+#ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H__
+#define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H__
+
+#include <windows.h>
+
+// compatibility shim
+#include "base/logging.h"
+#define ASSERT(cond, msg)  RAW_DCHECK(cond, msg)
+#define ASSERT1(cond)      RAW_DCHECK(cond, #cond)
+
+// Maximum size of the preamble stub. We overwrite at least the first 5
+// bytes of the function. Considering the worst case scenario, we need 4
+// bytes + the max instruction size + 5 more bytes for our jump back to
+// the original code. With that in mind, 32 is a good number :)
+#define MAX_PREAMBLE_STUB_SIZE    (32)     
+
+namespace sidestep {
+
+// Possible results of patching/unpatching
+enum SideStepError {
+  SIDESTEP_SUCCESS = 0,
+  SIDESTEP_INVALID_PARAMETER,
+  SIDESTEP_INSUFFICIENT_BUFFER,
+  SIDESTEP_JUMP_INSTRUCTION,
+  SIDESTEP_FUNCTION_TOO_SMALL,
+  SIDESTEP_UNSUPPORTED_INSTRUCTION,
+  SIDESTEP_NO_SUCH_MODULE,
+  SIDESTEP_NO_SUCH_FUNCTION,
+  SIDESTEP_ACCESS_DENIED,
+  SIDESTEP_UNEXPECTED,
+};
+
+// Implements a patching mechanism that overwrites the first few bytes of
+// a function preamble with a jump to our hook function, which is then
+// able to call the original function via a specially-made preamble-stub
+// that imitates the action of the original preamble.
+//
+// NOTE:  This patching mechanism should currently only be used for
+// non-production code, e.g. unit tests, because it is not threadsafe.
+// See the TODO in preamble_patcher_with_stub.cpp for instructions on what
+// we need to do before using it in production code; it's fairly simple
+// but unnecessary for now since we only intend to use it in unit tests.
+// 
+// To patch a function, use either of the typesafe Patch() methods.  You
+// can unpatch a function using Unpatch().
+// 
+// Typical usage goes something like this:
+// @code
+// typedef int (*MyTypesafeFuncPtr)(int x);
+// MyTypesafeFuncPtr original_func_stub;
+// int MyTypesafeFunc(int x) { return x + 1; }
+// int HookMyTypesafeFunc(int x) { return 1 + original_func_stub(x); }
+// 
+// void MyPatchInitializingFunction() {
+//   original_func_stub = PreamblePatcher::Patch(
+//              MyTypesafeFunc, HookMyTypesafeFunc);
+//   if (!original_func_stub) {
+//     // ... error handling ...
+//   }
+// 
+//   // ... continue - you have patched the function successfully ...
+// }
+// @endcode
+// 
+// Note that there are a number of ways that this method of patching can
+// fail.  The most common are:
+//    - If there is a jump (jxx) instruction in the first 5 bytes of
+//    the function being patched, we cannot patch it because in the
+//    current implementation we do not know how to rewrite relative
+//    jumps after relocating them to the preamble-stub.  Note that
+//    if you really really need to patch a function like this, it
+//    would be possible to add this functionality (but at some cost).
+//    - If there is a return (ret) instruction in the first 5 bytes
+//    we cannot patch the function because it may not be long enough
+//    for the jmp instruction we use to inject our patch.
+//    - If there is another thread currently executing within the bytes
+//    that are copied to the preamble stub, it will crash in an undefined
+//    way.
+// 
+// If you get any other error than the above, you're either pointing the
+// patcher at an invalid instruction (e.g. into the middle of a multi-
+// byte instruction, or not at memory containing executable instructions)
+// or, there may be a bug in the disassembler we use to find
+// instruction boundaries.
+//
+// NOTE:  In optimized builds, when you have very trivial functions that
+// the compiler can reason do not have side effects, the compiler may
+// reuse the result of calling the function with a given parameter, which
+// may mean if you patch the function in between your patch will never get
+// invoked.  See preamble_patcher_unittest.cpp for an example.
+class PreamblePatcher {
+ public:
+
+  // This is a typesafe version of RawPatch(), identical in all other
+  // ways than it takes a template parameter indicating the type of the
+  // function being patched.
+  //
+  // @param T The type of the function you are patching. Usually
+  // you will establish this type using a typedef, as in the following
+  // example:
+  // @code
+  // typedef BOOL (WINAPI *MessageBoxPtr)(HWND, LPCTSTR, LPCTSTR, UINT);
+  // MessageBoxPtr original = NULL;
+  // PreamblePatcher::Patch(MessageBox, Hook_MessageBox, &original);
+  // @endcode
+  template <class T>
+  static SideStepError Patch(T target_function,
+                               T replacement_function,
+                               T* original_function_stub) {
+    return RawPatch(reinterpret_cast<void*>(target_function),
+                    reinterpret_cast<void*>(replacement_function),
+                    reinterpret_cast<void**>(original_function_stub));
+  }
+
+  // Patches a named function imported from the named module using
+  // preamble patching.  Uses RawPatch() to do the actual patching
+  // work.
+  //
+  // @param T The type of the function you are patching.  Must
+  // exactly match the function you specify using module_name and
+  // function_name.
+  //
+  // @param module_name The name of the module from which the function
+  // is being imported.  Note that the patch will fail if this module
+  // has not already been loaded into the current process.
+  //
+  // @param function_name The name of the function you wish to patch.
+  //
+  // @param replacement_function Your replacement function which
+  // will be called whenever code tries to call the original function.
+  //
+  // @param original_function_stub Pointer to memory that should receive a
+  // pointer that can be used (e.g. in the replacement function) to call the
+  // original function, or NULL to indicate failure.
+  //
+  // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
+  // indicates success.
+  template <class T>
+  static SideStepError Patch(LPCTSTR module_name,
+                               LPCSTR function_name,
+                               T replacement_function,
+                               T* original_function_stub) {
+    ASSERT1(module_name && function_name);
+    if (!module_name || !function_name) {
+      ASSERT(false,
+             "You must specify a module name and function name.");
+      return SIDESTEP_INVALID_PARAMETER;
+    }
+    HMODULE module = ::GetModuleHandle(module_name);
+    ASSERT1(module != NULL);
+    if (!module) {
+      ASSERT(false, "Invalid module name.");
+      return SIDESTEP_NO_SUCH_MODULE;
+    }
+    FARPROC existing_function = ::GetProcAddress(module, function_name);
+    if (!existing_function) {
+      return SIDESTEP_NO_SUCH_FUNCTION;
+    }
+    return RawPatch(existing_function, replacement_function,
+                    reinterpret_cast<void**>(original_function_stub));
+  }
+
+  // Patches a function by overwriting its first few bytes with
+  // a jump to a different function.  This is the "worker" function
+  // for each of the typesafe Patch() functions.  In most cases,
+  // it is preferable to use the Patch() functions rather than
+  // this one as they do more checking at compile time.
+  //
+  // @param target_function A pointer to the function that should be
+  // patched.
+  //
+  // @param replacement_function A pointer to the function that should
+  // replace the target function.  The replacement function must have
+  // exactly the same calling convention and parameters as the original
+  // function.
+  //
+  // @param original_function_stub Pointer to memory that should receive a
+  // pointer that can be used (e.g. in the replacement function) to call the
+  // original function, or NULL to indicate failure.
+  //
+  // @param original_function_stub Pointer to memory that should receive a
+  // pointer that can be used (e.g. in the replacement function) to call the
+  // original function, or NULL to indicate failure.
+  //
+  // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
+  // indicates success.
+  //
+  // @note The preamble-stub (the memory pointed to by
+  // *original_function_stub) is allocated on the heap, and (in
+  // production binaries) never destroyed, resulting in a memory leak.  This
+  // will be the case until we implement safe unpatching of a method.
+  // However, it is quite difficult to unpatch a method (because other
+  // threads in the process may be using it) so we are leaving it for now.
+  // See however UnsafeUnpatch, which can be used for binaries where you
+  // know only one thread is running, e.g. unit tests.
+  static SideStepError RawPatch(void* target_function,
+                                  void* replacement_function,
+                                  void** original_function_stub);
+
+  // Unpatches target_function and deletes the stub that previously could be
+  // used to call the original version of the function.
+  //
+  // DELETES the stub that is passed to the function.
+  //
+  // @param target_function Pointer to the target function which was
+  // previously patched, i.e. a pointer which value should match the value
+  // of the symbol prior to patching it.
+  //
+  // @param replacement_function Pointer to the function target_function
+  // was patched to.
+  //
+  // @param original_function_stub Pointer to the stub returned when
+  // patching, that could be used to call the original version of the
+  // patched function.  This function will also delete the stub, which after
+  // unpatching is useless.
+  //
+  // If your original call was
+  //    origptr = Patch(VirtualAlloc, MyVirtualAlloc)
+  // then to undo it you would call
+  //    Unpatch(VirtualAlloc, MyVirtualAlloc, origptr);
+  //
+  // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
+  // indicates success.
+  static SideStepError Unpatch(void* target_function,
+                               void* replacement_function,
+                               void* original_function_stub);
+
+ private:
+
+  // Patches a function by overwriting its first few bytes with
+  // a jump to a different function.  This is similar to the RawPatch
+  // function except that it uses the stub allocated by the caller
+  // instead of allocating it.
+  //
+  // We call VirtualProtect to make the
+  // target function writable at least for the duration of the call.
+  //
+  // @param target_function A pointer to the function that should be
+  // patched.
+  //
+  // @param replacement_function A pointer to the function that should
+  // replace the target function.  The replacement function must have
+  // exactly the same calling convention and parameters as the original
+  // function.
+  //
+  // @param preamble_stub A pointer to a buffer where the preamble stub 
+  // should be copied. The size of the buffer should be sufficient to
+  // hold the preamble bytes. 
+  //
+  // @param stub_size Size in bytes of the buffer allocated for the
+  // preamble_stub
+  //
+  // @param bytes_needed Pointer to a variable that receives the minimum
+  // number of bytes required for the stub.  Can be set to NULL if you're
+  // not interested.
+  //
+  // @return An error code indicating the result of patching.
+  static SideStepError RawPatchWithStubAndProtections(void* target_function, 
+                                          void *replacement_function, 
+                                          unsigned char* preamble_stub, 
+                                          unsigned long stub_size, 
+                                          unsigned long* bytes_needed);
+
+  // A helper function used by RawPatchWithStubAndProtections -- it does
+  // everything but the VirtualProtect wsork.  Defined in
+  // preamble_patcher_with_stub.cc.
+  static SideStepError RawPatchWithStub(void* target_function, 
+                                          void *replacement_function, 
+                                          unsigned char* preamble_stub, 
+                                          unsigned long stub_size, 
+                                          unsigned long* bytes_needed);
+};
+
+};  // namespace sidestep
+
+#endif  // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H__
diff --git a/src/windows/preamble_patcher_with_stub.cc b/src/windows/preamble_patcher_with_stub.cc
new file mode 100644
index 0000000..1ad4326
--- /dev/null
+++ b/src/windows/preamble_patcher_with_stub.cc
@@ -0,0 +1,193 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Implementation of PreamblePatcher
+ */
+
+#include "preamble_patcher.h"
+
+#include "mini_disassembler.h"
+
+// Definitions of assembly statements we need
+#define ASM_JMP32REL 0xE9
+#define ASM_INT3 0xCC
+
+namespace sidestep {
+
+SideStepError PreamblePatcher::RawPatchWithStub( 
+    void* target_function, 
+    void *replacement_function, 
+    unsigned char* preamble_stub, 
+    unsigned long stub_size, 
+    unsigned long* bytes_needed) {
+  if ((NULL == target_function) || 
+      (NULL == replacement_function) || 
+      (NULL == preamble_stub)) {
+    ASSERT(false, "Invalid parameters - either pTargetFunction or "
+                  "pReplacementFunction or pPreambleStub were NULL.");
+    return SIDESTEP_INVALID_PARAMETER;
+  }
+
+  // TODO(V7:joi) Siggi and I just had a discussion and decided that both
+  // patching and unpatching are actually unsafe.  We also discussed a
+  // method of making it safe, which is to freeze all other threads in the
+  // process, check their thread context to see if their eip is currently
+  // inside the block of instructions we need to copy to the stub, and if so
+  // wait a bit and try again, then unfreeze all threads once we've patched.
+  // Not implementing this for now since we're only using SideStep for unit
+  // testing, but if we ever use it for production code this is what we
+  // should do.
+  //
+  // NOTE: Stoyan suggests we can write 8 or even 10 bytes atomically using
+  // FPU instructions, and on newer processors we could use cmpxchg8b or
+  // cmpxchg16b. So it might be possible to do the patching/unpatching
+  // atomically and avoid having to freeze other threads.  Note though, that
+  // doing it atomically does not help if one of the other threads happens
+  // to have its eip in the middle of the bytes you change while you change
+  // them.
+  unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
+
+  // First, deal with a special case that we see with functions that
+  // point into an IAT table (including functions linked statically
+  // into the application): these function already starts with
+  // ASM_JMP32REL.  For instance, malloc() might be implemented as a
+  // JMP to __malloc().  In that case, we replace the destination of
+  // the JMP (__malloc), rather than the JMP itself (malloc).  This
+  // way we get the correct behavior no matter how malloc gets called.
+  if (target[0] == ASM_JMP32REL) {
+    // target[1-4] holds the place the jmp goes to, but it's
+    // relative to the next instruction.
+    int relative_offset;   // Windows guarantees int is 4 bytes
+    ASSERT1(sizeof(relative_offset) == 4);
+    memcpy(reinterpret_cast<void*>(&relative_offset),
+           reinterpret_cast<void*>(target + 1), 4);
+    // I'd like to just say "target = target + 5 + relative_offset" here, but
+    // I can't, because the new target will need to have its protections set.
+    return RawPatchWithStubAndProtections(target + 5 + relative_offset,
+                                          replacement_function, preamble_stub,
+                                          stub_size, bytes_needed);
+  }
+
+  // Let's disassemble the preamble of the target function to see if we can
+  // patch, and to see how much of the preamble we need to take.  We need 5
+  // bytes for our jmp instruction, so let's find the minimum number of
+  // instructions to get 5 bytes.
+  MiniDisassembler disassembler;
+  unsigned int preamble_bytes = 0;
+  while (preamble_bytes < 5) {
+    InstructionType instruction_type = 
+      disassembler.Disassemble(target + preamble_bytes, preamble_bytes);
+    if (IT_JUMP == instruction_type) {
+      ASSERT(false, "Unable to patch because there is a jump instruction "
+                     "in the first 5 bytes.");
+      return SIDESTEP_JUMP_INSTRUCTION;
+    } else if (IT_RETURN == instruction_type) {
+      ASSERT(false, "Unable to patch because function is too short");
+      return SIDESTEP_FUNCTION_TOO_SMALL;
+    } else if (IT_GENERIC != instruction_type) {
+      ASSERT(false, "Disassembler encountered unsupported instruction "
+                    "(either unused or unknown)");
+      return SIDESTEP_UNSUPPORTED_INSTRUCTION;
+    }
+  }
+
+  if (NULL != bytes_needed)
+    *bytes_needed = preamble_bytes + 5;
+
+  // Inv: cbPreamble is the number of bytes (at least 5) that we need to take
+  // from the preamble to have whole instructions that are 5 bytes or more
+  // in size total. The size of the stub required is cbPreamble + size of
+  // jmp (5)
+  if (preamble_bytes + 5 > stub_size) {
+    ASSERT1(false);
+    return SIDESTEP_INSUFFICIENT_BUFFER;
+  }
+
+  // First, copy the preamble that we will overwrite.
+  memcpy(reinterpret_cast<void*>(preamble_stub),
+         reinterpret_cast<void*>(target), preamble_bytes);
+
+  // Now, make a jmp instruction to the rest of the target function (minus the
+  // preamble bytes we moved into the stub) and copy it into our preamble-stub.
+  // find address to jump to, relative to next address after jmp instruction
+#pragma warning(push)
+#pragma warning(disable:4244)
+  int relative_offset_to_target_rest
+    = ((reinterpret_cast<unsigned char*>(target) + preamble_bytes) - 
+        (preamble_stub + preamble_bytes + 5));
+#pragma warning(pop)
+  // jmp (Jump near, relative, displacement relative to next instruction)
+  preamble_stub[preamble_bytes] = ASM_JMP32REL;
+  // copy the address
+  memcpy(reinterpret_cast<void*>(preamble_stub + preamble_bytes + 1),
+    reinterpret_cast<void*>(&relative_offset_to_target_rest), 4);
+
+  // Inv: preamble_stub points to assembly code that will execute the
+  // original function by first executing the first cbPreamble bytes of the
+  // preamble, then jumping to the rest of the function.
+
+  // Overwrite the first 5 bytes of the target function with a jump to our
+  // replacement function.
+  // (Jump near, relative, displacement relative to next instruction)
+  target[0] = ASM_JMP32REL;
+
+  // Find offset from instruction after jmp, to the replacement function.
+#pragma warning(push)
+#pragma warning(disable:4244)
+  int offset_to_replacement_function =
+    reinterpret_cast<unsigned char*>(replacement_function) -
+    reinterpret_cast<unsigned char*>(target) - 5;
+#pragma warning(pop)
+  // complete the jmp instruction
+  memcpy(reinterpret_cast<void*>(target + 1),
+         reinterpret_cast<void*>(&offset_to_replacement_function), 4);
+  // Set any remaining bytes that were moved to the preamble-stub to INT3 so
+  // as not to cause confusion (otherwise you might see some strange
+  // instructions if you look at the disassembly, or even invalid
+  // instructions). Also, by doing this, we will break into the debugger if
+  // some code calls into this portion of the code.  If this happens, it
+  // means that this function cannot be patched using this patcher without
+  // further thought.
+  if (preamble_bytes > 5) {
+    memset(reinterpret_cast<void*>(target + 5), ASM_INT3, preamble_bytes - 5);
+  }
+
+  // Inv: The memory pointed to by target_function now points to a relative
+  // jump instruction that jumps over to the preamble_stub.  The preamble
+  // stub contains the first stub_size bytes of the original target
+  // function's preamble code, followed by a relative jump back to the next
+  // instruction after the first cbPreamble bytes.
+
+  return SIDESTEP_SUCCESS;
+}
+
+};  // namespace sidestep
diff --git a/src/windows/vc7and8.def b/src/windows/vc7and8.def
index e0eb312..79320ae 100644
--- a/src/windows/vc7and8.def
+++ b/src/windows/vc7and8.def
@@ -1,21 +1,27 @@
 ;; Most symbols in the google-perftools dll are exported via
-;; __declspec(dllexport).  However, we can't do that for the memory
-;; allocation routines we override (malloc, free, new), because those
-;; already have an export spec in msvcrt.dll.  In particular, they're
-;; already declared internally in a header that exists in the
-;; compiler's own static data, and there's no way to override
-;; inclusion of that header.  Since that header doesn't declare these
-;; functoin dllexport, we can't redeclare them dllexport.  Therefore,
-;; we have to put any export decorations either here, or nowhere.
+;; __declspec(dllexport).  This works fine for functions we're
+;; defining ourselves, but not for functions we're overriding, like
+;; malloc, free, and new.  Those already have an export spec in
+;; msvcrt.dll.  (In particular, they're already declared internally in
+;; a header that exists in the compiler's own static data, and there's
+;; no way to override inclusion of that header.)  Since that header
+;; doesn't declare these functions dllexport, we can't redeclare them
+;; dllexport.
 ;;
-;; Apparently, for malloc, free, and realloc, the right thing to do is
-;; to put the export decorations nowhere: I guess msvcrt already does
-;; something (I don't know what) that lets us override these functions
-;; just by declaring our own version, without any need to export.
+;; For malloc, calloc, realloc, and free, not only can we not override
+;; the declaration, we can't override the definition: windows does not
+;; provide "weak" linkage for these functions (in general).
+;; The way we deal with these functions in code is to patch the
+;; assembly code for the Windows malloc/etc to point to our
+;; functions.  Using this technique, there's no need to declare our
+;; own version of malloc/etc anywhere: we do our own "exporting" when
+;; we patch up the assembly code.
 ;;
-;; However, for new and delete, the right thing to do is to export the
-;; symbol here, in a .def file.  We export the 4 versions of new and
-;; delete that  we override:
+;; For new and delete, we *can* override the definition.  That means
+;; we need to export our declaration.  As mentioned, we can't
+;; redeclare them dllexport in our .h file.  The only other way to
+;; export a declaration is to declare it here, in a .def file.
+;; We export the 4 versions of new and delete that  we override:
 ;;     ??2@YAPAXI@Z    (void * __cdecl operator new(unsigned int))
 ;;     ??3@YAXPAX@Z    (void __cdecl operator delete(void *))
 ;;     ??_U@YAPAXI@Z   (void * __cdecl operator new[](unsigned int))
diff --git a/vsprojects/addressmap_unittest/addressmap_unittest.vcproj b/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
index e3e6ed0..7a4c242 100755
--- a/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
+++ b/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
@@ -118,13 +118,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 			<File

@@ -133,13 +135,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 			<File

@@ -148,13 +152,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 		</Filter>

diff --git a/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj b/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
index adc7c5a..d1356bd 100755
--- a/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
+++ b/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
@@ -31,7 +31,7 @@
 				Name="VCCustomBuildTool"/>

 			<Tool

 				Name="VCLinkerTool"

-				OutputFile="$(OutDir)/libtcmalloc_minimal.dll"

+				OutputFile="$(OutDir)/libtcmalloc_minimal-debug.dll"

 				LinkIncremental="2"

 				ModuleDefinitionFile="..\..\src\windows\vc7and8.def"

 				GenerateDebugInformation="TRUE"

@@ -80,7 +80,7 @@
 				Name="VCLinkerTool"

 				OutputFile="$(OutDir)/libtcmalloc_minimal.dll"

 				LinkIncremental="1"

-				ModuleDefinitionFile="src\windows\vc7and8.def"

+				ModuleDefinitionFile="..\..\src\windows\vc7and8.def"

 				GenerateDebugInformation="TRUE"

 				SubSystem="2"

 				OptimizeReferences="2"

@@ -134,6 +134,40 @@
 				</FileConfiguration>

 			</File>

 			<File

+				RelativePath="..\..\src\windows\ia32_modrm_map.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\ia32_opcode_map.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

 				RelativePath="..\..\src\internal_logging.cc">

 				<FileConfiguration

 					Name="Debug|Win32">

@@ -236,6 +270,40 @@
 				</FileConfiguration>

 			</File>

 			<File

+				RelativePath="..\..\src\windows\mini_disassembler.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\patch_functions.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

 				RelativePath="..\..\src\windows\port.cc">

 				<FileConfiguration

 					Name="Debug|Win32">

@@ -253,6 +321,57 @@
 				</FileConfiguration>

 			</File>

 			<File

+				RelativePath="..\..\src\windows\preamble_patcher.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\preamble_patcher_with_stub.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\base\sysinfo.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows;..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows;..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

 				RelativePath="..\..\src\tcmalloc.cc">

 				<FileConfiguration

 					Name="Debug|Win32">

@@ -317,6 +436,12 @@
 				RelativePath="..\..\src\memory_region_map.h">

 			</File>

 			<File

+				RelativePath="..\..\src\windows\mini_disassembler.h">

+			</File>

+			<File

+				RelativePath="..\..\src\windows\mini_disassembler_types.h">

+			</File>

+			<File

 				RelativePath="..\..\src\base\mutex.h">

 			</File>

 			<File

@@ -329,6 +454,9 @@
 				RelativePath="..\..\src\windows\port.h">

 			</File>

 			<File

+				RelativePath="..\..\src\windows\preamble_patcher.h">

+			</File>

+			<File

 				RelativePath="..\..\src\google\profiler.h">

 			</File>

 			<File

@@ -338,6 +466,9 @@
 				RelativePath="..\..\src\base\stl_allocator.h">

 			</File>

 			<File

+				RelativePath="..\..\src\base\sysinfo.h">

+			</File>

+			<File

 				RelativePath="..\..\src\system-alloc.h">

 			</File>

 			<File

diff --git a/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj b/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
index a5f39b6..85760c1 100755
--- a/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
+++ b/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
@@ -118,13 +118,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 			<File

@@ -133,13 +135,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 			<File

@@ -148,13 +152,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 			<File

@@ -163,13 +169,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 			<File

@@ -178,13 +186,15 @@
 					Name="Debug|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

 				</FileConfiguration>

 				<FileConfiguration

 					Name="Release|Win32">

 					<Tool

 						Name="VCCLCompilerTool"

-						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"/>

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

 				</FileConfiguration>

 			</File>

 		</Filter>

diff --git a/vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj b/vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj
new file mode 100755
index 0000000..fbee663
--- /dev/null
+++ b/vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj
@@ -0,0 +1,546 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="tcmalloc_minimal_unittest-static"

+	ProjectGUID="{8F708DCB-7EE4-4BA0-81AA-A52A0BA73B74}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/tcmalloc_minimal_unittest-static.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/tcmalloc_minimal_unittest-static.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				RuntimeLibrary="4"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/tcmalloc_minimal_unittest-static.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\..\src\heap-profile-table.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\ia32_modrm_map.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\ia32_opcode_map.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\internal_logging.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\base\logging.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\base\low_level_alloc.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\malloc_extension.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\malloc_hook.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\memory_region_map.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\mini_disassembler.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\patch_functions.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\port.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\preamble_patcher.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\windows\preamble_patcher_with_stub.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\base\sysinfo.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows;..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="..\..\src\windows;..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\tcmalloc.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\tests\tcmalloc_unittest.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\src\tests\testutil.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalOptions="/D PERFTOOLS_DLL_DECL="

+						AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"

+						RuntimeLibrary="2"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+			<File

+				RelativePath="..\..\src\addressmap-inl.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\basictypes.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\commandlineflags.h">

+			</File>

+			<File

+				RelativePath="..\..\src\windows\config.h">

+			</File>

+			<File

+				RelativePath="..\..\src\config_for_unittests.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\googleinit.h">

+			</File>

+			<File

+				RelativePath="..\..\src\google\heap-checker.h">

+			</File>

+			<File

+				RelativePath="..\..\src\heap-profile-table.h">

+			</File>

+			<File

+				RelativePath="..\..\src\google\heap-profiler.h">

+			</File>

+			<File

+				RelativePath="..\..\src\internal_logging.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\logging.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\low_level_alloc.h">

+			</File>

+			<File

+				RelativePath="..\..\src\google\malloc_extension.h">

+			</File>

+			<File

+				RelativePath="..\..\src\google\malloc_hook.h">

+			</File>

+			<File

+				RelativePath="..\..\src\memory_region_map.h">

+			</File>

+			<File

+				RelativePath="..\..\src\windows\mini_disassembler.h">

+			</File>

+			<File

+				RelativePath="..\..\src\windows\mini_disassembler_types.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\mutex.h">

+			</File>

+			<File

+				RelativePath="..\..\src\packed-cache-inl.h">

+			</File>

+			<File

+				RelativePath="..\..\src\pagemap.h">

+			</File>

+			<File

+				RelativePath="..\..\src\windows\port.h">

+			</File>

+			<File

+				RelativePath="..\..\src\windows\preamble_patcher.h">

+			</File>

+			<File

+				RelativePath="..\..\src\google\profiler.h">

+			</File>

+			<File

+				RelativePath="..\..\src\google\stacktrace.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\stl_allocator.h">

+			</File>

+			<File

+				RelativePath="..\..\src\base\sysinfo.h">

+			</File>

+			<File

+				RelativePath="..\..\src\system-alloc.h">

+			</File>

+			<File

+				RelativePath="..\..\src\tcmalloc.h">

+			</File>

+			<File

+				RelativePath="..\..\src\tests\testutil.h">

+			</File>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>