diff options
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | Makefile.am | 20 | ||||
-rw-r--r-- | Makefile.in | 12 | ||||
-rw-r--r-- | NEWS | 30 | ||||
-rw-r--r-- | README_windows.txt | 5 | ||||
-rwxr-xr-x | configure | 4 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rwxr-xr-x | google-perftools.sln | 7 | ||||
-rw-r--r-- | packages/deb/changelog | 8 | ||||
-rw-r--r-- | packages/deb/copyright | 4 | ||||
-rwxr-xr-x | src/pprof | 2 | ||||
-rw-r--r-- | src/system-alloc.cc | 2 | ||||
-rw-r--r-- | src/tcmalloc.cc | 10 | ||||
-rw-r--r-- | src/windows/config.h | 4 | ||||
-rw-r--r-- | src/windows/mini_disassembler.h | 3 | ||||
-rw-r--r-- | src/windows/patch_functions.cc | 4 | ||||
-rw-r--r-- | src/windows/preamble_patcher.h | 3 | ||||
-rw-r--r-- | src/windows/preamble_patcher_test.cc | 655 | ||||
-rw-r--r-- | src/windows/shortproc.asm | 2 | ||||
-rwxr-xr-x | vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj | 180 |
20 files changed, 641 insertions, 340 deletions
@@ -1,3 +1,25 @@ +Tue Jan 31 10:43:50 2012 Google Inc. <opensource@google.com> + + * google-perftools: version 1.10 release + * PORTING: Support for patching assembly on win x86_64! (scott.fr...) + * PORTING: Work around atexit-execution-order bug on freebsd (csilvers) + * PORTING: Patch _calloc_crt for windows (roger orr) + * PORTING: Add C++11 compatibility method for stl allocator (jdennett) + * PORTING: use MADV_FREE, not MADV_DONTNEED, on freebsd (csilvers) + * PORTING: Don't use SYS_open when not supported on solaris (csilvers) + * PORTING: Do not assume uname() returns 0 on success (csilvers) + * LSS: Improved ARM support in linux-syscall-support (dougkwan) + * LSS: Get rid of unused syscalls in linux-syscall-support (csilvers) + * LSS: Fix broken mmap wrapping for ppc (markus) + * LSS: Emit .cfi_adjust_cfa_offset when appropriate (ppluzhnikov) + * LSS: Be more accurate in register use in __asm__ (markus) + * LSS: Fix __asm__ calls to compile under clang (chandlerc) + * LSS: Fix ARM inline assembly bug around r7 and swi (lcwu) + * No longer log when an allocator fails (csilvers) + * void* -> const void* for MallocExtension methods (llib) + * Improve HEAP_PROFILE_MMAP and fix bugs with it (dmikurube) + * Replace int-based abs with more correct fabs in a test (pmurin) + Thu Dec 22 16:22:45 2011 Google Inc. <opensource@google.com> * google-perftools: version 1.9 release diff --git a/Makefile.am b/Makefile.am index cd6c8b0..91eb55b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -226,6 +226,18 @@ LIBSPINLOCK = libwindows.la libspinlock.la libsysinfo.la liblogging.la # (We do this via a #pragma for msvc, but need to do it here for mingw). libsysinfo_la_LIBADD += -lshlwapi +# There's a windows-specific unittest we can run. Right now it's +# win64-specific, and relies on masm, so we comment it out. +## TESTS += preamble_patcher_test +## preamble_patcher_test_SOURCES = src/windows/preamble_patcher_test.cc \ +## src/windows/shortproc.asm \ +## src/windows/auto_testing_hook.h \ +## src/windows/preamble_patcher.h \ +## src/base/basictypes.h \ +## src/base/logging.h +## preamble_patcher_test_LDFLAGS = $(TCMALLOC_FLAGS) +## preamble_patcher_test_LDADD = $(LIBTCMALLOC_MINIMAL) + # patch_functions.cc #includes tcmalloc.cc, so no need to link it in. TCMALLOC_CC = # windows has its own system for threads and system memory allocation. @@ -255,6 +267,14 @@ MAYBE_THREADS_CC = src/maybe_threads.cc SYSTEM_ALLOC_CC = src/system-alloc.cc endif !MINGW +# Add this whether or not we're under MinGW, to keep the tarball complete. +WINDOWS_PROJECTS += vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj +# Because we've commented out the test, above, we have to explicitly add +# the test files to the tarball or automake will leave them out. +WINDOWS_PROJECTS += src/windows/preamble_patcher_test.cc \ + src/windows/shortproc.asm \ + src/windows/auto_testing_hook.h + ### Unittests TESTS += low_level_alloc_unittest WINDOWS_PROJECTS += vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj diff --git a/Makefile.in b/Makefile.in index aa23791..aabf1a8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1774,7 +1774,14 @@ lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_24) \ noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_8) \ $(am__append_10) $(am__append_12) \ libtcmalloc_minimal_internal.la $(am__append_33) + +# Add this whether or not we're under MinGW, to keep the tarball complete. +# Because we've commented out the test, above, we have to explicitly add +# the test files to the tarball or automake will leave them out. WINDOWS_PROJECTS = google-perftools.sln \ + vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj \ + src/windows/preamble_patcher_test.cc src/windows/shortproc.asm \ + src/windows/auto_testing_hook.h \ vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj \ $(am__append_16) \ vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj \ @@ -1921,6 +1928,9 @@ libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_9) @MINGW_TRUE@LIBSPINLOCK = libwindows.la libspinlock.la libsysinfo.la liblogging.la @MINGW_FALSE@TCMALLOC_CC = src/tcmalloc.cc +# There's a windows-specific unittest we can run. Right now it's +# win64-specific, and relies on masm, so we comment it out. + # patch_functions.cc #includes tcmalloc.cc, so no need to link it in. @MINGW_TRUE@TCMALLOC_CC = @MINGW_FALSE@MAYBE_THREADS_CC = src/maybe_threads.cc @@ -4765,7 +4775,7 @@ check-TESTS: $(TESTS) 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)/src/windows $(distdir)/src/windows/google $(distdir)/vsprojects/addr2line-pdb $(distdir)/vsprojects/addressmap_unittest $(distdir)/vsprojects/current_allocated_bytes_test $(distdir)/vsprojects/frag_unittest $(distdir)/vsprojects/libtcmalloc_minimal $(distdir)/vsprojects/low_level_alloc_unittest $(distdir)/vsprojects/malloc_extension_test $(distdir)/vsprojects/malloc_hook_test $(distdir)/vsprojects/markidle_unittest $(distdir)/vsprojects/nm-pdb $(distdir)/vsprojects/packed-cache_test $(distdir)/vsprojects/page_heap_test $(distdir)/vsprojects/pagemap_unittest $(distdir)/vsprojects/realloc_unittest $(distdir)/vsprojects/sampler_test $(distdir)/vsprojects/stack_trace_table_test $(distdir)/vsprojects/tcmalloc_minimal_large $(distdir)/vsprojects/tcmalloc_minimal_unittest $(distdir)/vsprojects/thread_dealloc_unittest $(distdir)/vsprojects/tmu-static + $(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)/src/windows $(distdir)/src/windows/google $(distdir)/vsprojects/addr2line-pdb $(distdir)/vsprojects/addressmap_unittest $(distdir)/vsprojects/current_allocated_bytes_test $(distdir)/vsprojects/frag_unittest $(distdir)/vsprojects/libtcmalloc_minimal $(distdir)/vsprojects/low_level_alloc_unittest $(distdir)/vsprojects/malloc_extension_test $(distdir)/vsprojects/malloc_hook_test $(distdir)/vsprojects/markidle_unittest $(distdir)/vsprojects/nm-pdb $(distdir)/vsprojects/packed-cache_test $(distdir)/vsprojects/page_heap_test $(distdir)/vsprojects/pagemap_unittest $(distdir)/vsprojects/preamble_patcher_test $(distdir)/vsprojects/realloc_unittest $(distdir)/vsprojects/sampler_test $(distdir)/vsprojects/stack_trace_table_test $(distdir)/vsprojects/tcmalloc_minimal_large $(distdir)/vsprojects/tcmalloc_minimal_unittest $(distdir)/vsprojects/thread_dealloc_unittest $(distdir)/vsprojects/tmu-static @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -1,4 +1,32 @@ -== 24 January 2011 == +== 31 January 2012 == + +I've just released perftools 1.10 + +There is an API-incompatible change: several of the methods in the +`MallocExtension` class have changed from taking a `void*` to taking a +`const void*`. You should not be affected by this API change +unless you've written your own custom malloc extension that derives +from `MallocExtension`, but since it is a user-visible change, I have +upped the `.so` version number for this release. + +This release focuses on improvements to linux-syscall-support.h, +including ARM and PPC fixups and general cleanups. I hope this will +magically fix an array of bugs people have been seeing. + +There is also exciting news on the porting front, with support for +patching win64 assembly contributed by IBM Canada! This is an +important step -- perhaps the most difficult -- to getting perftools +to work on 64-bit windows using the patching technique (it doesn't +affect the libc-modification technique). `premable_patcher_test` has +been added to help test these changes; it is meant to compile under +x86_64, and won't work under win32. + +For the full list of changes, including improved `HEAP_PROFILE_MMAP` +support, see the +[http://google-perftools.googlecode.com/svn/tags/google-perftools-1.10/ChangeLog ChangeLog]. + + +=== 24 January 2011 === The `google-perftools` Google Code page has been renamed to `gperftools`, in preparation for the project being renamed to diff --git a/README_windows.txt b/README_windows.txt index 660abbb..621f1a3 100644 --- a/README_windows.txt +++ b/README_windows.txt @@ -78,6 +78,11 @@ both x86 and x64. In particular, if you use the 'statically link with libc, and replace its malloc with tcmalloc' approach, mentioned above,
it should be possible to use tcmalloc with 64-bit windows.
+As of perftools 1.10, there is some support for disassembling x86_64
+instructions, for work with win64. This work is preliminary, but the
+test file preamble_patcher_test.cc is provided to play around with
+that a bit. preamble_patcher_test will not compile on win32.
+
--- ISSUES
@@ -2592,8 +2592,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -TCMALLOC_SO_VERSION=3:0:3 -PROFILER_SO_VERSION=2:0:2 +TCMALLOC_SO_VERSION=4:0:0 +PROFILER_SO_VERSION=2:1:2 diff --git a/configure.ac b/configure.ac index eb8ba7c..659d3dc 100644 --- a/configure.ac +++ b/configure.ac @@ -7,8 +7,8 @@ AC_PREREQ(2.57) AC_INIT(google-perftools, 1.10, opensource@google.com) # Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -TCMALLOC_SO_VERSION=3:0:3 -PROFILER_SO_VERSION=2:0:2 +TCMALLOC_SO_VERSION=4:0:0 +PROFILER_SO_VERSION=2:1:2 AC_SUBST(TCMALLOC_SO_VERSION) AC_SUBST(PROFILER_SO_VERSION) diff --git a/google-perftools.sln b/google-perftools.sln index f7d29a5..7c3faa8 100755 --- a/google-perftools.sln +++ b/google-perftools.sln @@ -87,6 +87,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tmu-static", "vsprojects\tm ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "preamble_patcher_test", "vsprojects\preamble_patcher_test\preamble_patcher_test.vcproj", "{5765198D-5305-4AB0-9A21-A0CD8201EB2A}"
+ ProjectSection(ProjectDependencies) = postProject
+ {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} = {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}
+ EndProjectSection
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "addr2line-pdb", "vsprojects\addr2line-pdb\addr2line-pdb.vcproj", "{81CA712E-90B8-4AE5-9E89-5B436578D6DA}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
@@ -175,6 +180,8 @@ Global {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
+ {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug.ActiveCfg = Debug|Win32
+ {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release.ActiveCfg = Release|Win32
{81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Debug.ActiveCfg = Debug|Win32
{81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Debug.Build.0 = Debug|Win32
{81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release.ActiveCfg = Release|Win32
diff --git a/packages/deb/changelog b/packages/deb/changelog index 73673e4..4d72c97 100644 --- a/packages/deb/changelog +++ b/packages/deb/changelog @@ -1,3 +1,9 @@ +google-perftools (1.10-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. <opensource@google.com> Tue, 31 Jan 2012 10:43:50 -0800 + google-perftools (1.9-1) unstable; urgency=low * New upstream release. @@ -152,7 +158,7 @@ google-perftools (0.5-1) unstable; urgency=low * New upstream release. - -- Google Inc. <opensource@google.com> Mon Nov 14 17:28:59 2005 -0800 + -- Google Inc. <opensource@google.com> Mon, Nov 14 17:28:59 2005 -0800 google-perftools (0.4-1) unstable; urgency=low diff --git a/packages/deb/copyright b/packages/deb/copyright index 725a37d..f98719c 100644 --- a/packages/deb/copyright +++ b/packages/deb/copyright @@ -1,7 +1,7 @@ This package was debianized by Google Inc. <opensource@google.com> on -15 February 2005. +Tue, 31 Jan 2012 10:43:50 -0800. -It was downloaded from http://code.google.com/ +It was downloaded from http://code.google.com/p/gperftools/downloads/list Upstream Author: opensource@google.com @@ -72,7 +72,7 @@ use strict; use warnings; use Getopt::Long; -my $PPROF_VERSION = "1.9"; +my $PPROF_VERSION = "1.10"; # These are the object tools we use which can come from a # user-specified location using --tools, from the PPROF_TOOLS diff --git a/src/system-alloc.cc b/src/system-alloc.cc index cf35446..ea718b3 100644 --- a/src/system-alloc.cc +++ b/src/system-alloc.cc @@ -64,7 +64,7 @@ // MADV_FREE is specifically designed for use by malloc(), but only // FreeBSD supports it; in linux we fall back to the somewhat inferior // MADV_DONTNEED. -#ifndef MADV_FREE +#if !defined(MADV_FREE) && defined(MADV_DONTNEED) # define MADV_FREE MADV_DONTNEED #endif diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc index a83e7ea..425e90b 100644 --- a/src/tcmalloc.cc +++ b/src/tcmalloc.cc @@ -1095,7 +1095,15 @@ static inline ThreadCache* GetCacheIfPresent() { // It is used primarily by windows code which wants a specialized callback. inline void do_free_with_callback(void* ptr, void (*invalid_free_fn)(void*)) { if (ptr == NULL) return; - ASSERT(Static::pageheap() != NULL); // Should not call free() before malloc() + if (Static::pageheap() == NULL) { + // We called free() before malloc(). This can occur if the + // (system) malloc() is called before tcmalloc is loaded, and then + // free() is called after tcmalloc is loaded (and tc_free has + // replaced free), but before the global constructor has run that + // sets up the tcmalloc data structures. + (*invalid_free_fn)(ptr); // Decide how to handle the bad free request + return; + } const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; Span* span = NULL; size_t cl = Static::pageheap()->GetSizeClassIfCached(p); diff --git a/src/windows/config.h b/src/windows/config.h index f802c50..9504db2 100644 --- a/src/windows/config.h +++ b/src/windows/config.h @@ -222,7 +222,7 @@ #define PACKAGE_NAME "google-perftools" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "google-perftools 1.9" +#define PACKAGE_STRING "google-perftools 1.10" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "google-perftools" @@ -231,7 +231,7 @@ #undef PACKAGE_URL /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.9" +#define PACKAGE_VERSION "1.10" /* How to access the PC from a struct ucontext */ #undef PC_FROM_UCONTEXT diff --git a/src/windows/mini_disassembler.h b/src/windows/mini_disassembler.h index 59a5d08..52daa5d 100644 --- a/src/windows/mini_disassembler.h +++ b/src/windows/mini_disassembler.h @@ -36,6 +36,7 @@ #ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ #define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ +#include "config.h" #include <windows.h> #include "mini_disassembler_types.h" @@ -74,7 +75,7 @@ namespace sidestep { // IA-32 Intel® Architecture Software Developer’s Manual Volume 2: // Instruction Set Reference for information about operand decoding // etc. -class MiniDisassembler { +class PERFTOOLS_DLL_DECL MiniDisassembler { public: // Creates a new instance and sets defaults. diff --git a/src/windows/patch_functions.cc b/src/windows/patch_functions.cc index 3ff6eb5..813c9aa 100644 --- a/src/windows/patch_functions.cc +++ b/src/windows/patch_functions.cc @@ -826,7 +826,7 @@ void* LibcInfoWithPatchFunctions<T>::Perftools_realloc( return do_realloc_with_callback( old_ptr, new_size, (void (*)(void*))origstub_fn_[kFree], - (size_t (*)(void*))origstub_fn_[k_Msize]); + (size_t (*)(const void*))origstub_fn_[k_Msize]); } template<int T> @@ -904,7 +904,7 @@ void LibcInfoWithPatchFunctions<T>::Perftools_deletearray_nothrow( template<int T> size_t LibcInfoWithPatchFunctions<T>::Perftools__msize(void* ptr) __THROW { - return GetSizeWithCallback(ptr, (size_t (*)(void*))origstub_fn_[k_Msize]); + return GetSizeWithCallback(ptr, (size_t (*)(const void*))origstub_fn_[k_Msize]); } // We need to define this because internal windows functions like to diff --git a/src/windows/preamble_patcher.h b/src/windows/preamble_patcher.h index 50946bd..4fdb7d0 100644 --- a/src/windows/preamble_patcher.h +++ b/src/windows/preamble_patcher.h @@ -37,6 +37,7 @@ #ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ #define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ +#include "config.h" #include <windows.h> // compatibility shim @@ -147,7 +148,7 @@ class DeleteUnsignedCharArray; // 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_test.cc for an example. -class PreamblePatcher { +class PERFTOOLS_DLL_DECL PreamblePatcher { public: // This is a typesafe version of RawPatch(), identical in all other diff --git a/src/windows/preamble_patcher_test.cc b/src/windows/preamble_patcher_test.cc index 2506cfb..41ab551 100644 --- a/src/windows/preamble_patcher_test.cc +++ b/src/windows/preamble_patcher_test.cc @@ -32,325 +32,336 @@ * Author: Scott Francis * * Unit tests for PreamblePatcher - */
-
-#include "preamble_patcher.h"
-#include "mini_disassembler.h"
-#pragma warning(push)
-#pragma warning(disable:4553)
-#include "auto_testing_hook.h"
-#pragma warning(pop)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-
-// Turning off all optimizations for this file, since the official build's
-// "Whole program optimization" seems to cause the TestPatchUsingDynamicStub
-// test to crash with an access violation. We debugged this and found
-// that the optimized access a register that is changed by a call to the hook
-// function.
-#pragma optimize("", off)
-
-namespace {
-
-// Function for testing - this is what we patch
-//
-// NOTE: Because of the way the compiler optimizes this function in
-// release builds, we need to use a different input value every time we
-// call it within a function, otherwise the compiler will just reuse the
-// last calculated incremented value.
-int __declspec(noinline) IncrementNumber(int i) {
-#ifdef _M_X64
- __int64 i2 = i + 1;
- return (int) i2;
-#else
- return i + 1;
-#endif
-}
-
-extern "C" int TooShortFunction(int);
-
-extern "C" int JumpShortCondFunction(int);
-
-extern "C" int JumpNearCondFunction(int);
-
-extern "C" int JumpAbsoluteFunction(int);
-
-extern "C" int CallNearRelativeFunction(int);
-
-typedef int (*IncrementingFunc)(int);
-IncrementingFunc original_function = NULL;
-
-int HookIncrementNumber(int i) {
- SIDESTEP_ASSERT(original_function != NULL);
- int incremented_once = original_function(i);
- return incremented_once + 1;
-}
-
-// For the AutoTestingHook test, we can't use original_function, because
-// all that is encapsulated.
-// This function "increments" by 10, just to set it apart from the other
-// functions.
-int __declspec(noinline) AutoHookIncrementNumber(int i) {
- return i + 10;
-}
-
-}; // namespace
-
-namespace sidestep {
-
-bool TestDisassembler() {
- unsigned int instruction_size = 0;
- sidestep::MiniDisassembler disassembler;
- void * target = reinterpret_cast<unsigned char *>(IncrementNumber);
- void * new_target = PreamblePatcher::ResolveTarget(target);
- if (target != new_target)
- target = new_target;
-
- while (1) {
- sidestep::InstructionType instructionType = disassembler.Disassemble(
- reinterpret_cast<unsigned char *>(target) + instruction_size,
- instruction_size);
- if (sidestep::IT_RETURN == instructionType) {
- return true;
- }
- }
-}
-
-bool TestPatchWithLongJump() {
- original_function = NULL;
- void *p = ::VirtualAlloc(reinterpret_cast<void *>(0x0000020000000000), 4096,
- MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- SIDESTEP_EXPECT_TRUE(p != NULL);
- memset(p, 0xcc, 4096);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- (IncrementingFunc) p,
- &original_function));
- SIDESTEP_ASSERT((*original_function)(1) == 2);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Unpatch(IncrementNumber,
- (IncrementingFunc) p,
- original_function));
- ::VirtualFree(p, 0, MEM_RELEASE);
- return true;
-}
-
-bool TestPatchWithPreambleShortCondJump() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(JumpShortCondFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Unpatch(JumpShortCondFunction,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchWithPreambleNearRelativeCondJump() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(JumpNearCondFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(0);
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Unpatch(JumpNearCondFunction,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchWithPreambleAbsoluteJump() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(JumpAbsoluteFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(0);
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Unpatch(JumpAbsoluteFunction,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchWithPreambleNearRelativeCall() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(
- CallNearRelativeFunction,
- HookIncrementNumber,
- &original_function));
- (*original_function)(0);
- (*original_function)(1);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Unpatch(
- CallNearRelativeFunction,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool TestPatchUsingDynamicStub() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- HookIncrementNumber,
- &original_function));
- SIDESTEP_EXPECT_TRUE(original_function);
- SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 4);
- SIDESTEP_EXPECT_TRUE(original_function(3) == 4);
-
- // Clearbox test to see that the function has been patched.
- sidestep::MiniDisassembler disassembler;
- unsigned int instruction_size = 0;
- SIDESTEP_EXPECT_TRUE(sidestep::IT_JUMP == disassembler.Disassemble(
- reinterpret_cast<unsigned char*>(IncrementNumber),
- instruction_size));
-
- // Since we patched IncrementNumber, its first statement is a
- // jmp to the hook function. So verify that we now can not patch
- // IncrementNumber because it starts with a jump.
-#if 0
- IncrementingFunc dummy = NULL;
- // TODO(joi@chromium.org): restore this test once flag is added to
- // disable JMP following
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_JUMP_INSTRUCTION ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- HookIncrementNumber,
- &dummy));
-
- // This test disabled because code in preamble_patcher_with_stub.cc
- // asserts before returning the error code -- so there is no way
- // to get an error code here, in debug build.
- dummy = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_FUNCTION_TOO_SMALL ==
- sidestep::PreamblePatcher::Patch(TooShortFunction,
- HookIncrementNumber,
- &dummy));
-#endif
-
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Unpatch(IncrementNumber,
- HookIncrementNumber,
- original_function));
- return true;
-}
-
-bool PatchThenUnpatch() {
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Patch(IncrementNumber,
- HookIncrementNumber,
- &original_function));
- SIDESTEP_EXPECT_TRUE(original_function);
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 3);
- SIDESTEP_EXPECT_TRUE(original_function(2) == 3);
-
- SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
- sidestep::PreamblePatcher::Unpatch(IncrementNumber,
- HookIncrementNumber,
- original_function));
- original_function = NULL;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
-
- return true;
-}
-
-bool AutoTestingHookTest() {
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
-
- // Inner scope, so we can test what happens when the AutoTestingHook
- // goes out of scope
- {
- AutoTestingHook hook = MakeTestingHook(IncrementNumber,
- AutoHookIncrementNumber);
- (void) hook;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
- }
- SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
-
- return true;
-}
-
-bool AutoTestingHookInContainerTest() {
- SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
-
- // Inner scope, so we can test what happens when the AutoTestingHook
- // goes out of scope
- {
- AutoTestingHookHolder hook(MakeTestingHookHolder(IncrementNumber,
- AutoHookIncrementNumber));
- (void) hook;
- SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
- }
- SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
-
- return true;
-}
-
-bool TestPreambleAllocation() {
- __int64 diff = 0;
- void* p1 = reinterpret_cast<void*>(0x110000000);
- void* p2 = reinterpret_cast<void*>(0x810000000);
- unsigned char* b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
- SIDESTEP_EXPECT_TRUE(b1 != NULL);
- diff = reinterpret_cast<__int64>(p1) - reinterpret_cast<__int64>(b1);
- // Ensure blocks are within 2GB
- SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
- unsigned char* b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
- SIDESTEP_EXPECT_TRUE(b2 != NULL);
- diff = reinterpret_cast<__int64>(p2) - reinterpret_cast<__int64>(b2);
- SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
-
- // Ensure we're reusing free blocks
- unsigned char* b3 = b1;
- unsigned char* b4 = b2;
- PreamblePatcher::FreePreambleBlock(b1);
- PreamblePatcher::FreePreambleBlock(b2);
- b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
- SIDESTEP_EXPECT_TRUE(b1 == b3);
- b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
- SIDESTEP_EXPECT_TRUE(b2 == b4);
- PreamblePatcher::FreePreambleBlock(b1);
- PreamblePatcher::FreePreambleBlock(b2);
-
- return true;
-}
-
-bool UnitTests() {
- return TestPatchWithPreambleNearRelativeCall() &&
- TestPatchWithPreambleAbsoluteJump() &&
- TestPatchWithPreambleNearRelativeCondJump() &&
- TestPatchWithPreambleShortCondJump() &&
- TestDisassembler() && TestPatchWithLongJump() &&
- TestPatchUsingDynamicStub() && PatchThenUnpatch() &&
- AutoTestingHookTest() && AutoTestingHookInContainerTest() &&
- TestPreambleAllocation();
-}
-
-}; // namespace sidestep
-
-int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
- if (size == 0) // not even room for a \0?
- return -1; // not what C99 says to do, but what windows does
- str[size-1] = '\0';
- return _vsnprintf(str, size-1, format, ap);
-}
-
-int _tmain(int argc, _TCHAR* argv[])
-{
- bool ret = sidestep::UnitTests();
- printf("%s\n", ret ? "PASS" : "FAIL");
- return ret ? 0 : -1;
-}
-
-#pragma optimize("", on)
+ */ + +#include "config_for_unittests.h" +#include "preamble_patcher.h" +#include "mini_disassembler.h" +#pragma warning(push) +#pragma warning(disable:4553) +#include "auto_testing_hook.h" +#pragma warning(pop) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <tchar.h> + +// Turning off all optimizations for this file, since the official build's +// "Whole program optimization" seems to cause the TestPatchUsingDynamicStub +// test to crash with an access violation. We debugged this and found +// that the optimized access a register that is changed by a call to the hook +// function. +#pragma optimize("", off) + +// A convenience macro to avoid a lot of casting in the tests. +// I tried to make this a templated function, but windows complained: +// error C2782: 'sidestep::SideStepError `anonymous-namespace'::Unpatch(T,T,T *)' : template parameter 'T' is ambiguous +// could be 'int (int)' +// or 'int (__cdecl *)(int)' +// My life isn't long enough to try to figure out how to fix this. +#define UNPATCH(target_function, replacement_function, original_function_stub) \ + sidestep::PreamblePatcher::Unpatch((void*)(target_function), \ + (void*)(replacement_function), \ + (void*)(original_function)) + +namespace { + +// Function for testing - this is what we patch +// +// NOTE: Because of the way the compiler optimizes this function in +// release builds, we need to use a different input value every time we +// call it within a function, otherwise the compiler will just reuse the +// last calculated incremented value. +int __declspec(noinline) IncrementNumber(int i) { +#ifdef _M_X64 + __int64 i2 = i + 1; + return (int) i2; +#else + return i + 1; +#endif +} + +extern "C" int TooShortFunction(int); + +extern "C" int JumpShortCondFunction(int); + +extern "C" int JumpNearCondFunction(int); + +extern "C" int JumpAbsoluteFunction(int); + +extern "C" int CallNearRelativeFunction(int); + +typedef int (*IncrementingFunc)(int); +IncrementingFunc original_function = NULL; + +int HookIncrementNumber(int i) { + SIDESTEP_ASSERT(original_function != NULL); + int incremented_once = original_function(i); + return incremented_once + 1; +} + +// For the AutoTestingHook test, we can't use original_function, because +// all that is encapsulated. +// This function "increments" by 10, just to set it apart from the other +// functions. +int __declspec(noinline) AutoHookIncrementNumber(int i) { + return i + 10; +} + +}; // namespace + +namespace sidestep { + +bool TestDisassembler() { + unsigned int instruction_size = 0; + sidestep::MiniDisassembler disassembler; + void * target = reinterpret_cast<unsigned char *>(IncrementNumber); + void * new_target = PreamblePatcher::ResolveTarget(target); + if (target != new_target) + target = new_target; + + while (1) { + sidestep::InstructionType instructionType = disassembler.Disassemble( + reinterpret_cast<unsigned char *>(target) + instruction_size, + instruction_size); + if (sidestep::IT_RETURN == instructionType) { + return true; + } + } +} + +bool TestPatchWithLongJump() { + original_function = NULL; + void *p = ::VirtualAlloc(reinterpret_cast<void *>(0x0000020000000000), 4096, + MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + SIDESTEP_EXPECT_TRUE(p != NULL); + memset(p, 0xcc, 4096); + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + sidestep::PreamblePatcher::Patch(IncrementNumber, + (IncrementingFunc) p, + &original_function)); + SIDESTEP_ASSERT((*original_function)(1) == 2); + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + UNPATCH(IncrementNumber, + (IncrementingFunc)p, + original_function)); + ::VirtualFree(p, 0, MEM_RELEASE); + return true; +} + +bool TestPatchWithPreambleShortCondJump() { + original_function = NULL; + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + sidestep::PreamblePatcher::Patch(JumpShortCondFunction, + HookIncrementNumber, + &original_function)); + (*original_function)(1); + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + UNPATCH(JumpShortCondFunction, + (void*)HookIncrementNumber, + original_function)); + return true; +} + +bool TestPatchWithPreambleNearRelativeCondJump() { + original_function = NULL; + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + sidestep::PreamblePatcher::Patch(JumpNearCondFunction, + HookIncrementNumber, + &original_function)); + (*original_function)(0); + (*original_function)(1); + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + UNPATCH(JumpNearCondFunction, + HookIncrementNumber, + original_function)); + return true; +} + +bool TestPatchWithPreambleAbsoluteJump() { + original_function = NULL; + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + sidestep::PreamblePatcher::Patch(JumpAbsoluteFunction, + HookIncrementNumber, + &original_function)); + (*original_function)(0); + (*original_function)(1); + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + UNPATCH(JumpAbsoluteFunction, + HookIncrementNumber, + original_function)); + return true; +} + +bool TestPatchWithPreambleNearRelativeCall() { + original_function = NULL; + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + sidestep::PreamblePatcher::Patch( + CallNearRelativeFunction, + HookIncrementNumber, + &original_function)); + (*original_function)(0); + (*original_function)(1); + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + UNPATCH(CallNearRelativeFunction, + HookIncrementNumber, + original_function)); + return true; +} + +bool TestPatchUsingDynamicStub() { + original_function = NULL; + SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2); + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + sidestep::PreamblePatcher::Patch(IncrementNumber, + HookIncrementNumber, + &original_function)); + SIDESTEP_EXPECT_TRUE(original_function); + SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 4); + SIDESTEP_EXPECT_TRUE(original_function(3) == 4); + + // Clearbox test to see that the function has been patched. + sidestep::MiniDisassembler disassembler; + unsigned int instruction_size = 0; + SIDESTEP_EXPECT_TRUE(sidestep::IT_JUMP == disassembler.Disassemble( + reinterpret_cast<unsigned char*>(IncrementNumber), + instruction_size)); + + // Since we patched IncrementNumber, its first statement is a + // jmp to the hook function. So verify that we now can not patch + // IncrementNumber because it starts with a jump. +#if 0 + IncrementingFunc dummy = NULL; + // TODO(joi@chromium.org): restore this test once flag is added to + // disable JMP following + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_JUMP_INSTRUCTION == + sidestep::PreamblePatcher::Patch(IncrementNumber, + HookIncrementNumber, + &dummy)); + + // This test disabled because code in preamble_patcher_with_stub.cc + // asserts before returning the error code -- so there is no way + // to get an error code here, in debug build. + dummy = NULL; + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_FUNCTION_TOO_SMALL == + sidestep::PreamblePatcher::Patch(TooShortFunction, + HookIncrementNumber, + &dummy)); +#endif + + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + UNPATCH(IncrementNumber, + HookIncrementNumber, + original_function)); + return true; +} + +bool PatchThenUnpatch() { + original_function = NULL; + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + sidestep::PreamblePatcher::Patch(IncrementNumber, + HookIncrementNumber, + &original_function)); + SIDESTEP_EXPECT_TRUE(original_function); + SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 3); + SIDESTEP_EXPECT_TRUE(original_function(2) == 3); + + SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS == + UNPATCH(IncrementNumber, + HookIncrementNumber, + original_function)); + original_function = NULL; + SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4); + + return true; +} + +bool AutoTestingHookTest() { + SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2); + + // Inner scope, so we can test what happens when the AutoTestingHook + // goes out of scope + { + AutoTestingHook hook = MakeTestingHook(IncrementNumber, + AutoHookIncrementNumber); + (void) hook; + SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12); + } + SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4); + + return true; +} + +bool AutoTestingHookInContainerTest() { + SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2); + + // Inner scope, so we can test what happens when the AutoTestingHook + // goes out of scope + { + AutoTestingHookHolder hook(MakeTestingHookHolder(IncrementNumber, + AutoHookIncrementNumber)); + (void) hook; + SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12); + } + SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4); + + return true; +} + +bool TestPreambleAllocation() { + __int64 diff = 0; + void* p1 = reinterpret_cast<void*>(0x110000000); + void* p2 = reinterpret_cast<void*>(0x810000000); + unsigned char* b1 = PreamblePatcher::AllocPreambleBlockNear(p1); + SIDESTEP_EXPECT_TRUE(b1 != NULL); + diff = reinterpret_cast<__int64>(p1) - reinterpret_cast<__int64>(b1); + // Ensure blocks are within 2GB + SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN); + unsigned char* b2 = PreamblePatcher::AllocPreambleBlockNear(p2); + SIDESTEP_EXPECT_TRUE(b2 != NULL); + diff = reinterpret_cast<__int64>(p2) - reinterpret_cast<__int64>(b2); + SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN); + + // Ensure we're reusing free blocks + unsigned char* b3 = b1; + unsigned char* b4 = b2; + PreamblePatcher::FreePreambleBlock(b1); + PreamblePatcher::FreePreambleBlock(b2); + b1 = PreamblePatcher::AllocPreambleBlockNear(p1); + SIDESTEP_EXPECT_TRUE(b1 == b3); + b2 = PreamblePatcher::AllocPreambleBlockNear(p2); + SIDESTEP_EXPECT_TRUE(b2 == b4); + PreamblePatcher::FreePreambleBlock(b1); + PreamblePatcher::FreePreambleBlock(b2); + + return true; +} + +bool UnitTests() { + return TestPatchWithPreambleNearRelativeCall() && + TestPatchWithPreambleAbsoluteJump() && + TestPatchWithPreambleNearRelativeCondJump() && + TestPatchWithPreambleShortCondJump() && + TestDisassembler() && TestPatchWithLongJump() && + TestPatchUsingDynamicStub() && PatchThenUnpatch() && + AutoTestingHookTest() && AutoTestingHookInContainerTest() && + TestPreambleAllocation(); +} + +}; // namespace sidestep + +int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) { + if (size == 0) // not even room for a \0? + return -1; // not what C99 says to do, but what windows does + str[size-1] = '\0'; + return _vsnprintf(str, size-1, format, ap); +} + +int _tmain(int argc, _TCHAR* argv[]) +{ + bool ret = sidestep::UnitTests(); + printf("%s\n", ret ? "PASS" : "FAIL"); + return ret ? 0 : -1; +} + +#pragma optimize("", on) diff --git a/src/windows/shortproc.asm b/src/windows/shortproc.asm index 757fd43..7e8e3d7 100644 --- a/src/windows/shortproc.asm +++ b/src/windows/shortproc.asm @@ -32,6 +32,8 @@ ; ; Unit tests for PreamblePatcher
+.MODEL small
+
.CODE
TooShortFunction PROC
diff --git a/vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj b/vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj new file mode 100755 index 0000000..3c84f8f --- /dev/null +++ b/vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="preamble_patcher_test"
+ ProjectGUID="{5765198D-5305-4AB0-9A21-A0CD8201EB2A}"
+ 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"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/preamble_patcher_test.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/preamble_patcher_test.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"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/preamble_patcher_test.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="{3FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher_test.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\shortproc.asm">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="ml64 /Fo"$(OutDir)\$(InputName).obj" /c /Cx /coff "$(InputPath)""
+ Outputs="$(OutDir)\$(InputName).obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="ml64 /Fo"$(OutDir)\$(InputName).obj" /c /Cx /coff "$(InputPath)""
+ Outputs="$(OutDir)\$(InputName).obj"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{33995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\mini_disassembler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\auto_testing_hook.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\basictypes.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
|